2 Module : Gargantext.Database.Query.Table.NodeContext
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 Here is a longer description of this module, containing some
11 commentary with @some markup@.
14 {-# OPTIONS_GHC -fno-warn-orphans #-}
16 {-# LANGUAGE Arrows #-}
17 {-# LANGUAGE FunctionalDependencies #-}
18 {-# LANGUAGE QuasiQuotes #-}
19 {-# LANGUAGE TemplateHaskell #-}
21 module Gargantext.Database.Query.Table.NodeContext
22 ( module Gargantext.Database.Schema.NodeContext
23 , queryNodeContextTable
27 , nodeContextsCategory
31 , updateNodeContextCategory
32 , getContextsForNgrams
35 , selectPublicContexts
40 import Control.Arrow (returnA)
41 import Control.Lens (view, (^.))
42 import Data.Maybe (catMaybes)
43 import Data.Time (UTCTime)
44 import Data.Text (Text, splitOn)
45 import Database.PostgreSQL.Simple.SqlQQ (sql)
46 import Database.PostgreSQL.Simple.Types (Values(..), QualifiedIdentifier(..))
48 import qualified Database.PostgreSQL.Simple as PGS (In(..), Query, Only(..))
49 import qualified Opaleye as O
51 import Gargantext.Core
52 import Gargantext.Core.Types
53 -- import Gargantext.Core.Types.Search (HyperdataRow(..), toHyperdataRow)
54 import Gargantext.Database.Admin.Types.Hyperdata
55 import Gargantext.Database.Query.Table.Node.Error (HasNodeError, NodeError(DoesNotExist), nodeError)
56 import Gargantext.Database.Prelude
57 import Gargantext.Prelude.Crypto.Hash (Hash)
58 import Gargantext.Database.Schema.Context
59 import Gargantext.Database.Schema.Node
60 import Gargantext.Database.Schema.NodeContext
61 import Gargantext.Prelude
63 queryNodeContextTable :: Select NodeContextRead
64 queryNodeContextTable = selectTable nodeContextTable
66 -- | not optimized (get all ngrams without filters)
67 _nodesContexts :: Cmd err [NodeContext]
68 _nodesContexts = runOpaQuery queryNodeContextTable
70 ------------------------------------------------------------------------
71 -- | Basic NodeContext tools
72 getNodeContexts :: NodeId -> Cmd err [NodeContext]
73 getNodeContexts n = runOpaQuery (selectNodeContexts $ pgNodeId n)
75 selectNodeContexts :: Column SqlInt4 -> Select NodeContextRead
76 selectNodeContexts n' = proc () -> do
77 ns <- queryNodeContextTable -< ()
78 restrict -< _nc_node_id ns .== n'
82 getNodeContext :: HasNodeError err => ContextId -> NodeId -> Cmd err NodeContext
83 getNodeContext c n = do
84 maybeNodeContext <- headMay <$> runOpaQuery (selectNodeContext (pgNodeId c) (pgNodeId n))
85 case maybeNodeContext of
86 Nothing -> nodeError (DoesNotExist c)
89 selectNodeContext :: Column SqlInt4 -> Column SqlInt4 -> Select NodeContextRead
90 selectNodeContext c' n' = proc () -> do
91 ns <- queryNodeContextTable -< ()
92 restrict -< _nc_context_id ns .== c'
93 restrict -< _nc_node_id ns .== n'
96 updateNodeContextCategory :: ContextId -> NodeId -> Int -> Cmd err Int64
97 updateNodeContextCategory cId nId cat = do
98 execPGSQuery upScore (cat, cId, nId)
101 upScore = [sql| UPDATE nodes_contexts
106 getContextsForNgrams :: HasNodeError err => NodeId -> [Int] -> Cmd err [(NodeId, Maybe Hash, NodeTypeId, UserId, Maybe ParentId, ContextTitle, UTCTime, HyperdataDocument)]
107 getContextsForNgrams cId ngramsIds = runPGSQuery query (cId, PGS.In ngramsIds)
110 query = [sql| SELECT contexts.id, hash_id, typename, user_id, parent_id, name, date, hyperdata
112 JOIN context_node_ngrams ON contexts.id = context_node_ngrams.context_id
113 JOIN nodes_contexts ON contexts.id = nodes_contexts.context_id
114 WHERE nodes_contexts.node_id = ?
115 AND context_node_ngrams.ngrams_id IN ? |]
117 ------------------------------------------------------------------------
118 insertNodeContext :: [NodeContext] -> Cmd err Int
119 insertNodeContext ns = mkCmd $ \conn -> fromIntegral <$> (runInsert_ conn
120 $ Insert nodeContextTable ns' rCount (Just DoNothing))
122 ns' :: [NodeContextWrite]
123 ns' = map (\(NodeContext i n c x y)
124 -> NodeContext (sqlInt4 <$> i)
132 ------------------------------------------------------------------------
133 type Node_Id = NodeId
134 type Context_Id = NodeId
136 deleteNodeContext :: Node_Id -> Context_Id -> Cmd err Int
137 deleteNodeContext n c = mkCmd $ \conn ->
138 fromIntegral <$> runDelete_ conn
139 (Delete nodeContextTable
140 (\(NodeContext _ n_id c_id _ _) -> n_id .== pgNodeId n
141 .&& c_id .== pgNodeId c
146 ------------------------------------------------------------------------
147 -- | Favorite management
148 nodeContextsCategory :: [(CorpusId, DocId, Int)] -> Cmd err [Int]
149 nodeContextsCategory inputData = map (\(PGS.Only a) -> a)
150 <$> runPGSQuery catSelect (PGS.Only $ Values fields inputData)
152 fields = map (\t-> QualifiedIdentifier Nothing t) ["int4","int4","int4"]
153 catSelect :: PGS.Query
154 catSelect = [sql| UPDATE nodes_contexts as nn0
155 SET category = nn1.category
156 FROM (?) as nn1(node_id,context_id,category)
157 WHERE nn0.node_id = nn1.node_id
158 AND nn0.context_id = nn1.context_id
159 RETURNING nn1.node_id
162 ------------------------------------------------------------------------
163 -- | Score management
164 nodeContextsScore :: [(CorpusId, DocId, Int)] -> Cmd err [Int]
165 nodeContextsScore inputData = map (\(PGS.Only a) -> a)
166 <$> runPGSQuery catScore (PGS.Only $ Values fields inputData)
168 fields = map (\t-> QualifiedIdentifier Nothing t) ["int4","int4","int4"]
169 catScore :: PGS.Query
170 catScore = [sql| UPDATE nodes_contexts as nn0
171 SET score = nn1.score
172 FROM (?) as nn1(node_id, context_id, score)
173 WHERE nn0.node_id = nn1.node_id
174 AND nn0.context_id = nn1.context_id
175 RETURNING nn1.context_id
179 ------------------------------------------------------------------------
180 selectCountDocs :: HasDBid NodeType => CorpusId -> Cmd err Int
181 selectCountDocs cId = runCountOpaQuery (queryCountDocs cId)
183 queryCountDocs cId' = proc () -> do
184 (c, nc) <- joinInCorpus -< ()
185 restrict -< nc^.nc_node_id .== (toNullable $ pgNodeId cId')
186 restrict -< nc^.nc_category .>= (toNullable $ sqlInt4 1)
187 restrict -< c^.context_typename .== (sqlInt4 $ toDBid NodeDocument)
191 -- | TODO use UTCTime fast
192 selectDocsDates :: HasDBid NodeType => CorpusId -> Cmd err [Text]
193 selectDocsDates cId = map (head' "selectDocsDates" . splitOn "-")
195 <$> map (view hd_publication_date)
198 selectDocs :: HasDBid NodeType => CorpusId -> Cmd err [HyperdataDocument]
199 selectDocs cId = runOpaQuery (queryDocs cId)
201 queryDocs :: HasDBid NodeType => CorpusId -> O.Select (Column SqlJsonb)
202 queryDocs cId = proc () -> do
203 (c, nn) <- joinInCorpus -< ()
204 restrict -< nn^.nc_node_id .== (toNullable $ pgNodeId cId)
205 restrict -< nn^.nc_category .>= (toNullable $ sqlInt4 1)
206 restrict -< c^.context_typename .== (sqlInt4 $ toDBid NodeDocument)
207 returnA -< view (context_hyperdata) c
209 selectDocNodes :: HasDBid NodeType => CorpusId -> Cmd err [Context HyperdataDocument]
210 selectDocNodes cId = runOpaQuery (queryDocNodes cId)
212 queryDocNodes :: HasDBid NodeType => CorpusId -> O.Select ContextRead
213 queryDocNodes cId = proc () -> do
214 (c, nc) <- joinInCorpus -< ()
215 restrict -< nc^.nc_node_id .== (toNullable $ pgNodeId cId)
216 restrict -< nc^.nc_category .>= (toNullable $ sqlInt4 1)
217 restrict -< c^.context_typename .== (sqlInt4 $ toDBid NodeDocument)
220 joinInCorpus :: O.Select (ContextRead, NodeContextReadNull)
221 joinInCorpus = leftJoin queryContextTable queryNodeContextTable cond
223 cond :: (ContextRead, NodeContextRead) -> Column SqlBool
224 cond (c, nc) = c^.context_id .== nc^.nc_context_id
227 joinOn1 :: O.Select (NodeRead, NodeContextReadNull)
228 joinOn1 = leftJoin queryNodeTable queryNodeContextTable cond
230 cond :: (NodeRead, NodeContextRead) -> Column SqlBool
231 cond (n, nc) = nc^.nc_node_id .== n^.node_id
234 ------------------------------------------------------------------------
235 selectPublicContexts :: HasDBid NodeType => (Hyperdata a, DefaultFromField SqlJsonb a)
236 => Cmd err [(Node a, Maybe Int)]
237 selectPublicContexts = runOpaQuery (queryWithType NodeFolderPublic)
239 queryWithType :: HasDBid NodeType =>NodeType -> O.Select (NodeRead, Column (Nullable SqlInt4))
240 queryWithType nt = proc () -> do
241 (n, nc) <- joinOn1 -< ()
242 restrict -< n^.node_typename .== (sqlInt4 $ toDBid nt)
243 returnA -< (n, nc^.nc_context_id)