1 {-| Module : Gargantext.Database.Select.Table.NodeNode
3 Copyright : (c) CNRS, 2017-Present
4 License : AGPL + CECILL v3
5 Maintainer : team@gargantext.org
6 Stability : experimental
9 Here is a longer description of this module, containing some
10 commentary with @some markup@.
13 {-# OPTIONS_GHC -fno-warn-orphans #-}
15 {-# LANGUAGE Arrows #-}
16 {-# LANGUAGE FunctionalDependencies #-}
17 {-# LANGUAGE QuasiQuotes #-}
18 {-# LANGUAGE TemplateHaskell #-}
20 module Gargantext.Database.Query.Table.NodeNode
21 ( module Gargantext.Database.Schema.NodeNode
35 import Control.Arrow (returnA)
36 import Control.Lens ((^.), view)
37 import Data.Text (Text, splitOn)
38 import Data.Maybe (catMaybes)
39 import Database.PostgreSQL.Simple.SqlQQ (sql)
40 import Database.PostgreSQL.Simple.Types (Values(..), QualifiedIdentifier(..))
41 import Gargantext.Core
42 import Gargantext.Core.Types
43 import Gargantext.Database.Admin.Types.Hyperdata
44 import Gargantext.Database.Prelude
45 import Gargantext.Database.Schema.Node
46 import Gargantext.Database.Schema.NodeNode
47 import Gargantext.Prelude
49 import qualified Database.PostgreSQL.Simple as PGS
50 import qualified Opaleye as O
52 queryNodeNodeTable :: Select NodeNodeRead
53 queryNodeNodeTable = selectTable nodeNodeTable
55 -- | not optimized (get all ngrams without filters)
56 _nodesNodes :: Cmd err [NodeNode]
57 _nodesNodes = runOpaQuery queryNodeNodeTable
59 ------------------------------------------------------------------------
60 -- | Basic NodeNode tools
61 getNodeNode :: NodeId -> Cmd err [NodeNode]
62 getNodeNode n = runOpaQuery (selectNodeNode $ pgNodeId n)
64 selectNodeNode :: Column SqlInt4 -> Select NodeNodeRead
65 selectNodeNode n' = proc () -> do
66 ns <- queryNodeNodeTable -< ()
67 restrict -< _nn_node1_id ns .== n'
70 ------------------------------------------------------------------------
71 -- TODO (refactor with Children)
73 getNodeNodeWith :: NodeId -> proxy a -> Maybe NodeType -> Cmd err [a]
74 getNodeNodeWith pId _ maybeNodeType = runOpaQuery query
76 query = selectChildren pId maybeNodeType
78 selectChildren :: ParentId
81 selectChildren parentId maybeNodeType = proc () -> do
82 row@(Node nId typeName _ parent_id _ _ _) <- queryNodeTable -< ()
83 (NodeNode _ n1id n2id _ _) <- queryNodeNodeTable -< ()
85 let nodeType = maybe 0 toDBid maybeNodeType
86 restrict -< typeName .== sqlInt4 nodeType
88 restrict -< (.||) (parent_id .== (pgNodeId parentId))
89 ( (.&&) (n1id .== pgNodeId parentId)
94 ------------------------------------------------------------------------
95 insertNodeNode :: [NodeNode] -> Cmd err Int
96 insertNodeNode ns = mkCmd $ \conn -> fromIntegral <$> (runInsert_ conn
97 $ Insert nodeNodeTable ns' rCount (Just DoNothing))
99 ns' :: [NodeNodeWrite]
100 ns' = map (\(NodeNode n1 n2 x y)
101 -> NodeNode (pgNodeId n1)
109 ------------------------------------------------------------------------
110 type Node1_Id = NodeId
111 type Node2_Id = NodeId
113 deleteNodeNode :: Node1_Id -> Node2_Id -> Cmd err Int
114 deleteNodeNode n1 n2 = mkCmd $ \conn ->
115 fromIntegral <$> runDelete_ conn
116 (Delete nodeNodeTable
117 (\(NodeNode n1_id n2_id _ _) -> n1_id .== pgNodeId n1
118 .&& n2_id .== pgNodeId n2
123 ------------------------------------------------------------------------
124 -- | Favorite management
125 _nodeNodeCategory :: CorpusId -> DocId -> Int -> Cmd err [Int]
126 _nodeNodeCategory cId dId c = map (\(PGS.Only a) -> a) <$> runPGSQuery favQuery (c,cId,dId)
128 favQuery :: PGS.Query
129 favQuery = [sql|UPDATE nodes_nodes SET category = ?
130 WHERE node1_id = ? AND node2_id = ?
134 nodeNodesCategory :: [(CorpusId, DocId, Int)] -> Cmd err [Int]
135 nodeNodesCategory inputData = map (\(PGS.Only a) -> a)
136 <$> runPGSQuery catQuery (PGS.Only $ Values fields inputData)
138 fields = map (\t-> QualifiedIdentifier Nothing t) ["int4","int4","int4"]
139 catQuery :: PGS.Query
140 catQuery = [sql| UPDATE nodes_nodes as nn0
141 SET category = nn1.category
142 FROM (?) as nn1(node1_id,node2_id,category)
143 WHERE nn0.node1_id = nn1.node1_id
144 AND nn0.node2_id = nn1.node2_id
145 RETURNING nn1.node2_id
148 ------------------------------------------------------------------------
149 -- | Score management
150 _nodeNodeScore :: CorpusId -> DocId -> Int -> Cmd err [Int]
151 _nodeNodeScore cId dId c = map (\(PGS.Only a) -> a) <$> runPGSQuery scoreQuery (c,cId,dId)
153 scoreQuery :: PGS.Query
154 scoreQuery = [sql|UPDATE nodes_nodes SET score = ?
155 WHERE node1_id = ? AND node2_id = ?
159 nodeNodesScore :: [(CorpusId, DocId, Int)] -> Cmd err [Int]
160 nodeNodesScore inputData = map (\(PGS.Only a) -> a)
161 <$> runPGSQuery catScore (PGS.Only $ Values fields inputData)
163 fields = map (\t-> QualifiedIdentifier Nothing t) ["int4","int4","int4"]
164 catScore :: PGS.Query
165 catScore = [sql| UPDATE nodes_nodes as nn0
166 SET score = nn1.score
167 FROM (?) as nn1(node1_id, node2_id, score)
168 WHERE nn0.node1_id = nn1.node1_id
169 AND nn0.node2_id = nn1.node2_id
170 RETURNING nn1.node2_id
173 ------------------------------------------------------------------------
174 _selectCountDocs :: HasDBid NodeType => CorpusId -> Cmd err Int
175 _selectCountDocs cId = runCountOpaQuery (queryCountDocs cId)
177 queryCountDocs cId' = proc () -> do
178 (n, nn) <- joinInCorpus -< ()
179 restrict -< nn^.nn_node1_id .== (toNullable $ pgNodeId cId')
180 restrict -< nn^.nn_category .>= (toNullable $ sqlInt4 1)
181 restrict -< n^.node_typename .== (sqlInt4 $ toDBid NodeDocument)
187 -- | TODO use UTCTime fast
188 selectDocsDates :: HasDBid NodeType => CorpusId -> Cmd err [Text]
189 selectDocsDates cId = map (head' "selectDocsDates" . splitOn "-")
191 <$> map (view hd_publication_date)
194 selectDocs :: HasDBid NodeType => CorpusId -> Cmd err [HyperdataDocument]
195 selectDocs cId = runOpaQuery (queryDocs cId)
197 queryDocs :: HasDBid NodeType => CorpusId -> O.Select (Column SqlJsonb)
198 queryDocs cId = proc () -> do
199 (n, nn) <- joinInCorpus -< ()
200 restrict -< nn^.nn_node1_id .== (toNullable $ pgNodeId cId)
201 restrict -< nn^.nn_category .>= (toNullable $ sqlInt4 1)
202 restrict -< n^.node_typename .== (sqlInt4 $ toDBid NodeDocument)
203 returnA -< view (node_hyperdata) n
205 selectDocNodes :: HasDBid NodeType =>CorpusId -> Cmd err [Node HyperdataDocument]
206 selectDocNodes cId = runOpaQuery (queryDocNodes cId)
208 queryDocNodes :: HasDBid NodeType =>CorpusId -> O.Select NodeRead
209 queryDocNodes cId = proc () -> do
210 (n, nn) <- joinInCorpus -< ()
211 restrict -< nn^.nn_node1_id .== (toNullable $ pgNodeId cId)
212 restrict -< nn^.nn_category .>= (toNullable $ sqlInt4 1)
213 restrict -< n^.node_typename .== (sqlInt4 $ toDBid NodeDocument)
216 joinInCorpus :: O.Select (NodeRead, NodeNodeReadNull)
217 joinInCorpus = leftJoin queryNodeTable queryNodeNodeTable cond
219 cond :: (NodeRead, NodeNodeRead) -> Column SqlBool
220 cond (n, nn) = nn^.nn_node2_id .== (view node_id n)
222 _joinOn1 :: O.Select (NodeRead, NodeNodeReadNull)
223 _joinOn1 = leftJoin queryNodeTable queryNodeNodeTable cond
225 cond :: (NodeRead, NodeNodeRead) -> Column SqlBool
226 cond (n, nn) = nn^.nn_node1_id .== n^.node_id
229 ------------------------------------------------------------------------
230 selectPublicNodes :: HasDBid NodeType => (Hyperdata a, DefaultFromField SqlJsonb a)
231 => Cmd err [(Node a, Maybe Int)]
232 selectPublicNodes = runOpaQuery (queryWithType NodeFolderPublic)
234 queryWithType :: HasDBid NodeType
236 -> O.Select (NodeRead, Column (Nullable SqlInt4))
237 queryWithType nt = proc () -> do
238 (n, nn) <- node_NodeNode -< ()
239 restrict -< n^.node_typename .== (sqlInt4 $ toDBid nt)
240 returnA -< (n, nn^.nn_node2_id)
242 node_NodeNode :: O.Select (NodeRead, NodeNodeReadNull)
243 node_NodeNode = leftJoin queryNodeTable queryNodeNodeTable cond
245 cond :: (NodeRead, NodeNodeRead) -> Column SqlBool
246 cond (n, nn) = nn^.nn_node1_id .== n^.node_id