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 FlexibleContexts #-}
17 {-# LANGUAGE FlexibleInstances #-}
18 {-# LANGUAGE FunctionalDependencies #-}
19 {-# LANGUAGE MultiParamTypeClasses #-}
20 {-# LANGUAGE QuasiQuotes #-}
21 {-# LANGUAGE NoImplicitPrelude #-}
22 {-# LANGUAGE NoMonomorphismRestriction #-}
23 {-# LANGUAGE OverloadedStrings #-}
24 {-# LANGUAGE TemplateHaskell #-}
25 ------------------------------------------------------------------------
26 module Gargantext.Database.Facet
28 ------------------------------------------------------------------------
30 import Control.Arrow (returnA)
31 import Control.Lens.TH (makeLensesWith, abbreviatedFields)
32 import Data.Aeson (FromJSON, ToJSON)
33 import Data.Aeson.TH (deriveJSON)
34 import Data.Either(Either(Left))
35 import Data.Maybe (Maybe)
36 import Data.Profunctor.Product.TH (makeAdaptorAndInstance)
38 import Data.Text (Text)
39 import Data.Time (UTCTime)
40 import Data.Time.Segment (jour)
41 import Database.PostgreSQL.Simple (Connection)
42 import GHC.Generics (Generic)
43 import Gargantext.Core.Types
44 import Gargantext.Core.Utils.Prefix (unPrefix)
45 import Gargantext.Database.Config (nodeTypeId)
46 import Gargantext.Database.Schema.Ngrams
47 import Gargantext.Database.Schema.Node
48 import Gargantext.Database.Schema.NodeNgram
49 import Gargantext.Database.Schema.NodeNode
50 import Gargantext.Database.Queries.Join
51 import Gargantext.Database.Queries.Filter
53 import Prelude hiding (null, id, map, sum, not, read)
55 import Test.QuickCheck (elements)
56 import Test.QuickCheck.Arbitrary
57 import qualified Opaleye.Internal.Unpackspec()
59 ------------------------------------------------------------------------
62 -- data Facet = FacetDoc | FacetSources | FacetAuthors | FacetTerms
63 -- deriving (Show, Generic)
64 --instance FromJSON Facet
65 --instance ToJSON Facet
70 type FacetDoc = Facet NodeId UTCTime Title HyperdataDocument Favorite Int
71 type FacetSources = FacetDoc
72 type FacetAuthors = FacetDoc
73 type FacetTerms = FacetDoc
77 data Facet id created title hyperdata favorite ngramCount =
78 FacetDoc { facetDoc_id :: id
79 , facetDoc_created :: created
80 , facetDoc_title :: title
81 , facetDoc_hyperdata :: hyperdata
82 , facetDoc_favorite :: favorite
83 , facetDoc_ngramCount :: ngramCount
84 } deriving (Show, Generic)
88 $(deriveJSON (unPrefix "facetDoc_") ''Facet)
90 -- | Documentation instance
91 instance ToSchema FacetDoc
93 -- | Mock and Quickcheck instances
95 instance Arbitrary FacetDoc where
96 arbitrary = elements [ FacetDoc id' (jour year 01 01) t hp fav ngramCount
98 , year <- [1990..2000]
99 , t <- ["title", "another title"]
100 , hp <- hyperdataDocuments
101 , fav <- [True, False]
102 , ngramCount <- [3..100]
105 -- Facets / Views for the Front End
106 -- | Database instances
107 $(makeAdaptorAndInstance "pFacetDoc" ''Facet)
108 $(makeLensesWith abbreviatedFields ''Facet)
110 type FacetDocRead = Facet (Column PGInt4 )
111 (Column PGTimestamptz)
117 -----------------------------------------------------------------------
119 data FacetChart = FacetChart { facetChart_time :: UTCTime'
120 , facetChart_count :: Double
122 deriving (Show, Generic)
123 $(deriveJSON (unPrefix "facetChart_") ''FacetChart)
124 instance ToSchema FacetChart
126 instance Arbitrary FacetChart where
127 arbitrary = FacetChart <$> arbitrary <*> arbitrary
129 -----------------------------------------------------------------------
131 data OrderBy = DateAsc | DateDesc
132 | TitleAsc | TitleDesc
134 deriving (Generic, Enum, Bounded, Read, Show)
137 instance FromHttpApiData OrderBy
139 parseUrlPiece "DateAsc" = pure DateAsc
140 parseUrlPiece "DateDesc" = pure DateDesc
141 parseUrlPiece "TitleAsc" = pure TitleAsc
142 parseUrlPiece "TitleDesc" = pure TitleDesc
143 parseUrlPiece "FavAsc" = pure FavAsc
144 parseUrlPiece "FavDesc" = pure FavDesc
145 parseUrlPiece _ = Left "Unexpected value of OrderBy"
147 instance ToParamSchema OrderBy
148 instance FromJSON OrderBy
149 instance ToJSON OrderBy
150 instance ToSchema OrderBy
151 instance Arbitrary OrderBy
153 arbitrary = elements [minBound..maxBound]
156 runViewAuthorsDoc :: Connection -> ContactId -> Trash -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> IO [FacetDoc]
157 runViewAuthorsDoc c cId t o l order = runQuery c (filterDocuments o l order $ viewAuthorsDoc cId t ntId)
162 viewAuthorsDoc :: ContactId -> Trash -> NodeType -> Query FacetDocRead
163 viewAuthorsDoc cId _ nt = proc () -> do
164 (doc,(_,(_,(_,contact)))) <- queryAuthorsDoc -< ()
166 {-nn <- queryNodeNodeTable -< ()
167 restrict -< nodeNode_node1_id nn .== _node_id doc
168 -- restrict -< nodeNode_delete nn .== (pgBool t)
171 restrict -< _node_id contact .== (toNullable $ pgInt4 cId)
172 restrict -< _node_typename doc .== (pgInt4 $ nodeTypeId nt)
174 returnA -< FacetDoc (_node_id doc) (_node_date doc) (_node_name doc) (_node_hyperdata doc) (pgBool True) (pgInt4 1)
176 queryAuthorsDoc :: Query (NodeRead, (NodeNgramReadNull, (NgramsReadNull, (NodeNgramReadNull, NodeReadNull))))
177 queryAuthorsDoc = leftJoin5 queryNodeTable queryNodeNgramTable queryNgramsTable queryNodeNgramTable queryNodeTable cond12 cond23 cond34 cond45
179 cond12 :: (NodeNgramRead, NodeRead) -> Column PGBool
180 cond12 (nodeNgram, doc) = _node_id doc
181 .== nodeNgram_NodeNgramNodeId nodeNgram
183 cond23 :: (NgramsRead, (NodeNgramRead, NodeReadNull)) -> Column PGBool
184 cond23 (ngrams, (nodeNgram, _)) = ngrams_id ngrams
185 .== nodeNgram_NodeNgramNgramId nodeNgram
187 cond34 :: (NodeNgramRead, (NgramsRead, (NodeNgramReadNull, NodeReadNull))) -> Column PGBool
188 cond34 (nodeNgram2, (ngrams, (_,_)))= ngrams_id ngrams .== nodeNgram_NodeNgramNgramId nodeNgram2
190 cond45 :: (NodeRead, (NodeNgramRead, (NgramsReadNull, (NodeNgramReadNull, NodeReadNull)))) -> Column PGBool
191 cond45 (contact, (nodeNgram2, (_, (_,_)))) = _node_id contact .== nodeNgram_NodeNgramNodeId nodeNgram2
194 ------------------------------------------------------------------------
196 runViewDocuments :: CorpusId -> Trash -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> Cmd [FacetDoc]
197 runViewDocuments cId t o l order = mkCmd $ \c -> runViewDocuments' c cId t o l order
199 -- | TODO use only Cmd with Reader and delete function below
200 runViewDocuments' :: Connection -> CorpusId -> Trash -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> IO [FacetDoc]
201 runViewDocuments' c cId t o l order = runQuery c ( filterDocuments o l order
202 $ viewDocuments cId t ntId)
204 ntId = nodeTypeId NodeDocument
206 viewDocuments :: CorpusId -> Trash -> NodeTypeId -> Query FacetDocRead
207 viewDocuments cId t ntId = proc () -> do
208 n <- queryNodeTable -< ()
209 nn <- queryNodeNodeTable -< ()
210 restrict -< _node_id n .== nodeNode_node2_id nn
211 restrict -< nodeNode_node1_id nn .== (pgInt4 cId)
212 restrict -< _node_typename n .== (pgInt4 ntId)
213 restrict -< nodeNode_delete nn .== (pgBool t)
214 returnA -< FacetDoc (_node_id n) (_node_date n) (_node_name n) (_node_hyperdata n) (nodeNode_favorite nn) (pgInt4 1)
217 ------------------------------------------------------------------------
219 filterDocuments :: (PGOrd date, PGOrd title, PGOrd favorite) =>
220 Maybe Gargantext.Core.Types.Offset
221 -> Maybe Gargantext.Core.Types.Limit
223 -> Select (Facet id (Column date) (Column title) hyperdata (Column favorite) ngramCount)
224 -> Query (Facet id (Column date) (Column title) hyperdata (Column favorite) ngramCount)
225 filterDocuments o l order q = limit' l $ offset' o $ orderBy ordering q
227 ordering = case order of
228 (Just DateAsc) -> asc facetDoc_created
230 (Just TitleAsc) -> asc facetDoc_title
231 (Just TitleDesc) -> desc facetDoc_title
233 (Just FavAsc) -> asc facetDoc_favorite
234 (Just FavDesc) -> desc facetDoc_favorite
235 _ -> desc facetDoc_created