@@ -10,7 +10,21 @@ module Database.Bloodhound.Client
10 , getDocument
10 , getDocument
11 , documentExists
11 , documentExists
12 , deleteDocument
12 , deleteDocument
13 , EsResult(..)
14 , EsResult(..)
@@ -230,6 +244,29 @@ documentExists (Server server) indexName mappingName docId = do
230 return exists where
244 return exists where
231 url = joinPath [server, indexName, mappingName, docId]
245 url = joinPath [server, indexName, mappingName, docId]
248+dispatchSearch :: String -> Search -> IO Reply
249+dispatchSearch url search = dispatch url NHTM.methodPost (Just (encode search))
251+searchAll :: Server -> Search -> IO Reply
252+searchAll (Server server) search = dispatchSearch url search where
253+ url = joinPath [server, "_search"]
255+searchByIndex :: Server -> IndexName -> Search -> IO Reply
256+searchByIndex (Server server) indexName search = dispatchSearch url search where
257+ url = joinPath [server, indexName, "_search"]
259+searchByType :: Server -> IndexName -> MappingName -> Search -> IO Reply
260+searchByType (Server server) indexName mappingName search = dispatchSearch url search where
261+ url = joinPath [server, indexName, mappingName, "_search"]
263+data Search = Search { queryBody :: Maybe Query
264+ , filterBody :: Maybe Filter } deriving (Show)
266+instance ToJSON Search where
267+ toJSON (Search query filters) = object [--"query" .= fmap toJSON query,
268+ "filter" .= fmap toJSON filters]
233type QueryString = Text
270type QueryString = Text
234-- status:active
271-- status:active
235-- author:"John Smith"
272-- author:"John Smith"
@@ -244,6 +281,9 @@ newtype TieBreaker = TieBreaker Int deriving (Show)
244data QueryField = DefaultField Text
281data QueryField = DefaultField Text
245 | Fields [Text] DisMax TieBreaker deriving (Show)
282 | Fields [Text] DisMax TieBreaker deriving (Show)
284+-- this is will go away later
285+type Query = QueryStringQuery
247data QueryStringQuery =
287data QueryStringQuery =
248 QueryStringQuery { query :: QueryString
288 QueryStringQuery { query :: QueryString
249 -- default _all
289 -- default _all
@@ -291,7 +331,7 @@ defaultCache = False
291data Filter = AndFilter [Filter] Cache
331data Filter = AndFilter [Filter] Cache
292 | OrFilter [Filter] Cache
332 | OrFilter [Filter] Cache
293 | IdentityFilter
333 | IdentityFilter
294− | BoolFilter BoolMatch Cache
334+ | BoolFilter BoolMatch
295 | ExistsFilter FieldName -- always cached
335 | ExistsFilter FieldName -- always cached
296 | GeoBoundingBoxFilter GeoBoundingBoxConstraint GeoFilterType Cache
336 | GeoBoundingBoxFilter GeoBoundingBoxConstraint GeoFilterType Cache
297 | GeoDistanceFilter GeoConstraint Distance Cache
337 | GeoDistanceFilter GeoConstraint Distance Cache
@@ -325,9 +365,8 @@ instance ToJSON Filter where
325 toJSON (ExistsFilter fieldName) =
365 toJSON (ExistsFilter fieldName) =
326 object ["exists" .= object
366 object ["exists" .= object
327 ["field" .= fieldName]]
367 ["field" .= fieldName]]
328− toJSON (BoolFilter boolMatch cache) =
368+ toJSON (BoolFilter boolMatch) =
329− object ["bool" .= toJSON boolMatch
369+ object ["bool" .= toJSON boolMatch]
330− , "_cache" .= cache]
332data Term = Term { termField :: Text
371data Term = Term { termField :: Text
333 , termValue :: Text } deriving (Show)
372 , termValue :: Text } deriving (Show)
@@ -336,14 +375,17 @@ instance ToJSON Term where
336 toJSON (Term field value) = object ["term" .= object
375 toJSON (Term field value) = object ["term" .= object
337 [field .= value]]
376 [field .= value]]
339−data BoolMatch = MustMatch Term
378+data BoolMatch = MustMatch Term Cache
340− | MustNotMatch Term
379+ | MustNotMatch Term Cache
341− | ShouldMatch [Term] deriving (Show)
380+ | ShouldMatch [Term] Cache deriving (Show)
343instance ToJSON BoolMatch where
382instance ToJSON BoolMatch where
344− toJSON (MustMatch term) = object ["must" .= toJSON term]
383+ toJSON (MustMatch term cache) = object ["must" .= toJSON term,
345− toJSON (MustNotMatch term) = object ["must_not" .= toJSON term]
385+ toJSON (MustNotMatch term cache) = object ["must_not" .= toJSON term,
346− toJSON (ShouldMatch terms) = object ["should" .= fmap toJSON terms]
387+ toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
348-- "memory" or "indexed"
390-- "memory" or "indexed"
349data GeoFilterType = GeoFilterMemory | GeoFilterIndexed deriving (Show)
391data GeoFilterType = GeoFilterMemory | GeoFilterIndexed deriving (Show)
@@ -383,27 +425,58 @@ data Distance =
383 Distance { coefficient :: Double
425 Distance { coefficient :: Double
384 , unit :: DistanceUnits } deriving (Show)
426 , unit :: DistanceUnits } deriving (Show)
386−data FromJSON a => SearchResults a =
428+data FromJSON a => SearchResult a =
387− SearchResults { took :: Int
429+ SearchResult { took :: Int
388− , timedOut :: Bool
430+ , timedOut :: Bool
389− , shards :: ShardResults
431+ , shards :: ShardResult
390− , searchHits :: SearchHits a } deriving (Show)
432+ , searchHits :: SearchHits a } deriving (Show)
392type Score = Double
434type Score = Double
394data FromJSON a => SearchHits a =
436data FromJSON a => SearchHits a =
395 SearchHits { hitsTotal :: Int
437 SearchHits { hitsTotal :: Int
396 , maxScore :: Score
438 , maxScore :: Score
397− , hits :: [Hits a] } deriving (Show)
439+ , hits :: [Hit a] } deriving (Show)
399−data FromJSON a => Hits a =
441+data FromJSON a => Hit a =
400− Hits { hitsIndex :: IndexName
442+ Hit { hitIndex :: IndexName
401− , hitsType :: MappingName
443+ , hitType :: MappingName
402− , hitDocumentID :: DocumentID
444+ , hitDocumentID :: DocumentID
403− , hitScore :: Score
445+ , hitScore :: Score
404− , hitSource :: a } deriving (Show)
446+ , hitSource :: a } deriving (Show)
406−data ShardResults =
448+data ShardResult =
407− ShardResults { shardTotal :: Int
449+ ShardResult { shardTotal :: Int
408− , shardsSuccessful :: Int
450+ , shardsSuccessful :: Int
409− , shardsFailed :: Int } deriving (Show)
451+ , shardsFailed :: Int } deriving (Show, Generic)
453+instance (FromJSON a, ToJSON a) => FromJSON (SearchResult a) where
454+ parseJSON (Object v) = SearchResult <$>
456+ v .: "timed_out" <*>
461+instance (FromJSON a, ToJSON a) => FromJSON (SearchHits a) where
462+ parseJSON (Object v) = SearchHits <$>
464+ v .: "max_score" <*>
468+instance (FromJSON a, ToJSON a) => FromJSON (Hit a) where
469+ parseJSON (Object v) = Hit <$>
477+instance FromJSON ShardResult where
478+ parseJSON (Object v) = ShardResult <$>
480+ v .: "successful" <*>