@@ -196,6 +196,8 @@ module Database.V5.Bloodhound.Types
196 , RangeQuery(..)
196 , RangeQuery(..)
197 , RegexpQuery(..)
197 , RegexpQuery(..)
198 , QueryString(..)
198 , QueryString(..)
199+ , TemplateQueryInline(..)
200+ , TemplateQueryKeyValuePairs(..)
199 , BooleanOperator(..)
201 , BooleanOperator(..)
200 , ZeroTermsQuery(..)
202 , ZeroTermsQuery(..)
201 , CutoffFrequency(..)
203 , CutoffFrequency(..)
@@ -323,6 +325,15 @@ module Database.V5.Bloodhound.Types
323 , rrGroupRefNum
325 , rrGroupRefNum
324 , mkRRGroupRefNum
326 , mkRRGroupRefNum
325 , RestoreIndexSettings(..)
327 , RestoreIndexSettings(..)
330+ , PhraseSuggester(..)
331+ , PhraseSuggesterHighlighter(..)
332+ , PhraseSuggesterCollate(..)
334+ , SuggestOptions(..)
335+ , SuggestResponse(..)
336+ , NamedSuggestionResponse(..)
327 , Aggregation(..)
338 , Aggregation(..)
328 , Aggregations
339 , Aggregations
@@ -378,7 +389,8 @@ import Control.Monad.Writer (MonadWriter)
378import Data.Aeson
389import Data.Aeson
379import Data.Aeson.Types (Pair, Parser,
390import Data.Aeson.Types (Pair, Parser,
380 emptyObject,
391 emptyObject,
381− parseEither, parseMaybe)
392+ parseEither, parseMaybe,
382import qualified Data.ByteString.Lazy.Char8 as L
394import qualified Data.ByteString.Lazy.Char8 as L
383import Data.Char
395import Data.Char
384import Data.Hashable (Hashable)
396import Data.Hashable (Hashable)
@@ -1095,7 +1107,7 @@ unpackId (DocId docId) = docId
1096type TrackSortScores = Bool
1108type TrackSortScores = Bool
1097newtype From = From Int deriving (Eq, Read, Show, Generic, ToJSON)
1109newtype From = From Int deriving (Eq, Read, Show, Generic, ToJSON)
1098−newtype Size = Size Int deriving (Eq, Read, Show, Generic, ToJSON)
1110+newtype Size = Size Int deriving (Eq, Read, Show, Generic, ToJSON, FromJSON)
1100data Search = Search { queryBody :: Maybe Query
1112data Search = Search { queryBody :: Maybe Query
1101 , filterBody :: Maybe Filter
1113 , filterBody :: Maybe Filter
@@ -1108,7 +1120,9 @@ data Search = Search { queryBody :: Maybe Query
1108 , size :: Size
1120 , size :: Size
1109 , searchType :: SearchType
1121 , searchType :: SearchType
1110 , fields :: Maybe [FieldName]
1122 , fields :: Maybe [FieldName]
1123+ , source :: Maybe Source
1124+ , suggestBody :: Maybe Suggest -- ^ Only one Suggestion request / response per Search is supported.
1111− , source :: Maybe Source } deriving (Eq, Read, Show, Generic, Typeable)
1125+ } deriving (Eq, Read, Show, Generic, Typeable)
1113data SearchType = SearchTypeQueryThenFetch
1127data SearchType = SearchTypeQueryThenFetch
1114 | SearchTypeDfsQueryThenFetch
1128 | SearchTypeDfsQueryThenFetch
@@ -1211,6 +1225,7 @@ data Query =
1211 | QueryRegexpQuery RegexpQuery
1225 | QueryRegexpQuery RegexpQuery
1212 | QueryExistsQuery FieldName
1226 | QueryExistsQuery FieldName
1213 | QueryMatchNoneQuery
1227 | QueryMatchNoneQuery
1228+ | QueryTemplateQueryInline TemplateQueryInline
1214 deriving (Eq, Read, Show, Generic, Typeable)
1229 deriving (Eq, Read, Show, Generic, Typeable)
1216-- | As of Elastic 2.0, 'Filters' are just 'Queries' housed in a Bool Query, and
1231-- | As of Elastic 2.0, 'Filters' are just 'Queries' housed in a Bool Query, and
@@ -1622,13 +1637,49 @@ data DistanceRange =
1622 DistanceRange { distanceFrom :: Distance
1637 DistanceRange { distanceFrom :: Distance
1623 , distanceTo :: Distance } deriving (Eq, Read, Show, Generic, Typeable)
1638 , distanceTo :: Distance } deriving (Eq, Read, Show, Generic, Typeable)
1640+type TemplateQueryKey = Text
1641+type TemplateQueryValue = Text
1643+newtype TemplateQueryKeyValuePairs = TemplateQueryKeyValuePairs (HM.HashMap TemplateQueryKey TemplateQueryValue)
1644+ deriving (Eq, Read, Show, Generic)
1646+instance ToJSON TemplateQueryKeyValuePairs where
1647+ toJSON (TemplateQueryKeyValuePairs x) = Object $ HM.map toJSON x
1649+instance FromJSON TemplateQueryKeyValuePairs where
1650+ parseJSON (Object o) = pure . TemplateQueryKeyValuePairs $ HM.mapMaybe getValue o
1651+ where getValue (String x) = Just x
1652+ getValue _ = Nothing
1653+ parseJSON _ = fail "error parsing TemplateQueryKeyValuePairs"
1655+data TemplateQueryInline =
1656+ TemplateQueryInline { inline :: Query
1657+ , params :: TemplateQueryKeyValuePairs
1659+ deriving (Eq, Read, Show, Generic, Typeable)
1661+instance ToJSON TemplateQueryInline where
1662+ toJSON TemplateQueryInline{..} = object [ "inline" .= inline
1663+ , "params" .= params
1666+instance FromJSON TemplateQueryInline where
1667+ parseJSON = withObject "TemplateQueryInline" parse
1668+ where parse o = TemplateQueryInline
1625data SearchResult a =
1673data SearchResult a =
1626 SearchResult { took :: Int
1674 SearchResult { took :: Int
1627 , timedOut :: Bool
1675 , timedOut :: Bool
1628 , shards :: ShardResult
1676 , shards :: ShardResult
1629 , searchHits :: SearchHits a
1677 , searchHits :: SearchHits a
1630 , aggregations :: Maybe AggregationResults
1678 , aggregations :: Maybe AggregationResults
1679+ , scrollId :: Maybe ScrollId
1680+ , suggest :: Maybe NamedSuggestionResponse -- ^ Only one Suggestion request / response per Search is supported.
1631− , scrollId :: Maybe ScrollId } deriving (Eq, Read, Show, Generic, Typeable)
1682+ deriving (Eq, Read, Show, Generic, Typeable)
1633newtype ScrollId = ScrollId Text deriving (Eq, Read, Show, Generic, Ord, ToJSON, FromJSON)
1684newtype ScrollId = ScrollId Text deriving (Eq, Read, Show, Generic, Ord, ToJSON, FromJSON)
@@ -2220,6 +2271,9 @@ instance ToJSON Query where
2220 toJSON QueryMatchNoneQuery =
2271 toJSON QueryMatchNoneQuery =
2221 object ["match_none" .= object []]
2272 object ["match_none" .= object []]
2274+ toJSON (QueryTemplateQueryInline templateQuery) =
2275+ object [ "template" .= templateQuery ]
2223instance FromJSON Query where
2277instance FromJSON Query where
2224 parseJSON v = withObject "Query" parse v
2278 parseJSON v = withObject "Query" parse v
2225 where parse o = termQuery `taggedWith` "term"
2279 where parse o = termQuery `taggedWith` "term"
@@ -2247,6 +2301,7 @@ instance FromJSON Query where
2247 <|> queryRangeQuery `taggedWith` "range"
2301 <|> queryRangeQuery `taggedWith` "range"
2248 <|> queryRegexpQuery `taggedWith` "regexp"
2302 <|> queryRegexpQuery `taggedWith` "regexp"
2249 <|> querySimpleQueryStringQuery `taggedWith` "simple_query_string"
2303 <|> querySimpleQueryStringQuery `taggedWith` "simple_query_string"
2304+ <|> queryTemplateQueryInline `taggedWith` "template"
2250 where taggedWith parser k = parser =<< o .: k
2305 where taggedWith parser k = parser =<< o .: k
2251 termQuery = fieldTagged $ \(FieldName fn) o ->
2306 termQuery = fieldTagged $ \(FieldName fn) o ->
2252 TermQuery <$> (Term fn <$> o .: "value") <*> o .:? "boost"
2307 TermQuery <$> (Term fn <$> o .: "value") <*> o .:? "boost"
@@ -2284,6 +2339,7 @@ instance FromJSON Query where
2284 queryRegexpQuery = pure . QueryRegexpQuery
2339 queryRegexpQuery = pure . QueryRegexpQuery
2285 querySimpleQueryStringQuery = pure . QuerySimpleQueryStringQuery
2340 querySimpleQueryStringQuery = pure . QuerySimpleQueryStringQuery
2286 -- queryExistsQuery o = QueryExistsQuery <$> o .: "field"
2341 -- queryExistsQuery o = QueryExistsQuery <$> o .: "field"
2342+ queryTemplateQueryInline = pure . QueryTemplateQueryInline
2289omitNulls :: [(Text, Value)] -> Value
2345omitNulls :: [(Text, Value)] -> Value
@@ -2810,7 +2866,7 @@ instance ToJSON MultiMatchQuery where
2810 , "query" .= query
2866 , "query" .= query
2811 , "operator" .= boolOp
2867 , "operator" .= boolOp
2812 , "zero_terms_query" .= ztQ
2868 , "zero_terms_query" .= ztQ
2813− , "tiebreaker" .= tb
2869+ , "tie_breaker" .= tb
2814 , "type" .= mmqt
2870 , "type" .= mmqt
2815 , "cutoff_frequency" .= cf
2871 , "cutoff_frequency" .= cf
2816 , "analyzer" .= analyzer
2872 , "analyzer" .= analyzer
@@ -2825,7 +2881,7 @@ instance FromJSON MultiMatchQuery where
2825 <*> o .: "query"
2881 <*> o .: "query"
2826 <*> o .: "operator"
2882 <*> o .: "operator"
2827 <*> o .: "zero_terms_query"
2883 <*> o .: "zero_terms_query"
2828− <*> o .:? "tiebreaker"
2884+ <*> o .:? "tie_breaker"
2829 <*> o .:? "type"
2885 <*> o .:? "type"
2830 <*> o .:? "cutoff_frequency"
2886 <*> o .:? "cutoff_frequency"
2831 <*> o .:? "analyzer"
2887 <*> o .:? "analyzer"
@@ -3212,7 +3268,7 @@ instance FromJSON SearchAliasRouting where
3212 where parse t = SearchAliasRouting <$> parseNEJSON (String <$> T.splitOn "," t)
3268 where parse t = SearchAliasRouting <$> parseNEJSON (String <$> T.splitOn "," t)
3214instance ToJSON Search where
3270instance ToJSON Search where
3215− toJSON (Search mquery sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
3271+ toJSON (Search mquery sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource sSuggest) =
3216 omitNulls [ "query" .= query'
3272 omitNulls [ "query" .= query'
3217 , "sort" .= sort
3273 , "sort" .= sort
3218 , "aggregations" .= searchAggs
3274 , "aggregations" .= searchAggs
@@ -3221,7 +3277,8 @@ instance ToJSON Search where
3221 , "size" .= sSize
3277 , "size" .= sSize
3222 , "track_scores" .= sTrackSortScores
3278 , "track_scores" .= sTrackSortScores
3223 , "fields" .= sFields
3279 , "fields" .= sFields
3224− , "_source" .= sSource]
3280+ , "_source" .= sSource
3281+ , "suggest" .= sSuggest]
3226 where query' = case sFilter of
3283 where query' = case sFilter of
3227 Nothing -> mquery
3284 Nothing -> mquery
@@ -3574,7 +3631,8 @@ instance (FromJSON a) => FromJSON (SearchResult a) where
3574 v .: "_shards" <*>
3631 v .: "_shards" <*>
3575 v .: "hits" <*>
3632 v .: "hits" <*>
3576 v .:? "aggregations" <*>
3633 v .:? "aggregations" <*>
3577− v .:? "_scroll_id"
3634+ v .:? "_scroll_id" <*>
3578 parseJSON _ = empty
3636 parseJSON _ = empty
3580instance (FromJSON a) => FromJSON (SearchHits a) where
3638instance (FromJSON a) => FromJSON (SearchHits a) where
@@ -5055,3 +5113,178 @@ newtype MaybeNA a = MaybeNA { unMaybeNA :: Maybe a }
5055instance FromJSON a => FromJSON (MaybeNA a) where
5113instance FromJSON a => FromJSON (MaybeNA a) where
5056 parseJSON (String "NA") = pure $ MaybeNA Nothing
5114 parseJSON (String "NA") = pure $ MaybeNA Nothing
5057 parseJSON o = MaybeNA . Just <$> parseJSON o
5115 parseJSON o = MaybeNA . Just <$> parseJSON o
5117+data Suggest = Suggest { suggestText :: Text
5118+ , suggestName :: Text
5119+ , suggestType :: SuggestType
5121+ deriving (Show, Generic, Eq, Read)
5123+instance ToJSON Suggest where
5124+ toJSON Suggest{..} = object [ "text" .= suggestText
5125+ , suggestName .= suggestType
5128+instance FromJSON Suggest where
5129+ parseJSON (Object o) = do
5130+ suggestText' <- o .: "text"
5131+ let dropTextList = HM.toList $ HM.filterWithKey (\x _ -> x /= "text") o
5132+ suggestName' <- case dropTextList of
5133+ [(x, _)] -> return x
5134+ _ -> fail "error parsing Suggest field name"
5135+ suggestType' <- o .: suggestName'
5136+ return $ Suggest suggestText' suggestName' suggestType'
5137+ parseJSON x = typeMismatch "Suggest" x
5139+data SuggestType = SuggestTypePhraseSuggester PhraseSuggester
5140+ deriving (Show, Generic, Eq, Read)
5142+instance ToJSON SuggestType where
5143+ toJSON (SuggestTypePhraseSuggester x) = object ["phrase" .= x]
5145+instance FromJSON SuggestType where
5146+ parseJSON = withObject "SuggestType" parse
5147+ where parse o = phraseSuggester `taggedWith` "phrase"
5148+ where taggedWith parser k = parser =<< o .: k
5149+ phraseSuggester = pure . SuggestTypePhraseSuggester
5151+data PhraseSuggester =
5152+ PhraseSuggester { phraseSuggesterField :: FieldName
5153+ , phraseSuggesterGramSize :: Maybe Int
5154+ , phraseSuggesterRealWordErrorLikelihood :: Maybe Int
5155+ , phraseSuggesterConfidence :: Maybe Int
5156+ , phraseSuggesterMaxErrors :: Maybe Int
5157+ , phraseSuggesterSeparator :: Maybe Text
5158+ , phraseSuggesterSize :: Maybe Size
5159+ , phraseSuggesterAnalyzer :: Maybe Analyzer
5160+ , phraseSuggesterShardSize :: Maybe Int
5161+ , phraseSuggesterHighlight :: Maybe PhraseSuggesterHighlighter
5162+ , phraseSuggesterCollate :: Maybe PhraseSuggesterCollate
5164+ deriving (Show, Generic, Eq, Read)
5166+instance ToJSON PhraseSuggester where
5167+ toJSON PhraseSuggester{..} = omitNulls [ "field" .= phraseSuggesterField
5168+ , "gram_size" .= phraseSuggesterGramSize
5169+ , "real_word_error_likelihood" .= phraseSuggesterRealWordErrorLikelihood
5170+ , "confidence" .= phraseSuggesterConfidence
5171+ , "max_errors" .= phraseSuggesterMaxErrors
5172+ , "separator" .= phraseSuggesterSeparator
5173+ , "size" .= phraseSuggesterSize
5174+ , "analyzer" .= phraseSuggesterAnalyzer
5175+ , "shard_size" .= phraseSuggesterShardSize
5176+ , "highlight" .= phraseSuggesterHighlight
5177+ , "collate" .= phraseSuggesterCollate
5180+instance FromJSON PhraseSuggester where
5181+ parseJSON = withObject "PhraseSuggester" parse
5182+ where parse o = PhraseSuggester
5184+ <*> o .:? "gram_size"
5185+ <*> o .:? "real_word_error_likelihood"
5186+ <*> o .:? "confidence"
5187+ <*> o .:? "max_errors"
5188+ <*> o .:? "separator"
5190+ <*> o .:? "analyzer"
5191+ <*> o .:? "shard_size"
5192+ <*> o .:? "highlight"
5193+ <*> o .:? "collate"
5195+mkPhraseSuggester :: FieldName -> PhraseSuggester
5196+mkPhraseSuggester fName =
5197+ PhraseSuggester fName Nothing Nothing Nothing Nothing Nothing Nothing
5198+ Nothing Nothing Nothing Nothing
5200+data PhraseSuggesterHighlighter =
5201+ PhraseSuggesterHighlighter { phraseSuggesterHighlighterPreTag :: Text
5202+ , phraseSuggesterHighlighterPostTag :: Text
5204+ deriving (Show, Generic, Eq, Read)
5206+instance ToJSON PhraseSuggesterHighlighter where
5207+ toJSON PhraseSuggesterHighlighter{..} =
5208+ object [ "pre_tag" .= phraseSuggesterHighlighterPreTag
5209+ , "post_tag" .= phraseSuggesterHighlighterPostTag
5212+instance FromJSON PhraseSuggesterHighlighter where
5213+ parseJSON = withObject "PhraseSuggesterHighlighter" parse
5214+ where parse o = PhraseSuggesterHighlighter
5216+ <*> o .: "post_tag"
5218+data PhraseSuggesterCollate =
5219+ PhraseSuggesterCollate { phraseSuggesterCollateTemplateQuery :: TemplateQueryInline
5220+ , phraseSuggesterCollatePrune :: Bool
5222+ deriving (Show, Generic, Eq, Read)
5224+instance ToJSON PhraseSuggesterCollate where
5225+ toJSON PhraseSuggesterCollate{..} = object [ "query" .= object
5226+ [ "inline" .= (inline phraseSuggesterCollateTemplateQuery)
5228+ , "params" .= (params phraseSuggesterCollateTemplateQuery)
5229+ , "prune" .= phraseSuggesterCollatePrune
5232+instance FromJSON PhraseSuggesterCollate where
5233+ parseJSON (Object o) = do
5234+ query' <- o .: "query"
5235+ inline' <- query' .: "inline"
5236+ params' <- o .: "params"
5237+ prune' <- o .:? "prune" .!= False
5238+ return $ PhraseSuggesterCollate (TemplateQueryInline inline' params') prune'
5239+ parseJSON x = typeMismatch "PhraseSuggesterCollate" x
5241+mkPhraseSuggesterCollate :: TemplateQueryInline -> PhraseSuggesterCollate
5242+mkPhraseSuggesterCollate tQuery = PhraseSuggesterCollate tQuery False
5244+data SuggestOptions =
5245+ SuggestOptions { suggestOptionsText :: Text
5246+ , suggestOptionsScore :: Double
5247+ , suggestOptionsFreq :: Maybe Int
5248+ , suggestOptionsHighlighted :: Maybe Text
5250+ deriving (Eq, Read, Show)
5252+instance FromJSON SuggestOptions where
5253+ parseJSON = withObject "SuggestOptions" parse
5254+ where parse o = SuggestOptions
5258+ <*> o .:? "highlighted"
5260+data SuggestResponse =
5261+ SuggestResponse { suggestResponseText :: Text
5262+ , suggestResponseOffset :: Int
5263+ , suggestResponseLength :: Int
5264+ , suggestResponseOptions :: [SuggestOptions]
5266+ deriving (Eq, Read, Show)
5268+instance FromJSON SuggestResponse where
5269+ parseJSON = withObject "SuggestResponse" parse
5270+ where parse o = SuggestResponse
5276+data NamedSuggestionResponse =
5277+ NamedSuggestionResponse { nsrName :: Text
5278+ , nsrResponses :: [SuggestResponse]
5280+ deriving (Eq, Read, Show)
5282+instance FromJSON NamedSuggestionResponse where
5283+ parseJSON (Object o) = do
5284+ suggestionName' <- case HM.toList o of
5285+ [(x, _)] -> return x
5286+ _ -> fail "error parsing NamedSuggestionResponse name"
5287+ suggestionResponses' <- o .: suggestionName'
5288+ return $ NamedSuggestionResponse suggestionName' suggestionResponses'
5290+ parseJSON x = typeMismatch "NamedSuggestionResponse" x