2 Module : Gargantext.Database.Facet
3 Description : Main requests of Node to the database
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
11 {-# OPTIONS_GHC -fno-warn-orphans #-}
12 {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
14 {-# LANGUAGE Arrows #-}
15 {-# LANGUAGE DeriveGeneric #-}
16 {-# LANGUAGE TemplateHaskell #-}
17 {-# LANGUAGE FlexibleContexts #-}
18 {-# LANGUAGE FlexibleInstances #-}
19 {-# LANGUAGE MultiParamTypeClasses #-}
20 {-# LANGUAGE FunctionalDependencies #-}
21 {-# LANGUAGE NoMonomorphismRestriction #-}
23 ------------------------------------------------------------------------
24 module Gargantext.Database.Facet
26 ------------------------------------------------------------------------
28 import Prelude hiding (null, id, map, sum, not)
29 import GHC.Generics (Generic)
31 -- import Data.Aeson (Value)
32 import Control.Arrow (returnA)
33 import Control.Lens.TH (makeLensesWith, abbreviatedFields)
35 import Data.Aeson.TH (deriveJSON)
36 import Data.Maybe (Maybe)
37 import Data.Profunctor.Product.Default (Default)
38 import Data.Profunctor.Product.TH (makeAdaptorAndInstance)
39 import Data.Time (UTCTime)
40 import Data.Time.Segment (jour)
43 import Database.PostgreSQL.Simple (Connection)
45 import Opaleye.Internal.Join (NullMaker)
46 import qualified Opaleye.Internal.Unpackspec()
48 import Test.QuickCheck.Arbitrary
49 import Test.QuickCheck (elements)
51 import Gargantext.Types
52 import Gargantext.Types.Node (NodeType)
53 import Gargantext.Database.NodeNode
54 import Gargantext.Database.NodeNodeNgram
55 import Gargantext.Database.Node
56 import Gargantext.Database.Queries
57 import Gargantext.Utils.Prefix (unPrefix)
58 -- import Gargantext.Database.NodeNgram
60 ------------------------------------------------------------------------
63 -- data Facet = FacetDoc | FacetSources | FacetAuthors | FacetTerms
64 -- deriving (Show, Generic)
65 --instance FromJSON Facet
66 --instance ToJSON Facet
68 type FacetDoc = Facet NodeId UTCTime HyperdataDocument Bool Int
69 type FacetSources = FacetDoc
70 type FacetAuthors = FacetDoc
71 type FacetTerms = FacetDoc
75 data Facet id created hyperdata favorite ngramCount =
76 FacetDoc { facetDoc_id :: id
77 , facetDoc_created :: created
78 , facetDoc_hyperdata :: hyperdata
79 , facetDoc_favorite :: favorite
80 , facetDoc_ngramCount :: ngramCount
81 } deriving (Show, Generic)
85 $(deriveJSON (unPrefix "facetDoc_") ''Facet)
87 -- | Documentation instance
88 instance ToSchema FacetDoc
90 -- | Mock and Quickcheck instances
92 instance Arbitrary FacetDoc where
93 arbitrary = elements [ FacetDoc id' (jour year 01 01) hp fav ngramCount
95 , year <- [1990..2000]
96 , hp <- hyperdataDocuments
97 , fav <- [True, False]
98 , ngramCount <- [3..100]
101 -- Facets / Views for the Front End
102 -- | Database instances
103 $(makeAdaptorAndInstance "pFacetDoc" ''Facet)
104 $(makeLensesWith abbreviatedFields ''Facet)
106 type FacetDocRead = Facet (Column PGInt4 )
107 (Column PGTimestamptz)
112 -----------------------------------------------------------------------
114 data FacetChart = FacetChart { facetChart_time :: UTCTime'
115 , facetChart_count :: Double
117 deriving (Show, Generic)
118 $(deriveJSON (unPrefix "facetChart_") ''FacetChart)
119 instance ToSchema FacetChart
121 instance Arbitrary FacetChart where
122 arbitrary = FacetChart <$> arbitrary <*> arbitrary
124 -----------------------------------------------------------------------
127 getDocFacet :: Connection -> Int -> Maybe NodeType
128 -> Maybe Offset -> Maybe Limit
130 getDocFacet conn parentId nodeType maybeOffset maybeLimit =
131 runQuery conn $ selectDocFacet parentId nodeType maybeOffset maybeLimit
133 selectDocFacet :: ParentId -> Maybe NodeType
134 -> Maybe Offset -> Maybe Limit
135 -> Query FacetDocRead
136 selectDocFacet parentId maybeNodeType maybeOffset maybeLimit =
137 limit' maybeLimit $ offset' maybeOffset
138 $ orderBy (asc facetDoc_created)
139 $ selectDocFacet' parentId maybeNodeType
142 -- | Left join to the favorites
143 nodeNodeLeftJoin :: Query (NodeRead, NodeNodeReadNull)
144 nodeNodeLeftJoin = leftJoin queryNodeTable queryNodeNodeTable (eqNode)
146 eqNode (Node n1 _ _ _ _ _ _, NodeNode _ n2 _) = ((.==) n1 n2)
149 nodeNodeLeftJoin' :: (Column (Nullable PGInt4))
150 -> Query (NodeRead, NodeNodeReadNull)
151 nodeNodeLeftJoin' nId = leftJoin queryNodeTable queryNodeNodeTable (eqNode nId)
153 eqNode n (Node n1 _ _ _ _ _ _, NodeNode n1' n2 _)
154 = foldl (.&&) (pgBool True) [ ((.==) n1 n2)
158 nodeNodeLeftJoin'' :: Query (NodeRead, NodeRead, NodeNodeRead)
159 nodeNodeLeftJoin'' = join3 queryNodeTable queryNodeTable queryNodeNodeTable eqNode
161 eqNode (Node n1 _ _ _ _ _ _, Node n2 _ _ _ _ _ _, NodeNode n1' n2' _)
162 = foldl (.&&) (pgBool True) [ ((.==) n2 n2')
163 , ((.==) (toNullable n1) n1')
166 -- | Left join to the ngram count per document
167 nodeNodeNgramLeftJoin :: Query (NodeRead, NodeNodeNgramReadNull)
168 nodeNodeNgramLeftJoin = leftJoin queryNodeTable queryNodeNodeNgramTable (eqNode)
170 eqNode (Node n1 _ _ _ _ _ _, NodeNodeNgram n1' _ _ _) = ((.==) n1 n1')
173 nodeNodeNgramLeftJoin' :: Column (Nullable PGInt4)
174 -> Query (NodeRead, NodeNodeNgramReadNull)
175 nodeNodeNgramLeftJoin' nId = leftJoin queryNodeTable queryNodeNodeNgramTable (eqNode nId)
177 eqNode nId' (Node n1 _ _ _ _ _ _, NodeNodeNgram n1' n2 _ _)
178 = (.&&) ((.==) n1 n1')
179 ((.==) nId' (toNullable n2))
182 leftJoin3 :: (Default NullMaker (columnsL1, nullableColumnsR) nullableColumnsR1,
183 Default NullMaker columnsR nullableColumnsR,
184 Default Unpackspec columnsR columnsR,
185 Default Unpackspec nullableColumnsR nullableColumnsR,
186 Default Unpackspec columnsL1 columnsL1,
187 Default Unpackspec columnsL columnsL) =>
188 Query columnsL1 -> Query columnsR -> Query columnsL
189 -> ((columnsL1, columnsR) -> Column PGBool)
190 -> ((columnsL, (columnsL1, nullableColumnsR)) -> Column PGBool)
191 -> Query (columnsL, nullableColumnsR1)
192 leftJoin3 q1 q2 q3 cond12 cond23 = leftJoin q3 (leftJoin q1 q2 cond12) cond23
195 leftJoin3' :: Query (NodeRead, (NodeReadNull, NodeNodeNgramReadNull))
196 leftJoin3' = leftJoin3 queryNodeTable queryNodeNodeNgramTable queryNodeTable cond12 cond23
198 cond12 (Node occId _ _ _ _ _ _, NodeNodeNgram occId' _ _ _)
201 cond23 :: (NodeRead, (NodeRead, NodeNodeNgramReadNull)) -> Column PGBool
202 cond23 (Node docId _ _ _ _ _ _, (Node _ _ _ _ _ _ _, NodeNodeNgram _ docId' _ _))
203 = (.||) ((.==) (toNullable docId) docId') (isNull docId')
206 leftJoin3''' :: Query (NodeRead, (NodeNodeReadNull, NodeReadNull))
207 leftJoin3''' = leftJoin3 queryNodeNodeTable queryNodeTable queryNodeTable cond12 cond23
209 cond12 (NodeNode favId _ _, Node favId' _ _ _ _ _ _)
210 = (.||) ((.==) favId (toNullable favId')) (isNull $ toNullable favId)
212 cond23 :: (NodeRead, (NodeNodeRead, NodeReadNull)) -> Column PGBool
213 cond23 (Node nId _ _ _ _ _ _, (NodeNode _ nId' _, Node _ _ _ _ _ _ _ ))
214 = ((.==) (nId) (nId'))
217 -- getDocTest :: Connection -> IO [FacetDoc]
218 -- getDocTest conn = runQuery conn selectDocFacet
220 -- | Building the facet
221 -- selectDocFacet' :: ParentId -> Maybe NodeType -> Query FacetDocRead
222 selectDocFacet' :: ParentId -> Maybe NodeType -> Query FacetDocRead
223 selectDocFacet' _ _ = proc () -> do
224 (n1,(nn,n2)) <- leftJoin3''' -< ()
225 restrict -< (.&&) (node_parentId n1 .== (toNullable $ pgInt4 347476))
226 (node_typename n1 .== (pgInt4 4))
228 restrict -< (.||) (node_typename n2 .== (toNullable $ pgInt4 15))
229 (isNull $ node_typename n2)
231 restrict -< (.||) (node_parentId n2 .== (toNullable $ pgInt4 347476))
232 (isNull $ node_parentId n2)
234 let isFav = ifThenElse (isNull $ nodeNode_score nn) (pgBool False) (pgBool True)
236 returnA -< FacetDoc (node_id n1) (node_date n1) (node_hyperdata n1) (isFav) (pgInt4 1)