2 Module : Gargantext.Database.Schema.NodeNgrams
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 NodeNgrams register Context of Ngrams (named Cgrams then)
15 {-# OPTIONS_GHC -fno-warn-orphans #-}
17 {-# LANGUAGE Arrows #-}
18 {-# LANGUAGE FlexibleContexts #-}
19 {-# LANGUAGE FlexibleInstances #-}
20 {-# LANGUAGE FunctionalDependencies #-}
21 {-# LANGUAGE QuasiQuotes #-}
22 {-# LANGUAGE MultiParamTypeClasses #-}
23 {-# LANGUAGE NoImplicitPrelude #-}
24 {-# LANGUAGE OverloadedStrings #-}
25 {-# LANGUAGE RankNTypes #-}
26 {-# LANGUAGE TemplateHaskell #-}
28 module Gargantext.Database.Schema.NodeNgrams where
31 import qualified Data.Map as Map
32 import qualified Data.List as List
33 import Data.List.Extra (nubOrd)
34 import Data.Text (Text)
35 import qualified Database.PostgreSQL.Simple as PGS (Query, Only(..))
36 import Database.PostgreSQL.Simple.Types (Values(..), QualifiedIdentifier(..))
37 import Database.PostgreSQL.Simple.FromRow (fromRow, field)
38 import Database.PostgreSQL.Simple.ToField (toField)
39 import Database.PostgreSQL.Simple (FromRow)
40 import Database.PostgreSQL.Simple.SqlQQ (sql)
41 -- import Control.Lens.TH (makeLenses)
42 import Data.Maybe (Maybe, fromMaybe)
43 import Gargantext.Core.Types
44 import Gargantext.Database.Utils
45 import Gargantext.Database.Schema.Ngrams (NgramsType, ngramsTypeId, fromNgramsTypeId)
46 import Gargantext.Prelude
48 type NodeNgramsId = Int
50 data NodeNgramsPoly id
59 = NodeNgrams { _nng_id :: !id
60 , _nng_node_id :: !node_id'
61 , _nng_node_subtype :: !node_subtype
62 , _nng_ngrams_id :: !ngrams_id
63 , _nng_ngrams_type :: !ngrams_type
64 , _nng_ngrams_field :: !ngrams_field
65 , _nng_ngrams_tag :: !ngrams_tag
66 , _nng_ngrams_class :: !ngrams_class
67 , _nng_ngrams_weight :: !weight
68 } deriving (Show, Eq, Ord)
72 type NodeNgramsWrite = NodeNgramsPoly (Maybe (Column (PGInt4)))
74 (Maybe (Column (PGInt4)))
76 (Maybe (Column (PGInt4)))
77 (Maybe (Column (PGInt4)))
78 (Maybe (Column (PGInt4)))
79 (Maybe (Column (PGInt4)))
80 (Maybe (Column (PGFloat8)))
82 type NodeNodeRead = NodeNgramsPoly (Column PGInt4)
92 type NodeNgramsReadNull = NodeNgramsPoly (Column (Nullable PGInt4))
93 (Column (Nullable PGInt4))
94 (Column (Nullable PGInt4))
95 (Column (Nullable PGInt4))
97 (Column (Nullable PGInt4))
98 (Column (Nullable PGInt4))
99 (Column (Nullable PGInt4))
100 (Column (Nullable PGInt4))
101 (Column (Nullable PGFloat8))
104 type NgramsField = Int
106 type NgramsClass = Int
107 type NgramsText = Text
109 -- Example of list Ngrams
110 -- type ListNgrams = NodeNgramsPoly (Maybe Int) ListType Text
113 NodeNgramsPoly (Maybe Int) NodeId ListType NgramsText
114 NgramsType (Maybe NgramsField) (Maybe NgramsTag) (Maybe NgramsClass)
117 data Returning = Returning { re_type :: !(Maybe NgramsType)
119 , re_ngrams_id :: !Int
123 instance FromRow Returning where
124 fromRow = Returning <$> (fromNgramsTypeId <$> field) <*> field <*> field
126 getCgramsId :: Map NgramsType (Map Text Int) -> NgramsType -> Text -> Maybe Int
127 getCgramsId mapId nt t = case Map.lookup nt mapId of
129 Just mapId' -> Map.lookup t mapId'
132 -- insertDb :: ListId -> Map NgramsType [NgramsElement] -> Cmd err [Result]
133 listInsertDb :: Show a => ListId
134 -> (ListId -> a -> [NodeNgramsW])
136 -- -> Cmd err [Returning]
137 -> Cmd err (Map NgramsType (Map Text Int))
138 listInsertDb l f ngs = Map.map Map.fromList
139 <$> Map.fromListWith (<>)
140 <$> List.map (\(Returning t tx id) -> (fromJust t, [(tx, id)]))
141 <$> List.filter (\(Returning t _ _) -> isJust t)
142 <$> insertNodeNgrams (f l ngs)
144 -- TODO optimize with size of ngrams
145 insertNodeNgrams :: [NodeNgramsW] -> Cmd err [Returning]
146 insertNodeNgrams nns = runPGSQuery query (PGS.Only $ Values fields nns')
148 fields = map (\t-> QualifiedIdentifier Nothing t) ["int4","int4","text","int4"
149 ,"int4","int4","int4","int4"
151 -- nns' :: [(Int, ListTypeId, NgramsText, NgramsTypeId ,NgramsField, NgramsTag, NgramsClass, Double)]
152 nns' = map (\(NodeNgrams _id (NodeId node_id'') node_subtype ngrams_terms ngrams_type ngrams_field ngrams_tag ngrams_class weight)
153 -> [ toField node_id''
154 , toField $ listTypeId node_subtype
155 , toField $ ngrams_terms
156 , toField $ ngramsTypeId ngrams_type
157 , toField $ fromMaybe 0 ngrams_field
158 , toField $ fromMaybe 0 ngrams_tag
159 , toField $ fromMaybe 0 ngrams_class
166 WITH input(node_id, node_subtype, ngrams_terms, ngrams_type, ngrams_field, ngrams_tag, ngrams_class, weight) AS (?),
167 return(id, ngrams_type, ngrams_id) AS (
168 INSERT INTO node_ngrams (node_id, node_subtype, ngrams_id, ngrams_type, ngrams_field, ngrams_tag, ngrams_class, weight)
169 SELECT i.node_id, i.node_subtype, ng.id, i.ngrams_type, i.ngrams_field, i.ngrams_tag, i.ngrams_class, i.weight FROM input as i
170 INNER JOIN ngrams as ng ON ng.terms = i.ngrams_terms
171 ON CONFLICT(node_id, node_subtype, ngrams_id) DO NOTHING
172 -- DO UPDATE SET node_subtype = excluded.node_subtype, ngrams_type = excluded.ngrams_type, ngrams_field = excluded.ngrams_field, ngrams_tag = excluded.ngrams_tag, ngrams_class = excluded.ngrams_class, weight = excluded.weight
173 RETURNING id, ngrams_type, ngrams_id
175 SELECT return.ngrams_type, ng.terms, return.id FROM return
176 INNER JOIN ngrams ng ON return.ngrams_id = ng.id;