2 Module : Gargantext.Database.TextSearch
3 Description : Postgres text search experimentation
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
13 {-# LANGUAGE Arrows #-}
14 {-# LANGUAGE NoImplicitPrelude #-}
15 {-# LANGUAGE OverloadedStrings #-}
17 module Gargantext.Database.TextSearch where
21 import Data.List (intersperse)
22 import Data.String (IsString(..))
23 import Data.Text (Text, words)
25 import Database.PostgreSQL.Simple
26 import Database.PostgreSQL.Simple.ToField
27 import Gargantext.Database.Config (nodeTypeId)
28 import Gargantext.Database.Types.Node (NodeType(..))
29 import Gargantext.Prelude
30 import Gargantext.Database.Node
31 import Gargantext.Database.Queries
32 import Gargantext.Core.Types
33 import Control.Arrow (returnA)
34 import qualified Opaleye as O hiding (Order)
35 import Opaleye hiding (Query, Order)
37 newtype TSQuery = UnsafeTSQuery [Text]
41 searchQuery :: O.Query NodeRead
42 searchQuery = proc () -> do
43 row <- queryNodeTable -< ()
44 restrict -< (_node_search row) @@ (pgTSQuery "test")
49 -- | TODO [""] -> panic "error"
50 toTSQuery :: [Text] -> TSQuery
51 toTSQuery txt = UnsafeTSQuery txt
54 instance IsString TSQuery
56 fromString = UnsafeTSQuery . words . cs
59 instance ToField TSQuery
61 toField (UnsafeTSQuery xs)
62 = Many $ intersperse (Plain " && ")
63 $ map (\q -> Many [ Plain "plainto_tsquery("
69 data Order = Asc | Desc
71 instance ToField Order
73 toField Asc = Plain "ASC"
74 toField Desc = Plain "DESC"
80 textSearchQuery :: Query
81 textSearchQuery = "SELECT n.id, n.hyperdata->'publication_year' \
82 \ , n.hyperdata->'title' \
83 \ , n.hyperdata->'source' \
84 \ , n.hyperdata->'authors' \
85 \ , COALESCE(nn.score,null) \
87 \ LEFT JOIN nodes_nodes nn ON nn.node2_id = n.id \
89 \ n.search @@ (?::tsquery) \
90 \ AND (n.parent_id = ? OR nn.node1_id = ?) \
91 \ AND n.typename = ? \
92 \ ORDER BY n.hyperdata -> 'publication_date' ? \
95 -- | Text Search Function for Master Corpus
96 -- TODO : text search for user corpus
98 -- textSearchTest :: ParentId -> TSQuery -> Cmd [(Int, Value, Value, Value, Value, Maybe Int)]
99 -- textSearchTest pId q = mkCmd $ \c -> textSearch c q pId 5 0 Asc
100 textSearch :: Connection
101 -> TSQuery -> ParentId
102 -> Limit -> Offset -> Order
103 -> IO [(Int,Value,Value,Value, Value, Maybe Int)]
104 textSearch conn q p l o ord = query conn textSearchQuery (q,p,p,typeId,ord,o,l)
106 typeId = nodeTypeId NodeDocument