2 Module : Gargantext.API.Count
3 Description : Server API
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 Count API part of Gargantext.
15 {-# LANGUAGE TemplateHaskell #-}
16 {-# LANGUAGE TypeOperators #-}
17 {-# LANGUAGE DeriveAnyClass #-}
19 module Gargantext.API.Search
23 import Data.Maybe (fromMaybe)
24 import Data.Swagger hiding (fieldLabelModifier, Contact)
25 import Data.Text (Text)
26 import Data.Time (UTCTime)
27 import GHC.Generics (Generic)
28 import Gargantext.API.Prelude (GargServer)
29 import Gargantext.Core.Utils.Prefix (unPrefixSwagger, unCapitalize, dropPrefix)
30 import Gargantext.Database.Query.Facet
31 import Gargantext.Database.Action.Search
32 import Gargantext.Database.Action.Flow.Pairing (isPairedWith)
33 import Gargantext.Database.Admin.Types.Hyperdata (HyperdataContact(..), HyperdataDocument(..), ContactWho(..))
34 import Gargantext.Database.Admin.Types.Node
35 import Gargantext.Prelude
37 import Test.QuickCheck (elements)
38 import Test.QuickCheck.Arbitrary
40 -----------------------------------------------------------------------
41 -- TODO-ACCESS: CanSearch? or is it part of CanGetNode
42 -- TODO-EVENTS: No event, this is a read-only query.
43 type API results = Summary "Search endpoint"
44 :> ReqBody '[JSON] SearchQuery
45 :> QueryParam "offset" Int
46 :> QueryParam "limit" Int
47 :> QueryParam "order" OrderBy
48 :> Post '[JSON] results
49 -----------------------------------------------------------------------
50 api :: NodeId -> GargServer (API SearchResult)
51 api nId (SearchQuery q SearchDoc) o l order =
52 SearchResult <$> SearchResultDoc <$> map toRow <$> searchInCorpus nId False q o l order
53 api nId (SearchQuery q SearchContact) o l order = do
54 printDebug "isPairedWith" nId
55 aIds <- isPairedWith nId NodeAnnuaire
56 -- TODO if paired with several corpus
58 Nothing -> pure $ SearchResult $ SearchNoResult "[G.A.Search] pair corpus with an Annuaire"
59 Just aId -> SearchResult <$> SearchResultContact <$> map toRow <$> searchInCorpusWithContacts nId aId q o l order
60 api _ _ _ _ _ = undefined
62 -----------------------------------------------------------------------
63 -----------------------------------------------------------------------
65 -----------------------------------------------------------------------
66 data SearchType = SearchDoc | SearchContact
69 instance FromJSON SearchType
71 parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
73 instance ToJSON SearchType
75 toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
77 instance ToSchema SearchType
78 instance Arbitrary SearchType where
79 arbitrary = elements [SearchDoc, SearchContact]
81 -----------------------------------------------------------------------
83 SearchQuery { query :: ![Text]
84 , expected :: !SearchType
86 | SearchQueryErr !Text
89 instance FromJSON SearchQuery
91 parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
93 instance ToJSON SearchQuery
95 toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
97 instance ToSchema SearchQuery
100 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "")
103 instance Arbitrary SearchQuery where
104 arbitrary = elements [SearchQuery ["electrodes"] SearchDoc]
105 -- arbitrary = elements [SearchQuery "electrodes" 1 ] --SearchDoc]
106 -----------------------------------------------------------------------
108 SearchResult { result :: !SearchResultTypes
110 | SearchResultErr !Text
113 instance FromJSON SearchResult
115 parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
117 instance ToJSON SearchResult
119 toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
121 instance ToSchema SearchResult
124 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "")
127 instance Arbitrary SearchResult where
128 arbitrary = SearchResult <$> arbitrary
131 data SearchResultTypes = SearchResultDoc { docs :: ![Row]}
132 | SearchResultContact { contacts :: ![Row] }
133 | SearchNoResult { message :: !Text }
137 instance FromJSON SearchResultTypes
139 parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
141 instance ToJSON SearchResultTypes
143 toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
145 instance Arbitrary SearchResultTypes where
147 srd <- SearchResultDoc <$> arbitrary
148 src <- SearchResultContact <$> arbitrary
149 srn <- pure $ SearchNoResult "No result because.."
150 elements [srd, src, srn]
152 instance ToSchema SearchResultTypes where
153 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "")
156 --------------------------------------------------------------------
159 Document { id :: !NodeId
160 , created :: !UTCTime
162 , hyperdata :: !HyperdataRow
166 | Contact { c_id :: !Int
167 , c_created :: !UTCTime
168 , c_hyperdata :: !HyperdataRow
173 instance FromJSON Row
175 parseJSON = genericParseJSON
176 ( defaultOptions { sumEncoding = ObjectWithSingleField
182 toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
184 instance Arbitrary Row where
185 arbitrary = arbitrary
187 instance ToSchema Row where
188 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "")
193 instance ToRow FacetDoc where
194 toRow (FacetDoc nId utc t h mc _md sc) = Document nId utc t (toHyperdataRow h) (fromMaybe 0 mc) (round $ fromMaybe 0 sc)
196 -- | TODO rename FacetPaired
197 type FacetContact = FacetPaired Int UTCTime HyperdataContact Int
199 instance ToRow FacetContact where
200 toRow (FacetPaired nId utc h s) = Contact nId utc (toHyperdataRow h) s
203 --------------------------------------------------------------------
205 HyperdataRowDocument { _hr_bdd :: !Text
208 , _hr_uniqId :: !Text
209 , _hr_uniqIdBdd :: !Text
212 , _hr_authors :: !Text
213 , _hr_institutes :: !Text
214 , _hr_source :: !Text
215 , _hr_abstract :: !Text
216 , _hr_publication_date :: !Text
217 , _hr_publication_year :: !Int
218 , _hr_publication_month :: !Int
219 , _hr_publication_day :: !Int
220 , _hr_publication_hour :: !Int
221 , _hr_publication_minute :: !Int
222 , _hr_publication_second :: !Int
223 , _hr_language_iso2 :: !Text
225 | HyperdataRowContact { _hr_firstname :: !Text
226 , _hr_lastname :: !Text
231 instance FromJSON HyperdataRow
233 parseJSON = genericParseJSON
235 { sumEncoding = ObjectWithSingleField
236 , fieldLabelModifier = unCapitalize . dropPrefix "_hr_"
237 , omitNothingFields = False
241 instance ToJSON HyperdataRow
243 toJSON = genericToJSON
245 { sumEncoding = ObjectWithSingleField
246 , fieldLabelModifier = unCapitalize . dropPrefix "_hr_"
247 , omitNothingFields = False
251 instance Arbitrary HyperdataRow where
252 arbitrary = arbitrary
254 instance ToSchema HyperdataRow where
255 declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_hr_")
257 class ToHyperdataRow a where
258 toHyperdataRow :: a -> HyperdataRow
260 instance ToHyperdataRow HyperdataDocument where
261 toHyperdataRow (HyperdataDocument b d u ui ub p t a i s abs' pd py pm pda ph pmin psec l) =
269 (fromMaybe "Title" t)
283 instance ToHyperdataRow HyperdataContact where
284 toHyperdataRow (HyperdataContact _ (Just (ContactWho _ fn ln _ _)) _ _ _ _ _ _ ) = HyperdataRowContact (fromMaybe "FN" fn) (fromMaybe "LN" ln) "Labs"
285 toHyperdataRow (HyperdataContact _ _ _ _ _ _ _ _ ) = HyperdataRowContact "FirstName" "LastName" "Labs"