git.iko.soy/typeable/bloodhound
on master help sign in
Merge remote-tracking branch 'origin/index-aliases'
d1b4b7cChris Allen
bloodhound.cabal+5−2
@@ -45,7 +45,8 @@ library
45 data-default-class,
45 data-default-class,
46 blaze-builder,
46 blaze-builder,
47 unordered-containers,
47 unordered-containers,
48− mtl-compat
48+ mtl-compat,
49+ hashable
49 default-language: Haskell2010
50 default-language: Haskell2010
50
51
51test-suite tests
52test-suite tests
@@ -68,7 +69,9 @@ test-suite tests
68 vector,
69 vector,
69 unordered-containers >= 0.2.5.0 && <0.3,
70 unordered-containers >= 0.2.5.0 && <0.3,
70 mtl,
71 mtl,
71− quickcheck-properties
72+ quickcheck-properties,
73+ derive,
74+ quickcheck-instances
72 default-language: Haskell2010
75 default-language: Haskell2010
73
76
74test-suite doctests
77test-suite doctests
src/Database/Bloodhound/Client.hs+56
@@ -27,6 +27,8 @@ module Database.Bloodhound.Client
27 , indexExists
27 , indexExists
28 , openIndex
28 , openIndex
29 , closeIndex
29 , closeIndex
30+ , updateIndexAliases
31+ , getIndexAliases
30 , putTemplate
32 , putTemplate
31 , templateExists
33 , templateExists
32 , deleteTemplate
34 , deleteTemplate
@@ -55,6 +57,7 @@ module Database.Bloodhound.Client
55 , isVersionConflict
57 , isVersionConflict
56 , isSuccess
58 , isSuccess
57 , isCreated
59 , isCreated
60+ , parseEsResponse
58 )
61 )
59 where
62 where
60
63
@@ -66,8 +69,10 @@ import Control.Monad.IO.Class
66import Data.Aeson
69import Data.Aeson
67import Data.ByteString.Lazy.Builder
70import Data.ByteString.Lazy.Builder
68import qualified Data.ByteString.Lazy.Char8 as L
71import qualified Data.ByteString.Lazy.Char8 as L
72+import Data.Foldable (toList)
69import Data.Ix
73import Data.Ix
70import qualified Data.List as LS (filter)
74import qualified Data.List as LS (filter)
75+import Data.List.NonEmpty (NonEmpty (..))
71import Data.Maybe (fromMaybe, isJust)
76import Data.Maybe (fromMaybe, isJust)
72import Data.Monoid
77import Data.Monoid
73import Data.Text (Text)
78import Data.Text (Text)
@@ -279,6 +284,28 @@ existentialQuery url = do
279 reply <- head url
284 reply <- head url
280 return (reply, respIsTwoHunna reply)
285 return (reply, respIsTwoHunna reply)
281
286
287+
288+-- | Tries to parse a response body as the expected type @a@ and
289+-- failing that tries to parse it as an EsError. All well-formed, JSON
290+-- responses from elasticsearch should fall into these two
291+-- categories. If they don't, a 'StatusCodeException' will be thrown.
292+parseEsResponse :: (MonadBH m, MonadThrow m, FromJSON a) => Reply
293+ -> m (Either EsError a)
294+parseEsResponse reply
295+ | respIsTwoHunna reply = case eitherDecode body of
296+ Right a -> return (Right a)
297+ Left _ -> tryParseError
298+ | otherwise = tryParseError
299+ where body = responseBody reply
300+ stat = responseStatus reply
301+ hdrs = responseHeaders reply
302+ cookies = responseCookieJar reply
303+ tryParseError = case eitherDecode body of
304+ Right e -> return (Left e)
305+ -- this case should not be possible
306+ Left _ -> explode
307+ explode = throwM (StatusCodeException stat hdrs cookies)
308+
282-- | 'indexExists' enables you to check if an index exists. Returns 'Bool'
309-- | 'indexExists' enables you to check if an index exists. Returns 'Bool'
283-- in IO
310-- in IO
284--
311--
@@ -323,6 +350,35 @@ openIndex = openOrCloseIndexes OpenIndex
323closeIndex :: MonadBH m => IndexName -> m Reply
350closeIndex :: MonadBH m => IndexName -> m Reply
324closeIndex = openOrCloseIndexes CloseIndex
351closeIndex = openOrCloseIndexes CloseIndex
325
352
353+
354+-- | 'updateIndexAliases' updates the server's index alias
355+-- table. Operations are atomic. Explained in further detail at
356+-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html>
357+--
358+-- >>> let src = IndexName "a-real-index"
359+-- >>> let aliasName = IndexName "an-alias"
360+-- >>> let iAlias = IndexAlias src (IndexAliasName aliasName)
361+-- >>> let aliasCreate = IndexAliasCreate Nothing Nothing
362+-- >>> respIsTwoHunna <$> runBH' (createIndex defaultIndexSettings src)
363+-- True
364+-- >>> runBH' $ indexExists src
365+-- True
366+-- >>> respIsTwoHunna <$> runBH' (updateIndexAliases (AddAlias iAlias aliasCreate :| []))
367+-- True
368+-- >>> runBH' $ indexExists aliasName
369+-- True
370+updateIndexAliases :: MonadBH m => NonEmpty IndexAliasAction -> m Reply
371+updateIndexAliases actions = bindM2 post url (return body)
372+ where url = joinPath ["_aliases"]
373+ body = Just (encode bodyJSON)
374+ bodyJSON = object [ "actions" .= toList actions]
375+
376+-- | Get all aliases configured on the server.
377+getIndexAliases :: (MonadBH m, MonadThrow m)
378+ => m (Either EsError IndexAliasesSummary)
379+getIndexAliases = parseEsResponse =<< get =<< url
380+ where url = joinPath ["_aliases"]
381+
326-- | 'putTemplate' creates a template given an 'IndexTemplate' and a 'TemplateName'.
382-- | 'putTemplate' creates a template given an 'IndexTemplate' and a 'TemplateName'.
327-- Explained in further detail at
383-- Explained in further detail at
328-- <https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html>
384-- <https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html>
src/Database/Bloodhound/Types.hs+780−196
@@ -1,8 +1,10 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
1{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE DeriveGeneric #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE NoMonomorphismRestriction #-}
6{-# LANGUAGE OverloadedStrings #-}
8{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE RecordWildCards #-}
9{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE UndecidableInstances #-}
10{-# LANGUAGE UndecidableInstances #-}
@@ -62,6 +64,16 @@ module Database.Bloodhound.Types
62 , EsResult(..)
64 , EsResult(..)
63 , EsResultFound(..)
65 , EsResultFound(..)
64 , EsError(..)
66 , EsError(..)
67+ , IndexAlias(..)
68+ , IndexAliasName(..)
69+ , IndexAliasAction(..)
70+ , IndexAliasCreate(..)
71+ , IndexAliasSummary(..)
72+ , IndexAliasesSummary(..)
73+ , AliasRouting(..)
74+ , SearchAliasRouting(..)
75+ , IndexAliasRouting(..)
76+ , RoutingValue(..)
65 , DocVersion
77 , DocVersion
66 , ExternalDocVersion(..)
78 , ExternalDocVersion(..)
67 , VersionControl(..)
79 , VersionControl(..)
@@ -237,9 +249,12 @@ import Control.Monad.Reader
237import Control.Monad.State
249import Control.Monad.State
238import Control.Monad.Writer
250import Control.Monad.Writer
239import Data.Aeson
251import Data.Aeson
240−import Data.Aeson.Types (Pair, emptyObject, parseMaybe)
252+import Data.Aeson.Types (Pair, Parser, emptyObject,
253+ parseMaybe)
241import qualified Data.ByteString.Lazy.Char8 as L
254import qualified Data.ByteString.Lazy.Char8 as L
255+import Data.Char
256+import Data.Hashable (Hashable)
242−import qualified Data.HashMap.Strict as HM (union)
257+import qualified Data.HashMap.Strict as HM
243import Data.List (foldl', nub)
258import Data.List (foldl', nub)
244import Data.List.NonEmpty (NonEmpty (..), toList)
259import Data.List.NonEmpty (NonEmpty (..), toList)
245import qualified Data.Map.Strict as M
260import qualified Data.Map.Strict as M
@@ -247,6 +262,8 @@ import Data.Maybe
247import Data.Text (Text)
262import Data.Text (Text)
248import qualified Data.Text as T
263import qualified Data.Text as T
249import Data.Time.Clock (UTCTime)
264import Data.Time.Clock (UTCTime)
265+import qualified Data.Traversable as DT
266+import Data.Typeable (Typeable)
250import qualified Data.Vector as V
267import qualified Data.Vector as V
251import GHC.Enum
268import GHC.Enum
252import GHC.Generics (Generic)
269import GHC.Generics (Generic)
@@ -320,7 +337,7 @@ data Version = Version { number :: Text
320 , build_hash :: Text
337 , build_hash :: Text
321 , build_timestamp :: UTCTime
338 , build_timestamp :: UTCTime
322 , build_snapshot :: Bool
339 , build_snapshot :: Bool
323− , lucene_version :: Text } deriving (Eq, Show, Generic)
340+ , lucene_version :: Text } deriving (Eq, Show, Generic, Typeable)
324
341
325{-| 'Status' is a data type for describing the JSON body returned by
342{-| 'Status' is a data type for describing the JSON body returned by
326 Elasticsearch when you query its status. This was deprecated in 1.2.0.
343 Elasticsearch when you query its status. This was deprecated in 1.2.0.
@@ -430,6 +447,33 @@ data EsResultFound a = EsResultFound { _version :: DocVersion
430data EsError = EsError { errorStatus :: Int
447data EsError = EsError { errorStatus :: Int
431 , errorMessage :: Text } deriving (Eq, Show)
448 , errorMessage :: Text } deriving (Eq, Show)
432
449
450+data IndexAlias = IndexAlias { srcIndex :: IndexName
451+ , indexAlias :: IndexAliasName } deriving (Eq, Show)
452+
453+newtype IndexAliasName = IndexAliasName { indexAliasName :: IndexName } deriving (Eq, Show, ToJSON)
454+
455+data IndexAliasAction = AddAlias IndexAlias IndexAliasCreate
456+ | RemoveAlias IndexAlias deriving (Show, Eq, Typeable)
457+
458+data IndexAliasCreate = IndexAliasCreate { aliasCreateRouting :: Maybe AliasRouting
459+ , aliasCreateFilter :: Maybe Filter}
460+ deriving (Show, Eq, Typeable)
461+
462+data AliasRouting = AllAliasRouting RoutingValue
463+ | GranularAliasRouting (Maybe SearchAliasRouting) (Maybe IndexAliasRouting)
464+ deriving (Show, Eq, Typeable)
465+
466+newtype SearchAliasRouting = SearchAliasRouting (NonEmpty RoutingValue) deriving (Show, Eq, Typeable)
467+
468+newtype IndexAliasRouting = IndexAliasRouting RoutingValue deriving (Show, Eq, ToJSON, FromJSON, Typeable)
469+
470+newtype RoutingValue = RoutingValue { routingValue :: Text } deriving (Show, Eq, ToJSON, FromJSON, Typeable)
471+
472+newtype IndexAliasesSummary = IndexAliasesSummary { indexAliasesSummary :: [IndexAliasSummary] } deriving (Show, Eq, Typeable)
473+
474+{-| 'IndexAliasSummary' is a summary of an index alias configured for a server. -}
475+data IndexAliasSummary = IndexAliasSummary { indexAliasSummaryAlias :: IndexAlias
476+ , indexAliasSummaryCreate :: IndexAliasCreate} deriving (Show, Eq)
433
477
434{-| 'DocVersion' is an integer version number for a document between 1
478{-| 'DocVersion' is an integer version number for a document between 1
435and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
479and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
@@ -581,15 +625,15 @@ type PrefixValue = Text
581{-| 'BooleanOperator' is the usual And/Or operators with an ES compatible
625{-| 'BooleanOperator' is the usual And/Or operators with an ES compatible
582 JSON encoding baked in. Used all over the place.
626 JSON encoding baked in. Used all over the place.
583-}
627-}
584−data BooleanOperator = And | Or deriving (Eq, Show)
628+data BooleanOperator = And | Or deriving (Eq, Show, Typeable)
585
629
586{-| 'ShardCount' is part of 'IndexSettings'
630{-| 'ShardCount' is part of 'IndexSettings'
587-}
631-}
588−newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic)
632+newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
589
633
590{-| 'ReplicaCount' is part of 'IndexSettings'
634{-| 'ReplicaCount' is part of 'IndexSettings'
591-}
635-}
592−newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic)
636+newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
593
637
594{-| 'Server' is used with the client functions to point at the ES instance
638{-| 'Server' is used with the client functions to point at the ES instance
595-}
639-}
@@ -597,35 +641,35 @@ newtype Server = Server Text deriving (Eq, Show)
597
641
598{-| 'IndexName' is used to describe which index to query/create/delete
642{-| 'IndexName' is used to describe which index to query/create/delete
599-}
643-}
600−newtype IndexName = IndexName Text deriving (Eq, Generic, Show)
644+newtype IndexName = IndexName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
601
645
602{-| 'TemplateName' is used to describe which template to query/create/delete
646{-| 'TemplateName' is used to describe which template to query/create/delete
603-}
647-}
604−newtype TemplateName = TemplateName Text deriving (Eq, Show, Generic)
648+newtype TemplateName = TemplateName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
605
649
606{-| 'TemplatePattern' represents a pattern which is matched against index names
650{-| 'TemplatePattern' represents a pattern which is matched against index names
607-}
651-}
608−newtype TemplatePattern = TemplatePattern Text deriving (Eq, Show, Generic)
652+newtype TemplatePattern = TemplatePattern Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
609
653
610{-| 'MappingName' is part of mappings which are how ES describes and schematizes
654{-| 'MappingName' is part of mappings which are how ES describes and schematizes
611 the data in the indices.
655 the data in the indices.
612-}
656-}
613−newtype MappingName = MappingName Text deriving (Eq, Generic, Show)
657+newtype MappingName = MappingName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
614
658
615{-| 'DocId' is a generic wrapper value for expressing unique Document IDs.
659{-| 'DocId' is a generic wrapper value for expressing unique Document IDs.
616 Can be set by the user or created by ES itself. Often used in client
660 Can be set by the user or created by ES itself. Often used in client
617 functions for poking at specific documents.
661 functions for poking at specific documents.
618-}
662-}
619−newtype DocId = DocId Text deriving (Eq, Generic, Show)
663+newtype DocId = DocId Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
620
664
621{-| 'QueryString' is used to wrap query text bodies, be they human written or not.
665{-| 'QueryString' is used to wrap query text bodies, be they human written or not.
622-}
666-}
623−newtype QueryString = QueryString Text deriving (Eq, Generic, Show)
667+newtype QueryString = QueryString Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
624
668
625{-| 'FieldName' is used all over the place wherever a specific field within
669{-| 'FieldName' is used all over the place wherever a specific field within
626 a document needs to be specified, usually in 'Query's or 'Filter's.
670 a document needs to be specified, usually in 'Query's or 'Filter's.
627-}
671-}
628−newtype FieldName = FieldName Text deriving (Eq, Show)
672+newtype FieldName = FieldName Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
629
673
630
674
631{-| 'Script' is often used in place of 'FieldName' to specify more
675{-| 'Script' is often used in place of 'FieldName' to specify more
@@ -636,100 +680,98 @@ newtype Script = Script { scriptText :: Text } deriving (Eq, Show)
636{-| 'CacheName' is used in 'RegexpFilter' for describing the
680{-| 'CacheName' is used in 'RegexpFilter' for describing the
637 'CacheKey' keyed caching behavior.
681 'CacheKey' keyed caching behavior.
638-}
682-}
639−newtype CacheName = CacheName Text deriving (Eq, Show)
683+newtype CacheName = CacheName Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
640
684
641{-| 'CacheKey' is used in 'RegexpFilter' to key regex caching.
685{-| 'CacheKey' is used in 'RegexpFilter' to key regex caching.
642-}
686-}
643newtype CacheKey =
687newtype CacheKey =
644− CacheKey Text deriving (Eq, Show)
688+ CacheKey Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
645newtype Existence =
689newtype Existence =
646− Existence Bool deriving (Eq, Show)
690+ Existence Bool deriving (Eq, Show, ToJSON, FromJSON, Typeable)
647newtype NullValue =
691newtype NullValue =
648− NullValue Bool deriving (Eq, Show)
692+ NullValue Bool deriving (Eq, Show, ToJSON, FromJSON, Typeable)
649newtype CutoffFrequency =
693newtype CutoffFrequency =
650− CutoffFrequency Double deriving (Eq, Show, Generic)
694+ CutoffFrequency Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
651newtype Analyzer =
695newtype Analyzer =
652− Analyzer Text deriving (Eq, Show, Generic)
696+ Analyzer Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
653newtype MaxExpansions =
697newtype MaxExpansions =
654− MaxExpansions Int deriving (Eq, Show, Generic)
698+ MaxExpansions Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
655
699
656{-| 'Lenient', if set to true, will cause format based failures to be
700{-| 'Lenient', if set to true, will cause format based failures to be
657 ignored. I don't know what the bloody default is, Elasticsearch
701 ignored. I don't know what the bloody default is, Elasticsearch
658 documentation didn't say what it was. Let me know if you figure it out.
702 documentation didn't say what it was. Let me know if you figure it out.
659-}
703-}
660newtype Lenient =
704newtype Lenient =
661− Lenient Bool deriving (Eq, Show, Generic)
705+ Lenient Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
662newtype Tiebreaker =
706newtype Tiebreaker =
663− Tiebreaker Double deriving (Eq, Show, Generic)
707+ Tiebreaker Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
664newtype Boost =
708newtype Boost =
665− Boost Double deriving (Eq, Show, Generic)
709+ Boost Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
666newtype BoostTerms =
710newtype BoostTerms =
667− BoostTerms Double deriving (Eq, Show, Generic)
711+ BoostTerms Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
668
712
669{-| 'MinimumMatch' controls how many should clauses in the bool query should
713{-| 'MinimumMatch' controls how many should clauses in the bool query should
670 match. Can be an absolute value (2) or a percentage (30%) or a
714 match. Can be an absolute value (2) or a percentage (30%) or a
671 combination of both.
715 combination of both.
672-}
716-}
673newtype MinimumMatch =
717newtype MinimumMatch =
674− MinimumMatch Int deriving (Eq, Show, Generic)
718+ MinimumMatch Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
675−newtype MinimumMatchText =
676− MinimumMatchText Text deriving (Eq, Show)
677newtype DisableCoord =
719newtype DisableCoord =
678− DisableCoord Bool deriving (Eq, Show, Generic)
720+ DisableCoord Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
679newtype IgnoreTermFrequency =
721newtype IgnoreTermFrequency =
680− IgnoreTermFrequency Bool deriving (Eq, Show, Generic)
722+ IgnoreTermFrequency Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
681newtype MinimumTermFrequency =
723newtype MinimumTermFrequency =
682− MinimumTermFrequency Int deriving (Eq, Show, Generic)
724+ MinimumTermFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
683newtype MaxQueryTerms =
725newtype MaxQueryTerms =
684− MaxQueryTerms Int deriving (Eq, Show, Generic)
726+ MaxQueryTerms Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
685newtype Fuzziness =
727newtype Fuzziness =
686− Fuzziness Double deriving (Eq, Show, Generic)
728+ Fuzziness Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
687
729
688{-| 'PrefixLength' is the prefix length used in queries, defaults to 0. -}
730{-| 'PrefixLength' is the prefix length used in queries, defaults to 0. -}
689newtype PrefixLength =
731newtype PrefixLength =
690− PrefixLength Int deriving (Eq, Show, Generic)
732+ PrefixLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
691newtype TypeName =
733newtype TypeName =
692− TypeName Text deriving (Eq, Show, Generic)
734+ TypeName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
693newtype PercentMatch =
735newtype PercentMatch =
694− PercentMatch Double deriving (Eq, Show, Generic)
736+ PercentMatch Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
695newtype StopWord =
737newtype StopWord =
696− StopWord Text deriving (Eq, Show, Generic)
738+ StopWord Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
697newtype QueryPath =
739newtype QueryPath =
698− QueryPath Text deriving (Eq, Show, Generic)
740+ QueryPath Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
699
741
700{-| Allowing a wildcard at the beginning of a word (eg "*ing") is particularly
742{-| Allowing a wildcard at the beginning of a word (eg "*ing") is particularly
701 heavy, because all terms in the index need to be examined, just in case
743 heavy, because all terms in the index need to be examined, just in case
702 they match. Leading wildcards can be disabled by setting
744 they match. Leading wildcards can be disabled by setting
703 'AllowLeadingWildcard' to false. -}
745 'AllowLeadingWildcard' to false. -}
704newtype AllowLeadingWildcard =
746newtype AllowLeadingWildcard =
705− AllowLeadingWildcard Bool deriving (Eq, Show, Generic)
747+ AllowLeadingWildcard Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
706newtype LowercaseExpanded =
748newtype LowercaseExpanded =
707− LowercaseExpanded Bool deriving (Eq, Show, Generic)
749+ LowercaseExpanded Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
708newtype EnablePositionIncrements =
750newtype EnablePositionIncrements =
709− EnablePositionIncrements Bool deriving (Eq, Show, Generic)
751+ EnablePositionIncrements Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
710
752
711{-| By default, wildcard terms in a query are not analyzed.
753{-| By default, wildcard terms in a query are not analyzed.
712 Setting 'AnalyzeWildcard' to true enables best-effort analysis.
754 Setting 'AnalyzeWildcard' to true enables best-effort analysis.
713-}
755-}
714−newtype AnalyzeWildcard = AnalyzeWildcard Bool deriving (Eq, Show, Generic)
756+newtype AnalyzeWildcard = AnalyzeWildcard Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
715
757
716{-| 'GeneratePhraseQueries' defaults to false.
758{-| 'GeneratePhraseQueries' defaults to false.
717-}
759-}
718newtype GeneratePhraseQueries =
760newtype GeneratePhraseQueries =
719− GeneratePhraseQueries Bool deriving (Eq, Show, Generic)
761+ GeneratePhraseQueries Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
720
762
721{-| 'Locale' is used for string conversions - defaults to ROOT.
763{-| 'Locale' is used for string conversions - defaults to ROOT.
722-}
764-}
723−newtype Locale = Locale Text deriving (Eq, Show, Generic)
765+newtype Locale = Locale Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
724−newtype MaxWordLength = MaxWordLength Int deriving (Eq, Show, Generic)
766+newtype MaxWordLength = MaxWordLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
725−newtype MinWordLength = MinWordLength Int deriving (Eq, Show, Generic)
767+newtype MinWordLength = MinWordLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
726
768
727{-| 'PhraseSlop' sets the default slop for phrases, 0 means exact
769{-| 'PhraseSlop' sets the default slop for phrases, 0 means exact
728 phrase matches. Default is 0.
770 phrase matches. Default is 0.
729-}
771-}
730−newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show, Generic)
772+newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
731−newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show, Generic)
773+newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
732−newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show, Generic)
774+newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
733
775
734{-| 'unpackId' is a silly convenience function that gets used once.
776{-| 'unpackId' is a silly convenience function that gets used once.
735-}
777-}
@@ -832,7 +874,7 @@ data HighlightTag = TagSchema Text
832
874
833data Query =
875data Query =
834 TermQuery Term (Maybe Boost)
876 TermQuery Term (Maybe Boost)
835− | TermsQuery (NonEmpty Term)
877+ | TermsQuery Text (NonEmpty Text)
836 | QueryMatchQuery MatchQuery
878 | QueryMatchQuery MatchQuery
837 | QueryMultiMatchQuery MultiMatchQuery
879 | QueryMultiMatchQuery MultiMatchQuery
838 | QueryBoolQuery BoolQuery
880 | QueryBoolQuery BoolQuery
@@ -858,19 +900,19 @@ data Query =
858 | QuerySimpleQueryStringQuery SimpleQueryStringQuery
900 | QuerySimpleQueryStringQuery SimpleQueryStringQuery
859 | QueryRangeQuery RangeQuery
901 | QueryRangeQuery RangeQuery
860 | QueryRegexpQuery RegexpQuery
902 | QueryRegexpQuery RegexpQuery
861− deriving (Eq, Show)
903+ deriving (Eq, Show, Typeable)
862
904
863data RegexpQuery =
905data RegexpQuery =
864 RegexpQuery { regexpQueryField :: FieldName
906 RegexpQuery { regexpQueryField :: FieldName
865 , regexpQuery :: Regexp
907 , regexpQuery :: Regexp
866 , regexpQueryFlags :: RegexpFlags
908 , regexpQueryFlags :: RegexpFlags
867 , regexpQueryBoost :: Maybe Boost
909 , regexpQueryBoost :: Maybe Boost
868− } deriving (Eq, Show)
910+ } deriving (Eq, Show, Typeable)
869
911
870data RangeQuery =
912data RangeQuery =
871 RangeQuery { rangeQueryField :: FieldName
913 RangeQuery { rangeQueryField :: FieldName
872 , rangeQueryRange :: RangeValue
914 , rangeQueryRange :: RangeValue
873− , rangeQueryBoost :: Boost } deriving (Eq, Show)
915+ , rangeQueryBoost :: Boost } deriving (Eq, Show, Typeable)
874
916
875mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
917mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
876mkRangeQuery f r = RangeQuery f r (Boost 1.0)
918mkRangeQuery f r = RangeQuery f r (Boost 1.0)
@@ -881,10 +923,10 @@ data SimpleQueryStringQuery =
881 , simpleQueryStringField :: Maybe FieldOrFields
923 , simpleQueryStringField :: Maybe FieldOrFields
882 , simpleQueryStringOperator :: Maybe BooleanOperator
924 , simpleQueryStringOperator :: Maybe BooleanOperator
883 , simpleQueryStringAnalyzer :: Maybe Analyzer
925 , simpleQueryStringAnalyzer :: Maybe Analyzer
884− , simpleQueryStringFlags :: Maybe [SimpleQueryFlag]
926+ , simpleQueryStringFlags :: Maybe (NonEmpty SimpleQueryFlag)
885 , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
927 , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
886 , simpleQueryStringLocale :: Maybe Locale
928 , simpleQueryStringLocale :: Maybe Locale
887− } deriving (Eq, Show)
929+ } deriving (Eq, Show, Typeable)
888
930
889data SimpleQueryFlag =
931data SimpleQueryFlag =
890 SimpleQueryAll
932 SimpleQueryAll
@@ -898,7 +940,7 @@ data SimpleQueryFlag =
898 | SimpleQueryWhitespace
940 | SimpleQueryWhitespace
899 | SimpleQueryFuzzy
941 | SimpleQueryFuzzy
900 | SimpleQueryNear
942 | SimpleQueryNear
901− | SimpleQuerySlop deriving (Eq, Show)
943+ | SimpleQuerySlop deriving (Eq, Show, Typeable)
902
944
903-- use_dis_max and tie_breaker when fields are plural?
945-- use_dis_max and tie_breaker when fields are plural?
904data QueryStringQuery =
946data QueryStringQuery =
@@ -920,7 +962,7 @@ data QueryStringQuery =
920 , queryStringMinimumShouldMatch :: Maybe MinimumMatch
962 , queryStringMinimumShouldMatch :: Maybe MinimumMatch
921 , queryStringLenient :: Maybe Lenient
963 , queryStringLenient :: Maybe Lenient
922 , queryStringLocale :: Maybe Locale
964 , queryStringLocale :: Maybe Locale
923− } deriving (Eq, Show)
965+ } deriving (Eq, Show, Typeable)
924
966
925mkQueryStringQuery :: QueryString -> QueryStringQuery
967mkQueryStringQuery :: QueryString -> QueryStringQuery
926mkQueryStringQuery qs =
968mkQueryStringQuery qs =
@@ -931,19 +973,19 @@ mkQueryStringQuery qs =
931 Nothing Nothing
973 Nothing Nothing
932
974
933data FieldOrFields = FofField FieldName
975data FieldOrFields = FofField FieldName
934− | FofFields [FieldName] deriving (Eq, Show)
976+ | FofFields (NonEmpty FieldName) deriving (Eq, Show, Typeable)
935
977
936data PrefixQuery =
978data PrefixQuery =
937 PrefixQuery
979 PrefixQuery
938 { prefixQueryField :: FieldName
980 { prefixQueryField :: FieldName
939 , prefixQueryPrefixValue :: Text
981 , prefixQueryPrefixValue :: Text
940− , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show)
982+ , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show, Typeable)
941
983
942data NestedQuery =
984data NestedQuery =
943 NestedQuery
985 NestedQuery
944 { nestedQueryPath :: QueryPath
986 { nestedQueryPath :: QueryPath
945 , nestedQueryScoreType :: ScoreType
987 , nestedQueryScoreType :: ScoreType
946− , nestedQuery :: Query } deriving (Eq, Show)
988+ , nestedQuery :: Query } deriving (Eq, Show, Typeable)
947
989
948data MoreLikeThisFieldQuery =
990data MoreLikeThisFieldQuery =
949 MoreLikeThisFieldQuery
991 MoreLikeThisFieldQuery
@@ -953,7 +995,7 @@ data MoreLikeThisFieldQuery =
953 , moreLikeThisFieldPercentMatch :: Maybe PercentMatch
995 , moreLikeThisFieldPercentMatch :: Maybe PercentMatch
954 , moreLikeThisFieldMinimumTermFreq :: Maybe MinimumTermFrequency
996 , moreLikeThisFieldMinimumTermFreq :: Maybe MinimumTermFrequency
955 , moreLikeThisFieldMaxQueryTerms :: Maybe MaxQueryTerms
997 , moreLikeThisFieldMaxQueryTerms :: Maybe MaxQueryTerms
956− , moreLikeThisFieldStopWords :: Maybe [StopWord]
998+ , moreLikeThisFieldStopWords :: Maybe (NonEmpty StopWord)
957 , moreLikeThisFieldMinDocFrequency :: Maybe MinDocFrequency
999 , moreLikeThisFieldMinDocFrequency :: Maybe MinDocFrequency
958 , moreLikeThisFieldMaxDocFrequency :: Maybe MaxDocFrequency
1000 , moreLikeThisFieldMaxDocFrequency :: Maybe MaxDocFrequency
959 , moreLikeThisFieldMinWordLength :: Maybe MinWordLength
1001 , moreLikeThisFieldMinWordLength :: Maybe MinWordLength
@@ -961,17 +1003,17 @@ data MoreLikeThisFieldQuery =
961 , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
1003 , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
962 , moreLikeThisFieldBoost :: Maybe Boost
1004 , moreLikeThisFieldBoost :: Maybe Boost
963 , moreLikeThisFieldAnalyzer :: Maybe Analyzer
1005 , moreLikeThisFieldAnalyzer :: Maybe Analyzer
964− } deriving (Eq, Show)
1006+ } deriving (Eq, Show, Typeable)
965
1007
966data MoreLikeThisQuery =
1008data MoreLikeThisQuery =
967 MoreLikeThisQuery
1009 MoreLikeThisQuery
968 { moreLikeThisText :: Text
1010 { moreLikeThisText :: Text
969− , moreLikeThisFields :: Maybe [FieldName]
1011+ , moreLikeThisFields :: Maybe (NonEmpty FieldName)
970 -- default 0.3 (30%)
1012 -- default 0.3 (30%)
971 , moreLikeThisPercentMatch :: Maybe PercentMatch
1013 , moreLikeThisPercentMatch :: Maybe PercentMatch
972 , moreLikeThisMinimumTermFreq :: Maybe MinimumTermFrequency
1014 , moreLikeThisMinimumTermFreq :: Maybe MinimumTermFrequency
973 , moreLikeThisMaxQueryTerms :: Maybe MaxQueryTerms
1015 , moreLikeThisMaxQueryTerms :: Maybe MaxQueryTerms
974− , moreLikeThisStopWords :: Maybe [StopWord]
1016+ , moreLikeThisStopWords :: Maybe (NonEmpty StopWord)
975 , moreLikeThisMinDocFrequency :: Maybe MinDocFrequency
1017 , moreLikeThisMinDocFrequency :: Maybe MinDocFrequency
976 , moreLikeThisMaxDocFrequency :: Maybe MaxDocFrequency
1018 , moreLikeThisMaxDocFrequency :: Maybe MaxDocFrequency
977 , moreLikeThisMinWordLength :: Maybe MinWordLength
1019 , moreLikeThisMinWordLength :: Maybe MinWordLength
@@ -979,32 +1021,32 @@ data MoreLikeThisQuery =
979 , moreLikeThisBoostTerms :: Maybe BoostTerms
1021 , moreLikeThisBoostTerms :: Maybe BoostTerms
980 , moreLikeThisBoost :: Maybe Boost
1022 , moreLikeThisBoost :: Maybe Boost
981 , moreLikeThisAnalyzer :: Maybe Analyzer
1023 , moreLikeThisAnalyzer :: Maybe Analyzer
982− } deriving (Eq, Show)
1024+ } deriving (Eq, Show, Typeable)
983
1025
984data IndicesQuery =
1026data IndicesQuery =
985 IndicesQuery
1027 IndicesQuery
986 { indicesQueryIndices :: [IndexName]
1028 { indicesQueryIndices :: [IndexName]
987 , indicesQuery :: Query
1029 , indicesQuery :: Query
988 -- default "all"
1030 -- default "all"
989− , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show)
1031+ , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show, Typeable)
990
1032
991data HasParentQuery =
1033data HasParentQuery =
992 HasParentQuery
1034 HasParentQuery
993 { hasParentQueryType :: TypeName
1035 { hasParentQueryType :: TypeName
994 , hasParentQuery :: Query
1036 , hasParentQuery :: Query
995− , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show)
1037+ , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Typeable)
996
1038
997data HasChildQuery =
1039data HasChildQuery =
998 HasChildQuery
1040 HasChildQuery
999 { hasChildQueryType :: TypeName
1041 { hasChildQueryType :: TypeName
1000 , hasChildQuery :: Query
1042 , hasChildQuery :: Query
1001− , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show)
1043+ , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Typeable)
1002
1044
1003data ScoreType =
1045data ScoreType =
1004 ScoreTypeMax
1046 ScoreTypeMax
1005 | ScoreTypeSum
1047 | ScoreTypeSum
1006 | ScoreTypeAvg
1048 | ScoreTypeAvg
1007− | ScoreTypeNone deriving (Eq, Show)
1049+ | ScoreTypeNone deriving (Eq, Show, Typeable)
1008
1050
1009data FuzzyQuery =
1051data FuzzyQuery =
1010 FuzzyQuery { fuzzyQueryField :: FieldName
1052 FuzzyQuery { fuzzyQueryField :: FieldName
@@ -1013,7 +1055,7 @@ data FuzzyQuery =
1013 , fuzzyQueryMaxExpansions :: MaxExpansions
1055 , fuzzyQueryMaxExpansions :: MaxExpansions
1014 , fuzzyQueryFuzziness :: Fuzziness
1056 , fuzzyQueryFuzziness :: Fuzziness
1015 , fuzzyQueryBoost :: Maybe Boost
1057 , fuzzyQueryBoost :: Maybe Boost
1016− } deriving (Eq, Show)
1058+ } deriving (Eq, Show, Typeable)
1017
1059
1018data FuzzyLikeFieldQuery =
1060data FuzzyLikeFieldQuery =
1019 FuzzyLikeFieldQuery
1061 FuzzyLikeFieldQuery
@@ -1026,7 +1068,7 @@ data FuzzyLikeFieldQuery =
1026 , fuzzyLikeFieldPrefixLength :: PrefixLength
1068 , fuzzyLikeFieldPrefixLength :: PrefixLength
1027 , fuzzyLikeFieldBoost :: Boost
1069 , fuzzyLikeFieldBoost :: Boost
1028 , fuzzyLikeFieldAnalyzer :: Maybe Analyzer
1070 , fuzzyLikeFieldAnalyzer :: Maybe Analyzer
1029− } deriving (Eq, Show)
1071+ } deriving (Eq, Show, Typeable)
1030
1072
1031data FuzzyLikeThisQuery =
1073data FuzzyLikeThisQuery =
1032 FuzzyLikeThisQuery
1074 FuzzyLikeThisQuery
@@ -1038,19 +1080,19 @@ data FuzzyLikeThisQuery =
1038 , fuzzyLikePrefixLength :: PrefixLength
1080 , fuzzyLikePrefixLength :: PrefixLength
1039 , fuzzyLikeBoost :: Boost
1081 , fuzzyLikeBoost :: Boost
1040 , fuzzyLikeAnalyzer :: Maybe Analyzer
1082 , fuzzyLikeAnalyzer :: Maybe Analyzer
1041− } deriving (Eq, Show)
1083+ } deriving (Eq, Show, Typeable)
1042
1084
1043data FilteredQuery =
1085data FilteredQuery =
1044 FilteredQuery
1086 FilteredQuery
1045 { filteredQuery :: Query
1087 { filteredQuery :: Query
1046− , filteredFilter :: Filter } deriving (Eq, Show)
1088+ , filteredFilter :: Filter } deriving (Eq, Show, Typeable)
1047
1089
1048data DisMaxQuery =
1090data DisMaxQuery =
1049 DisMaxQuery { disMaxQueries :: [Query]
1091 DisMaxQuery { disMaxQueries :: [Query]
1050 -- default 0.0
1092 -- default 0.0
1051 , disMaxTiebreaker :: Tiebreaker
1093 , disMaxTiebreaker :: Tiebreaker
1052 , disMaxBoost :: Maybe Boost
1094 , disMaxBoost :: Maybe Boost
1053− } deriving (Eq, Show)
1095+ } deriving (Eq, Show, Typeable)
1054
1096
1055data MatchQuery =
1097data MatchQuery =
1056 MatchQuery { matchQueryField :: FieldName
1098 MatchQuery { matchQueryField :: FieldName
@@ -1062,7 +1104,7 @@ data MatchQuery =
1062 , matchQueryAnalyzer :: Maybe Analyzer
1104 , matchQueryAnalyzer :: Maybe Analyzer
1063 , matchQueryMaxExpansions :: Maybe MaxExpansions
1105 , matchQueryMaxExpansions :: Maybe MaxExpansions
1064 , matchQueryLenient :: Maybe Lenient
1106 , matchQueryLenient :: Maybe Lenient
1065− , matchQueryBoost :: Maybe Boost } deriving (Eq, Show)
1107+ , matchQueryBoost :: Maybe Boost } deriving (Eq, Show, Typeable)
1066
1108
1067{-| 'mkMatchQuery' is a convenience function that defaults the less common parameters,
1109{-| 'mkMatchQuery' is a convenience function that defaults the less common parameters,
1068 enabling you to provide only the 'FieldName' and 'QueryString' to make a 'MatchQuery'
1110 enabling you to provide only the 'FieldName' and 'QueryString' to make a 'MatchQuery'
@@ -1072,7 +1114,7 @@ mkMatchQuery field query = MatchQuery field query Or ZeroTermsNone Nothing Nothi
1072
1114
1073data MatchQueryType =
1115data MatchQueryType =
1074 MatchPhrase
1116 MatchPhrase
1075− | MatchPhrasePrefix deriving (Eq, Show)
1117+ | MatchPhrasePrefix deriving (Eq, Show, Typeable)
1076
1118
1077data MultiMatchQuery =
1119data MultiMatchQuery =
1078 MultiMatchQuery { multiMatchQueryFields :: [FieldName]
1120 MultiMatchQuery { multiMatchQueryFields :: [FieldName]
@@ -1084,7 +1126,7 @@ data MultiMatchQuery =
1084 , multiMatchQueryCutoffFrequency :: Maybe CutoffFrequency
1126 , multiMatchQueryCutoffFrequency :: Maybe CutoffFrequency
1085 , multiMatchQueryAnalyzer :: Maybe Analyzer
1127 , multiMatchQueryAnalyzer :: Maybe Analyzer
1086 , multiMatchQueryMaxExpansions :: Maybe MaxExpansions
1128 , multiMatchQueryMaxExpansions :: Maybe MaxExpansions
1087− , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show)
1129+ , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show, Typeable)
1088
1130
1089{-| 'mkMultiMatchQuery' is a convenience function that defaults the less common parameters,
1131{-| 'mkMultiMatchQuery' is a convenience function that defaults the less common parameters,
1090 enabling you to provide only the list of 'FieldName's and 'QueryString' to
1132 enabling you to provide only the list of 'FieldName's and 'QueryString' to
@@ -1101,7 +1143,7 @@ data MultiMatchQueryType =
1101 | MultiMatchMostFields
1143 | MultiMatchMostFields
1102 | MultiMatchCrossFields
1144 | MultiMatchCrossFields
1103 | MultiMatchPhrase
1145 | MultiMatchPhrase
1104− | MultiMatchPhrasePrefix deriving (Eq, Show)
1146+ | MultiMatchPhrasePrefix deriving (Eq, Show, Typeable)
1105
1147
1106data BoolQuery =
1148data BoolQuery =
1107 BoolQuery { boolQueryMustMatch :: [Query]
1149 BoolQuery { boolQueryMustMatch :: [Query]
@@ -1110,7 +1152,7 @@ data BoolQuery =
1110 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
1152 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
1111 , boolQueryBoost :: Maybe Boost
1153 , boolQueryBoost :: Maybe Boost
1112 , boolQueryDisableCoord :: Maybe DisableCoord
1154 , boolQueryDisableCoord :: Maybe DisableCoord
1113− } deriving (Eq, Show)
1155+ } deriving (Eq, Show, Typeable)
1114
1156
1115mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
1157mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
1116mkBoolQuery must mustNot should =
1158mkBoolQuery must mustNot should =
@@ -1119,7 +1161,7 @@ mkBoolQuery must mustNot should =
1119data BoostingQuery =
1161data BoostingQuery =
1120 BoostingQuery { positiveQuery :: Query
1162 BoostingQuery { positiveQuery :: Query
1121 , negativeQuery :: Query
1163 , negativeQuery :: Query
1122− , negativeBoost :: Boost } deriving (Eq, Show)
1164+ , negativeBoost :: Boost } deriving (Eq, Show, Typeable)
1123
1165
1124data CommonTermsQuery =
1166data CommonTermsQuery =
1125 CommonTermsQuery { commonField :: FieldName
1167 CommonTermsQuery { commonField :: FieldName
@@ -1131,16 +1173,16 @@ data CommonTermsQuery =
1131 , commonBoost :: Maybe Boost
1173 , commonBoost :: Maybe Boost
1132 , commonAnalyzer :: Maybe Analyzer
1174 , commonAnalyzer :: Maybe Analyzer
1133 , commonDisableCoord :: Maybe DisableCoord
1175 , commonDisableCoord :: Maybe DisableCoord
1134− } deriving (Eq, Show)
1176+ } deriving (Eq, Show, Typeable)
1135
1177
1136data CommonMinimumMatch =
1178data CommonMinimumMatch =
1137 CommonMinimumMatchHighLow MinimumMatchHighLow
1179 CommonMinimumMatchHighLow MinimumMatchHighLow
1138 | CommonMinimumMatch MinimumMatch
1180 | CommonMinimumMatch MinimumMatch
1139− deriving (Eq, Show)
1181+ deriving (Eq, Show, Typeable)
1140
1182
1141data MinimumMatchHighLow =
1183data MinimumMatchHighLow =
1142 MinimumMatchHighLow { lowFreq :: MinimumMatch
1184 MinimumMatchHighLow { lowFreq :: MinimumMatch
1143− , highFreq :: MinimumMatch } deriving (Eq, Show)
1185+ , highFreq :: MinimumMatch } deriving (Eq, Show, Typeable)
1144
1186
1145data Filter = AndFilter [Filter] Cache
1187data Filter = AndFilter [Filter] Cache
1146 | OrFilter [Filter] Cache
1188 | OrFilter [Filter] Cache
@@ -1160,15 +1202,15 @@ data Filter = AndFilter [Filter] Cache
1160 | RangeFilter FieldName RangeValue RangeExecution Cache
1202 | RangeFilter FieldName RangeValue RangeExecution Cache
1161 | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
1203 | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
1162 | TermFilter Term Cache
1204 | TermFilter Term Cache
1163− deriving (Eq, Show)
1205+ deriving (Eq, Show, Typeable)
1164
1206
1165data ZeroTermsQuery = ZeroTermsNone
1207data ZeroTermsQuery = ZeroTermsNone
1166− | ZeroTermsAll deriving (Eq, Show)
1208+ | ZeroTermsAll deriving (Eq, Show, Typeable)
1167
1209
1168data RangeExecution = RangeExecutionIndex
1210data RangeExecution = RangeExecutionIndex
1169− | RangeExecutionFielddata deriving (Eq, Show)
1211+ | RangeExecutionFielddata deriving (Eq, Show, Typeable)
1170
1212
1171−newtype Regexp = Regexp Text deriving (Eq, Show)
1213+newtype Regexp = Regexp Text deriving (Eq, Show, FromJSON)
1172
1214
1173data RegexpFlags = AllRegexpFlags
1215data RegexpFlags = AllRegexpFlags
1174 | NoRegexpFlags
1216 | NoRegexpFlags
@@ -1229,33 +1271,33 @@ rangeValueToPair rv = case rv of
1229 RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
1271 RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
1230
1272
1231data Term = Term { termField :: Text
1273data Term = Term { termField :: Text
1232− , termValue :: Text } deriving (Eq, Show)
1274+ , termValue :: Text } deriving (Eq, Show, Typeable)
1233
1275
1234data BoolMatch = MustMatch Term Cache
1276data BoolMatch = MustMatch Term Cache
1235 | MustNotMatch Term Cache
1277 | MustNotMatch Term Cache
1236− | ShouldMatch [Term] Cache deriving (Eq, Show)
1278+ | ShouldMatch [Term] Cache deriving (Eq, Show, Typeable)
1237
1279
1238-- "memory" or "indexed"
1280-- "memory" or "indexed"
1239data GeoFilterType = GeoFilterMemory
1281data GeoFilterType = GeoFilterMemory
1240− | GeoFilterIndexed deriving (Eq, Show)
1282+ | GeoFilterIndexed deriving (Eq, Show, Typeable)
1241
1283
1242data LatLon = LatLon { lat :: Double
1284data LatLon = LatLon { lat :: Double
1243− , lon :: Double } deriving (Eq, Show)
1285+ , lon :: Double } deriving (Eq, Show, Typeable)
1244
1286
1245data GeoBoundingBox =
1287data GeoBoundingBox =
1246 GeoBoundingBox { topLeft :: LatLon
1288 GeoBoundingBox { topLeft :: LatLon
1247− , bottomRight :: LatLon } deriving (Eq, Show)
1289+ , bottomRight :: LatLon } deriving (Eq, Show, Typeable)
1248
1290
1249data GeoBoundingBoxConstraint =
1291data GeoBoundingBoxConstraint =
1250 GeoBoundingBoxConstraint { geoBBField :: FieldName
1292 GeoBoundingBoxConstraint { geoBBField :: FieldName
1251 , constraintBox :: GeoBoundingBox
1293 , constraintBox :: GeoBoundingBox
1252 , bbConstraintcache :: Cache
1294 , bbConstraintcache :: Cache
1253 , geoType :: GeoFilterType
1295 , geoType :: GeoFilterType
1254− } deriving (Eq, Show)
1296+ } deriving (Eq, Show, Typeable)
1255
1297
1256data GeoPoint =
1298data GeoPoint =
1257 GeoPoint { geoField :: FieldName
1299 GeoPoint { geoField :: FieldName
1258− , latLon :: LatLon} deriving (Eq, Show)
1300+ , latLon :: LatLon} deriving (Eq, Show, Typeable)
1259
1301
1260data DistanceUnit = Miles
1302data DistanceUnit = Miles
1261 | Yards
1303 | Yards
@@ -1265,18 +1307,18 @@ data DistanceUnit = Miles
1265 | Meters
1307 | Meters
1266 | Centimeters
1308 | Centimeters
1267 | Millimeters
1309 | Millimeters
1268− | NauticalMiles deriving (Eq, Show)
1310+ | NauticalMiles deriving (Eq, Show, Typeable)
1269
1311
1270data DistanceType = Arc
1312data DistanceType = Arc
1271 | SloppyArc -- doesn't exist <1.0
1313 | SloppyArc -- doesn't exist <1.0
1272− | Plane deriving (Eq, Show)
1314+ | Plane deriving (Eq, Show, Typeable)
1273
1315
1274data OptimizeBbox = OptimizeGeoFilterType GeoFilterType
1316data OptimizeBbox = OptimizeGeoFilterType GeoFilterType
1275− | NoOptimizeBbox deriving (Eq, Show)
1317+ | NoOptimizeBbox deriving (Eq, Show, Typeable)
1276
1318
1277data Distance =
1319data Distance =
1278 Distance { coefficient :: Double
1320 Distance { coefficient :: Double
1279− , unit :: DistanceUnit } deriving (Eq, Show)
1321+ , unit :: DistanceUnit } deriving (Eq, Show, Typeable)
1280
1322
1281data DistanceRange =
1323data DistanceRange =
1282 DistanceRange { distanceFrom :: Distance
1324 DistanceRange { distanceFrom :: Distance
@@ -1409,6 +1451,22 @@ mkTermsScriptAggregation t = TermsAggregation (Right t) Nothing Nothing Nothing
1409mkDateHistogram :: FieldName -> Interval -> DateHistogramAggregation
1451mkDateHistogram :: FieldName -> Interval -> DateHistogramAggregation
1410mkDateHistogram t i = DateHistogramAggregation t i Nothing Nothing Nothing Nothing Nothing Nothing
1452mkDateHistogram t i = DateHistogramAggregation t i Nothing Nothing Nothing Nothing Nothing Nothing
1411
1453
1454+instance ToJSON Version where
1455+ toJSON Version {..} = object ["number" .= number
1456+ ,"build_hash" .= build_hash
1457+ ,"build_timestamp" .= build_timestamp
1458+ ,"build_snapshot" .= build_snapshot
1459+ ,"lucene_version" .= lucene_version]
1460+
1461+instance FromJSON Version where
1462+ parseJSON = withObject "Version" parse
1463+ where parse o = Version
1464+ <$> o .: "number"
1465+ <*> o .: "build_hash"
1466+ <*> o .: "build_timestamp"
1467+ <*> o .: "build_snapshot"
1468+ <*> o .: "lucene_version"
1469+
1412instance ToJSON TermOrder where
1470instance ToJSON TermOrder where
1413 toJSON (TermOrder termSortField termSortOrder) = object [termSortField .= termSortOrder]
1471 toJSON (TermOrder termSortField termSortOrder) = object [termSortField .= termSortOrder]
1414
1472
@@ -1641,6 +1699,94 @@ instance ToJSON Filter where
1641 , "_cache" .= cache
1699 , "_cache" .= cache
1642 , "_cache_key" .= cacheKey]]
1700 , "_cache_key" .= cacheKey]]
1643
1701
1702+instance FromJSON Filter where
1703+ parseJSON = withObject "Filter" parse
1704+ where parse o = andFilter `taggedWith` "and"
1705+ <|> orFilter `taggedWith` "or"
1706+ <|> notFilter `taggedWith` "not"
1707+ <|> identityFilter `taggedWith` "match_all"
1708+ <|> boolFilter `taggedWith` "bool"
1709+ <|> existsFilter `taggedWith` "exists"
1710+ <|> geoBoundingBoxFilter `taggedWith` "geo_bounding_box"
1711+ <|> geoDistanceFilter `taggedWith` "geo_distance"
1712+ <|> geoDistanceRangeFilter `taggedWith` "geo_distance_range"
1713+ <|> geoPolygonFilter `taggedWith` "geo_polygon"
1714+ <|> idsFilter `taggedWith` "ids"
1715+ <|> limitFilter `taggedWith` "limit"
1716+ <|> missingFilter `taggedWith` "missing"
1717+ <|> prefixFilter `taggedWith` "prefix"
1718+ <|> queryFilter `taggedWith` "query"
1719+ <|> fqueryFilter `taggedWith` "fquery"
1720+ <|> rangeFilter `taggedWith` "range"
1721+ <|> regexpFilter `taggedWith` "regexp"
1722+ <|> termFilter `taggedWith` "term"
1723+ where taggedWith parser k = parser =<< o .: k
1724+ andFilter o = AndFilter <$> o .: "filters"
1725+ <*> o .:? "_cache" .!= defaultCache
1726+ orFilter o = OrFilter <$> o .: "filters"
1727+ <*> o .:? "_cache" .!= defaultCache
1728+ notFilter o = NotFilter <$> o .: "filter"
1729+ <*> o .: "_cache" .!= defaultCache
1730+ identityFilter :: Object -> Parser Filter
1731+ identityFilter m
1732+ | HM.null m = pure IdentityFilter
1733+ | otherwise = fail ("Identityfilter expected empty object but got " <> show m)
1734+ boolFilter = pure . BoolFilter
1735+ existsFilter o = ExistsFilter <$> o .: "field"
1736+ geoBoundingBoxFilter = pure . GeoBoundingBoxFilter
1737+ geoDistanceFilter o = do
1738+ case HM.toList (deleteSeveral ["distance", "distance_type", "optimize_bbox", "_cache"] o) of
1739+ [(fn, v)] -> do
1740+ gp <- GeoPoint (FieldName fn) <$> parseJSON v
1741+ GeoDistanceFilter gp <$> o .: "distance"
1742+ <*> o .: "distance_type"
1743+ <*> o .: "optimize_bbox"
1744+ <*> o .:? "_cache" .!= defaultCache
1745+ _ -> fail "Could not find GeoDistanceFilter field name"
1746+ geoDistanceRangeFilter o = do
1747+ case HM.toList (deleteSeveral ["from", "to"] o) of
1748+ [(fn, v)] -> do
1749+ gp <- GeoPoint (FieldName fn) <$> parseJSON v
1750+ rng <- DistanceRange <$> o .: "from" <*> o .: "to"
1751+ return (GeoDistanceRangeFilter gp rng)
1752+ _ -> fail "Could not find GeoDistanceRangeFilter field name"
1753+ geoPolygonFilter = fieldTagged $ \fn o -> GeoPolygonFilter fn <$> o .: "points"
1754+ idsFilter o = IdsFilter <$> o .: "type"
1755+ <*> o .: "values"
1756+ limitFilter o = LimitFilter <$> o .: "value"
1757+ missingFilter o = MissingFilter <$> o .: "field"
1758+ <*> o .: "existence"
1759+ <*> o .: "null_value"
1760+ prefixFilter o = case HM.toList (HM.delete "_cache" o) of
1761+ [(fn, String v)] -> PrefixFilter (FieldName fn) v <$> o .:? "_cache" .!= defaultCache
1762+ _ -> fail "Could not parse PrefixFilter"
1763+
1764+ queryFilter q = pure (QueryFilter q False)
1765+ fqueryFilter o = QueryFilter <$> o .: "query" <*> pure True
1766+ rangeFilter o = case HM.toList (deleteSeveral ["execution", "_cache"] o) of
1767+ [(fn, v)] -> RangeFilter (FieldName fn)
1768+ <$> parseJSON v
1769+ <*> o .: "execution"
1770+ <*> o .:? "_cache" .!= defaultCache
1771+ _ -> fail "Could not find field name for RangeFilter"
1772+ regexpFilter o = case HM.toList (deleteSeveral ["_name", "_cache", "_cache_key"] o) of
1773+ [(fn, Object o')] -> RegexpFilter (FieldName fn)
1774+ <$> o' .: "value"
1775+ <*> o' .: "flags"
1776+ <*> o .: "_name"
1777+ <*> o .:? "_cache" .!= defaultCache
1778+ <*> o .: "_cache_key"
1779+ _ -> fail "Could not find field name for RegexpFilter"
1780+ termFilter o = case HM.toList (HM.delete "_cache" o) of
1781+ [(termField, String termVal)] -> TermFilter (Term termField termVal)
1782+ <$> o .:? "_cache" .!= defaultCache
1783+ _ -> fail "Could not find term field for TermFilter"
1784+
1785+fieldTagged :: Monad m => (FieldName -> Object -> m a) -> Object -> m a
1786+fieldTagged f o = case HM.toList o of
1787+ [(k, Object o')] -> f (FieldName k) o'
1788+ _ -> fail "Expected object with 1 field-named key"
1789+
1644instance ToJSON GeoPoint where
1790instance ToJSON GeoPoint where
1645 toJSON (GeoPoint (FieldName geoPointField) geoPointLatLon) =
1791 toJSON (GeoPoint (FieldName geoPointField) geoPointLatLon) =
1646 object [ geoPointField .= geoPointLatLon ]
1792 object [ geoPointField .= geoPointLatLon ]
@@ -1655,12 +1801,9 @@ instance ToJSON Query where
1655 boosted = maybe [] (return . ("boost" .=)) boost
1801 boosted = maybe [] (return . ("boost" .=)) boost
1656 merged = mappend base boosted
1802 merged = mappend base boosted
1657
1803
1658− toJSON (TermsQuery terms) =
1804+ toJSON (TermsQuery fieldName terms) =
1659 object [ "terms" .= object conjoined ]
1805 object [ "terms" .= object conjoined ]
1660− where conjoined = [ getTermsField terms .=
1806+ where conjoined = [fieldName .= terms]
1661− fmap (toJSON . getTermValue) (toList terms)]
1662− getTermsField ((Term f _ ) :| _) = f
1663− getTermValue (Term _ v) = v
1664 toJSON (IdsQuery idsQueryMappingName docIds) =
1807 toJSON (IdsQuery idsQueryMappingName docIds) =
1665 object [ "ids" .= object conjoined ]
1808 object [ "ids" .= object conjoined ]
1666 where conjoined = [ "type" .= idsQueryMappingName
1809 where conjoined = [ "type" .= idsQueryMappingName
@@ -1685,12 +1828,12 @@ instance ToJSON Query where
1685 object [ "common" .= commonTermsQuery ]
1828 object [ "common" .= commonTermsQuery ]
1686
1829
1687 toJSON (ConstantScoreFilter csFilter boost) =
1830 toJSON (ConstantScoreFilter csFilter boost) =
1688− object [ "constant_score" .= csFilter
1831+ object ["constant_score" .= object ["filter" .= csFilter
1689− , "boost" .= boost]
1832+ , "boost" .= boost]]
1690
1833
1691 toJSON (ConstantScoreQuery query boost) =
1834 toJSON (ConstantScoreQuery query boost) =
1692− object [ "constant_score" .= query
1835+ object ["constant_score" .= object ["query" .= query
1693− , "boost" .= boost]
1836+ , "boost" .= boost]]
1694
1837
1695 toJSON (QueryDisMaxQuery disMaxQuery) =
1838 toJSON (QueryDisMaxQuery disMaxQuery) =
1696 object [ "dis_max" .= disMaxQuery ]
1839 object [ "dis_max" .= disMaxQuery ]
@@ -1740,6 +1883,77 @@ instance ToJSON Query where
1740 toJSON (QuerySimpleQueryStringQuery query) =
1883 toJSON (QuerySimpleQueryStringQuery query) =
1741 object [ "simple_query_string" .= query ]
1884 object [ "simple_query_string" .= query ]
1742
1885
1886+instance FromJSON Query where
1887+ parseJSON v = withObject "Query" parse v
1888+ where parse o = termQuery `taggedWith` "term"
1889+ <|> termsQuery `taggedWith` "terms"
1890+ <|> idsQuery `taggedWith` "ids"
1891+ <|> queryQueryStringQuery `taggedWith` "query_string"
1892+ <|> queryMatchQuery `taggedWith` "match"
1893+ <|> queryMultiMatchQuery --TODO: is this a precedence issue?
1894+ <|> queryBoolQuery `taggedWith` "bool"
1895+ <|> queryBoostingQuery `taggedWith` "boosting"
1896+ <|> queryCommonTermsQuery `taggedWith` "common"
1897+ <|> constantScoreFilter `taggedWith` "constant_score"
1898+ <|> constantScoreQuery `taggedWith` "constant_score"
1899+ <|> queryDisMaxQuery `taggedWith` "dis_max"
1900+ <|> queryFilteredQuery `taggedWith` "filtered"
1901+ <|> queryFuzzyLikeThisQuery `taggedWith` "fuzzy_like_this"
1902+ <|> queryFuzzyLikeFieldQuery `taggedWith` "fuzzy_like_this_field"
1903+ <|> queryFuzzyQuery `taggedWith` "fuzzy"
1904+ <|> queryHasChildQuery `taggedWith` "has_child"
1905+ <|> queryHasParentQuery `taggedWith` "has_parent"
1906+ <|> queryIndicesQuery `taggedWith` "indices"
1907+ <|> matchAllQuery `taggedWith` "match_all"
1908+ <|> queryMoreLikeThisQuery `taggedWith` "more_like_this"
1909+ <|> queryMoreLikeThisFieldQuery `taggedWith` "more_like_this_field"
1910+ <|> queryNestedQuery `taggedWith` "nested"
1911+ <|> queryPrefixQuery `taggedWith` "prefix"
1912+ <|> queryRangeQuery `taggedWith` "range"
1913+ <|> queryRegexpQuery `taggedWith` "regexp"
1914+ <|> querySimpleQueryStringQuery `taggedWith` "simple_query_string"
1915+ where taggedWith parser k = parser =<< o .: k
1916+ termQuery = fieldTagged $ \(FieldName fn) o ->
1917+ TermQuery <$> (Term fn <$> o .: "value") <*> o .:? "boost"
1918+ termsQuery o = case HM.toList o of
1919+ [(fn, vs)] -> do vals <- parseJSON vs
1920+ case vals of
1921+ x:xs -> return (TermsQuery fn (x :| xs))
1922+ _ -> fail "Expected non empty list of values"
1923+ _ -> fail "Expected object with 1 field-named key"
1924+ idsQuery o = IdsQuery <$> o .: "type"
1925+ <*> o .: "values"
1926+ queryQueryStringQuery = pure . QueryQueryStringQuery
1927+ queryMatchQuery = pure . QueryMatchQuery
1928+ queryMultiMatchQuery = QueryMultiMatchQuery <$> parseJSON v
1929+ queryBoolQuery = pure . QueryBoolQuery
1930+ queryBoostingQuery = pure . QueryBoostingQuery
1931+ queryCommonTermsQuery = pure . QueryCommonTermsQuery
1932+ constantScoreFilter o = case HM.lookup "filter" o of
1933+ Just x -> ConstantScoreFilter <$> parseJSON x
1934+ <*> o .: "boost"
1935+ _ -> fail "Does not appear to be a ConstantScoreFilter"
1936+ constantScoreQuery o = case HM.lookup "query" o of
1937+ Just x -> ConstantScoreQuery <$> parseJSON x
1938+ <*> o .: "boost"
1939+ _ -> fail "Does not appear to be a ConstantScoreQuery"
1940+ queryDisMaxQuery = pure . QueryDisMaxQuery
1941+ queryFilteredQuery = pure . QueryFilteredQuery
1942+ queryFuzzyLikeThisQuery = pure . QueryFuzzyLikeThisQuery
1943+ queryFuzzyLikeFieldQuery = pure . QueryFuzzyLikeFieldQuery
1944+ queryFuzzyQuery = pure . QueryFuzzyQuery
1945+ queryHasChildQuery = pure . QueryHasChildQuery
1946+ queryHasParentQuery = pure . QueryHasParentQuery
1947+ queryIndicesQuery = pure . QueryIndicesQuery
1948+ matchAllQuery o = MatchAllQuery <$> o .:? "boost"
1949+ queryMoreLikeThisQuery = pure . QueryMoreLikeThisQuery
1950+ queryMoreLikeThisFieldQuery = pure . QueryMoreLikeThisFieldQuery
1951+ queryNestedQuery = pure . QueryNestedQuery
1952+ queryPrefixQuery = pure . QueryPrefixQuery
1953+ queryRangeQuery = pure . QueryRangeQuery
1954+ queryRegexpQuery = pure . QueryRegexpQuery
1955+ querySimpleQueryStringQuery = pure . QuerySimpleQueryStringQuery
1956+
1743
1957
1744omitNulls :: [(Text, Value)] -> Value
1958omitNulls :: [(Text, Value)] -> Value
1745omitNulls = object . filter notNull where
1959omitNulls = object . filter notNull where
@@ -1759,6 +1973,17 @@ instance ToJSON SimpleQueryStringQuery where
1759 , "lowercase_expanded_terms" .= simpleQueryStringLowercaseExpanded
1973 , "lowercase_expanded_terms" .= simpleQueryStringLowercaseExpanded
1760 , "locale" .= simpleQueryStringLocale ]
1974 , "locale" .= simpleQueryStringLocale ]
1761
1975
1976+instance FromJSON SimpleQueryStringQuery where
1977+ parseJSON = withObject "SimpleQueryStringQuery" parse
1978+ where parse o = SimpleQueryStringQuery <$> o .: "query"
1979+ <*> o .:? "fields"
1980+ <*> o .:? "default_operator"
1981+ <*> o .:? "analyzer"
1982+ <*> (parseFlags <$> o .:? "flags")
1983+ <*> o .:? "lowercase_expanded_terms"
1984+ <*> o .:? "locale"
1985+ parseFlags (Just (x:xs)) = Just (x :| xs)
1986+ parseFlags _ = Nothing
1762
1987
1763instance ToJSON FieldOrFields where
1988instance ToJSON FieldOrFields where
1764 toJSON (FofField fieldName) =
1989 toJSON (FofField fieldName) =
@@ -1766,6 +1991,10 @@ instance ToJSON FieldOrFields where
1766 toJSON (FofFields fieldNames) =
1991 toJSON (FofFields fieldNames) =
1767 toJSON fieldNames
1992 toJSON fieldNames
1768
1993
1994+instance FromJSON FieldOrFields where
1995+ parseJSON v = FofField <$> parseJSON v
1996+ <|> FofFields <$> (parseNEJSON =<< parseJSON v)
1997+
1769instance ToJSON SimpleQueryFlag where
1998instance ToJSON SimpleQueryFlag where
1770 toJSON SimpleQueryAll = "ALL"
1999 toJSON SimpleQueryAll = "ALL"
1771 toJSON SimpleQueryNone = "NONE"
2000 toJSON SimpleQueryNone = "NONE"
@@ -1780,6 +2009,21 @@ instance ToJSON SimpleQueryFlag where
1780 toJSON SimpleQueryNear = "NEAR"
2009 toJSON SimpleQueryNear = "NEAR"
1781 toJSON SimpleQuerySlop = "SLOP"
2010 toJSON SimpleQuerySlop = "SLOP"
1782
2011
2012+instance FromJSON SimpleQueryFlag where
2013+ parseJSON = withText "SimpleQueryFlag" parse
2014+ where parse "ALL" = pure SimpleQueryAll
2015+ parse "NONE" = pure SimpleQueryNone
2016+ parse "AND" = pure SimpleQueryAnd
2017+ parse "OR" = pure SimpleQueryOr
2018+ parse "PREFIX" = pure SimpleQueryPrefix
2019+ parse "PHRASE" = pure SimpleQueryPhrase
2020+ parse "PRECEDENCE" = pure SimpleQueryPrecedence
2021+ parse "ESCAPE" = pure SimpleQueryEscape
2022+ parse "WHITESPACE" = pure SimpleQueryWhitespace
2023+ parse "FUZZY" = pure SimpleQueryFuzzy
2024+ parse "NEAR" = pure SimpleQueryNear
2025+ parse "SLOP" = pure SimpleQuerySlop
2026+ parse f = fail ("Unexpected SimpleQueryFlag: " <> show f)
1783
2027
1784instance ToJSON RegexpQuery where
2028instance ToJSON RegexpQuery where
1785 toJSON (RegexpQuery (FieldName rqQueryField)
2029 toJSON (RegexpQuery (FieldName rqQueryField)
@@ -1790,6 +2034,13 @@ instance ToJSON RegexpQuery where
1790 , "flags" .= rqQueryFlags
2034 , "flags" .= rqQueryFlags
1791 , "boost" .= rqQueryBoost ]
2035 , "boost" .= rqQueryBoost ]
1792
2036
2037+instance FromJSON RegexpQuery where
2038+ parseJSON = withObject "RegexpQuery" parse
2039+ where parse = fieldTagged $ \fn o ->
2040+ RegexpQuery fn
2041+ <$> o .: "value"
2042+ <*> o .: "flags"
2043+ <*> o .:? "boost"
1793
2044
1794instance ToJSON QueryStringQuery where
2045instance ToJSON QueryStringQuery where
1795 toJSON (QueryStringQuery qsQueryString
2046 toJSON (QueryStringQuery qsQueryString
@@ -1821,12 +2072,71 @@ instance ToJSON QueryStringQuery where
1821 , "lenient" .= qsLenient
2072 , "lenient" .= qsLenient
1822 , "locale" .= qsLocale ]
2073 , "locale" .= qsLocale ]
1823
2074
2075+instance FromJSON QueryStringQuery where
2076+ parseJSON = withObject "QueryStringQuery" parse
2077+ where parse o = QueryStringQuery
2078+ <$> o .: "query"
2079+ <*> o .:? "default_field"
2080+ <*> o .:? "default_operator"
2081+ <*> o .:? "analyzer"
2082+ <*> o .:? "allow_leading_wildcard"
2083+ <*> o .:? "lowercase_expanded_terms"
2084+ <*> o .:? "enable_position_increments"
2085+ <*> o .:? "fuzzy_max_expansions"
2086+ <*> o .:? "fuzziness"
2087+ <*> o .:? "fuzzy_prefix_length"
2088+ <*> o .:? "phrase_slop"
2089+ <*> o .:? "boost"
2090+ <*> o .:? "analyze_wildcard"
2091+ <*> o .:? "auto_generate_phrase_queries"
2092+ <*> o .:? "minimum_should_match"
2093+ <*> o .:? "lenient"
2094+ <*> o .:? "locale"
1824
2095
1825instance ToJSON RangeQuery where
2096instance ToJSON RangeQuery where
1826 toJSON (RangeQuery (FieldName fieldName) range boost) =
2097 toJSON (RangeQuery (FieldName fieldName) range boost) =
1827− object [ fieldName .= conjoined ]
2098+ object [ fieldName .= object conjoined ]
1828 where conjoined = [ "boost" .= boost ] ++ (rangeValueToPair range)
2099 where conjoined = [ "boost" .= boost ] ++ (rangeValueToPair range)
1829
2100
2101+instance FromJSON RangeQuery where
2102+ parseJSON = withObject "RangeQuery" parse
2103+ where parse = fieldTagged $ \fn o ->
2104+ RangeQuery fn
2105+ <$> parseJSON (Object o)
2106+ <*> o .: "boost"
2107+
2108+instance FromJSON RangeValue where
2109+ parseJSON = withObject "RangeValue" parse
2110+ where parse o = parseDate o
2111+ <|> parseDouble o
2112+ parseDate o = do lt <- o .:? "lt"
2113+ lte <- o .:? "lte"
2114+ gt <- o .:? "gt"
2115+ gte <- o .:? "gte"
2116+ case (lt, lte, gt, gte) of
2117+ (Just a, _, Just b, _) -> return (RangeDateGtLt (GreaterThanD b) (LessThanD a))
2118+ (Just a, _, _, Just b)-> return (RangeDateGteLt (GreaterThanEqD b) (LessThanD a))
2119+ (_, Just a, Just b, _)-> return (RangeDateGtLte (GreaterThanD b) (LessThanEqD a))
2120+ (_, Just a, _, Just b)-> return (RangeDateGteLte (GreaterThanEqD b) (LessThanEqD a))
2121+ (_, _, Just a, _)-> return (RangeDateGt (GreaterThanD a))
2122+ (Just a, _, _, _)-> return (RangeDateLt (LessThanD a))
2123+ (_, _, _, Just a)-> return (RangeDateGte (GreaterThanEqD a))
2124+ (_, Just a, _, _)-> return (RangeDateLte (LessThanEqD a))
2125+ (Nothing, Nothing, Nothing, Nothing) -> mzero
2126+ parseDouble o = do lt <- o .:? "lt"
2127+ lte <- o .:? "lte"
2128+ gt <- o .:? "gt"
2129+ gte <- o .:? "gte"
2130+ case (lt, lte, gt, gte) of
2131+ (Just a, _, Just b, _) -> return (RangeDoubleGtLt (GreaterThan b) (LessThan a))
2132+ (Just a, _, _, Just b)-> return (RangeDoubleGteLt (GreaterThanEq b) (LessThan a))
2133+ (_, Just a, Just b, _)-> return (RangeDoubleGtLte (GreaterThan b) (LessThanEq a))
2134+ (_, Just a, _, Just b)-> return (RangeDoubleGteLte (GreaterThanEq b) (LessThanEq a))
2135+ (_, _, Just a, _)-> return (RangeDoubleGt (GreaterThan a))
2136+ (Just a, _, _, _)-> return (RangeDoubleLt (LessThan a))
2137+ (_, _, _, Just a)-> return (RangeDoubleGte (GreaterThanEq a))
2138+ (_, Just a, _, _)-> return (RangeDoubleLte (LessThanEq a))
2139+ (Nothing, Nothing, Nothing, Nothing) -> mzero
1830
2140
1831instance ToJSON PrefixQuery where
2141instance ToJSON PrefixQuery where
1832 toJSON (PrefixQuery (FieldName fieldName) queryValue boost) =
2142 toJSON (PrefixQuery (FieldName fieldName) queryValue boost) =
@@ -1834,6 +2144,12 @@ instance ToJSON PrefixQuery where
1834 where base = [ "value" .= queryValue
2144 where base = [ "value" .= queryValue
1835 , "boost" .= boost ]
2145 , "boost" .= boost ]
1836
2146
2147+instance FromJSON PrefixQuery where
2148+ parseJSON = withObject "PrefixQuery" parse
2149+ where parse = fieldTagged $ \fn o ->
2150+ PrefixQuery fn
2151+ <$> o .: "value"
2152+ <*> o .:? "boost"
1837
2153
1838instance ToJSON NestedQuery where
2154instance ToJSON NestedQuery where
1839 toJSON (NestedQuery nqPath nqScoreType nqQuery) =
2155 toJSON (NestedQuery nqPath nqScoreType nqQuery) =
@@ -1841,6 +2157,12 @@ instance ToJSON NestedQuery where
1841 , "score_mode" .= nqScoreType
2157 , "score_mode" .= nqScoreType
1842 , "query" .= nqQuery ]
2158 , "query" .= nqQuery ]
1843
2159
2160+instance FromJSON NestedQuery where
2161+ parseJSON = withObject "NestedQuery" parse
2162+ where parse o = NestedQuery
2163+ <$> o .: "path"
2164+ <*> o .: "score_mode"
2165+ <*> o .: "query"
1844
2166
1845instance ToJSON MoreLikeThisFieldQuery where
2167instance ToJSON MoreLikeThisFieldQuery where
1846 toJSON (MoreLikeThisFieldQuery text (FieldName fieldName)
2168 toJSON (MoreLikeThisFieldQuery text (FieldName fieldName)
@@ -1860,6 +2182,24 @@ instance ToJSON MoreLikeThisFieldQuery where
1860 , "boost" .= boost
2182 , "boost" .= boost
1861 , "analyzer" .= analyzer ]
2183 , "analyzer" .= analyzer ]
1862
2184
2185+instance FromJSON MoreLikeThisFieldQuery where
2186+ parseJSON = withObject "MoreLikeThisFieldQuery" parse
2187+ where parse = fieldTagged $ \fn o ->
2188+ MoreLikeThisFieldQuery
2189+ <$> o .: "like_text"
2190+ <*> pure fn
2191+ <*> o .:? "percent_terms_to_match"
2192+ <*> o .:? "min_term_freq"
2193+ <*> o .:? "max_query_terms"
2194+ <*> (optionalNE =<< o .:? "stop_words")
2195+ <*> o .:? "min_doc_freq"
2196+ <*> o .:? "max_doc_freq"
2197+ <*> o .:? "min_word_length"
2198+ <*> o .:? "max_word_length"
2199+ <*> o .:? "boost_terms"
2200+ <*> o .:? "boost"
2201+ <*> o .:? "analyzer"
2202+ optionalNE = maybe (pure Nothing) (fmap Just . parseNEJSON)
1863
2203
1864instance ToJSON MoreLikeThisQuery where
2204instance ToJSON MoreLikeThisQuery where
1865 toJSON (MoreLikeThisQuery text fields percent
2205 toJSON (MoreLikeThisQuery text fields percent
@@ -1880,6 +2220,23 @@ instance ToJSON MoreLikeThisQuery where
1880 , "boost" .= boost
2220 , "boost" .= boost
1881 , "analyzer" .= analyzer ]
2221 , "analyzer" .= analyzer ]
1882
2222
2223+instance FromJSON MoreLikeThisQuery where
2224+ parseJSON = withObject "MoreLikeThisQuery" parse
2225+ where parse o = MoreLikeThisQuery
2226+ <$> o .: "like_text"
2227+ <*> (optionalNE =<< o .:? "fields")
2228+ <*> o .:? "percent_terms_to_match"
2229+ <*> o .:? "min_term_freq"
2230+ <*> o .:? "max_query_terms"
2231+ <*> (optionalNE =<< o .:? "stop_words")
2232+ <*> o .:? "min_doc_freq"
2233+ <*> o .:? "max_doc_freq"
2234+ <*> o .:? "min_word_length"
2235+ <*> o .:? "max_word_length"
2236+ <*> o .:? "boost_terms"
2237+ <*> o .:? "boost"
2238+ <*> o .:? "analyzer"
2239+ optionalNE = maybe (pure Nothing) (fmap Just . parseNEJSON)
1883
2240
1884instance ToJSON IndicesQuery where
2241instance ToJSON IndicesQuery where
1885 toJSON (IndicesQuery indices query noMatch) =
2242 toJSON (IndicesQuery indices query noMatch) =
@@ -1887,6 +2244,12 @@ instance ToJSON IndicesQuery where
1887 , "no_match_query" .= noMatch
2244 , "no_match_query" .= noMatch
1888 , "query" .= query ]
2245 , "query" .= query ]
1889
2246
2247+instance FromJSON IndicesQuery where
2248+ parseJSON = withObject "IndicesQuery" parse
2249+ where parse o = IndicesQuery
2250+ <$> o .:? "indices" .!= []
2251+ <*> o .: "query"
2252+ <*> o .:? "no_match_query"
1890
2253
1891instance ToJSON HasParentQuery where
2254instance ToJSON HasParentQuery where
1892 toJSON (HasParentQuery queryType query scoreType) =
2255 toJSON (HasParentQuery queryType query scoreType) =
@@ -1894,6 +2257,12 @@ instance ToJSON HasParentQuery where
1894 , "score_type" .= scoreType
2257 , "score_type" .= scoreType
1895 , "query" .= query ]
2258 , "query" .= query ]
1896
2259
2260+instance FromJSON HasParentQuery where
2261+ parseJSON = withObject "HasParentQuery" parse
2262+ where parse o = HasParentQuery
2263+ <$> o .: "parent_type"
2264+ <*> o .: "query"
2265+ <*> o .:? "score_type"
1897
2266
1898instance ToJSON HasChildQuery where
2267instance ToJSON HasChildQuery where
1899 toJSON (HasChildQuery queryType query scoreType) =
2268 toJSON (HasChildQuery queryType query scoreType) =
@@ -1901,6 +2270,12 @@ instance ToJSON HasChildQuery where
1901 , "score_type" .= scoreType
2270 , "score_type" .= scoreType
1902 , "type" .= queryType ]
2271 , "type" .= queryType ]
1903
2272
2273+instance FromJSON HasChildQuery where
2274+ parseJSON = withObject "HasChildQuery" parse
2275+ where parse o = HasChildQuery
2276+ <$> o .: "type"
2277+ <*> o .: "query"
2278+ <*> o .:? "score_type"
1904
2279
1905instance ToJSON FuzzyQuery where
2280instance ToJSON FuzzyQuery where
1906 toJSON (FuzzyQuery (FieldName fieldName) queryText
2281 toJSON (FuzzyQuery (FieldName fieldName) queryText
@@ -1912,6 +2287,15 @@ instance ToJSON FuzzyQuery where
1912 , "boost" .= boost
2287 , "boost" .= boost
1913 , "max_expansions" .= maxEx ]
2288 , "max_expansions" .= maxEx ]
1914
2289
2290+instance FromJSON FuzzyQuery where
2291+ parseJSON = withObject "FuzzyQuery" parse
2292+ where parse = fieldTagged $ \fn o ->
2293+ FuzzyQuery fn
2294+ <$> o .: "value"
2295+ <*> o .: "prefix_length"
2296+ <*> o .: "max_expansions"
2297+ <*> o .: "fuzziness"
2298+ <*> o .:? "boost"
1915
2299
1916instance ToJSON FuzzyLikeFieldQuery where
2300instance ToJSON FuzzyLikeFieldQuery where
1917 toJSON (FuzzyLikeFieldQuery (FieldName fieldName)
2301 toJSON (FuzzyLikeFieldQuery (FieldName fieldName)
@@ -1926,6 +2310,17 @@ instance ToJSON FuzzyLikeFieldQuery where
1926 , "analyzer" .= analyzer
2310 , "analyzer" .= analyzer
1927 , "boost" .= boost ]]
2311 , "boost" .= boost ]]
1928
2312
2313+instance FromJSON FuzzyLikeFieldQuery where
2314+ parseJSON = withObject "FuzzyLikeFieldQuery" parse
2315+ where parse = fieldTagged $ \fn o ->
2316+ FuzzyLikeFieldQuery fn
2317+ <$> o .: "like_text"
2318+ <*> o .: "max_query_terms"
2319+ <*> o .: "ignore_tf"
2320+ <*> o .: "fuzziness"
2321+ <*> o .: "prefix_length"
2322+ <*> o .: "boost"
2323+ <*> o .:? "analyzer"
1929
2324
1930instance ToJSON FuzzyLikeThisQuery where
2325instance ToJSON FuzzyLikeThisQuery where
1931 toJSON (FuzzyLikeThisQuery fields text maxTerms
2326 toJSON (FuzzyLikeThisQuery fields text maxTerms
@@ -1940,12 +2335,28 @@ instance ToJSON FuzzyLikeThisQuery where
1940 , "analyzer" .= analyzer
2335 , "analyzer" .= analyzer
1941 , "boost" .= boost ]
2336 , "boost" .= boost ]
1942
2337
2338+instance FromJSON FuzzyLikeThisQuery where
2339+ parseJSON = withObject "FuzzyLikeThisQuery" parse
2340+ where parse o = FuzzyLikeThisQuery
2341+ <$> o .:? "fields" .!= []
2342+ <*> o .: "like_text"
2343+ <*> o .: "max_query_terms"
2344+ <*> o .: "ignore_tf"
2345+ <*> o .: "fuzziness"
2346+ <*> o .: "prefix_length"
2347+ <*> o .: "boost"
2348+ <*> o .:? "analyzer"
1943
2349
1944instance ToJSON FilteredQuery where
2350instance ToJSON FilteredQuery where
1945 toJSON (FilteredQuery query fFilter) =
2351 toJSON (FilteredQuery query fFilter) =
1946 object [ "query" .= query
2352 object [ "query" .= query
1947 , "filter" .= fFilter ]
2353 , "filter" .= fFilter ]
1948
2354
2355+instance FromJSON FilteredQuery where
2356+ parseJSON = withObject "FilteredQuery" parse
2357+ where parse o = FilteredQuery
2358+ <$> o .: "query"
2359+ <*> o .: "filter"
1949
2360
1950instance ToJSON DisMaxQuery where
2361instance ToJSON DisMaxQuery where
1951 toJSON (DisMaxQuery queries tiebreaker boost) =
2362 toJSON (DisMaxQuery queries tiebreaker boost) =
@@ -1954,6 +2365,12 @@ instance ToJSON DisMaxQuery where
1954 , "boost" .= boost
2365 , "boost" .= boost
1955 , "tie_breaker" .= tiebreaker ]
2366 , "tie_breaker" .= tiebreaker ]
1956
2367
2368+instance FromJSON DisMaxQuery where
2369+ parseJSON = withObject "DisMaxQuery" parse
2370+ where parse o = DisMaxQuery
2371+ <$> o .:? "queries" .!= []
2372+ <*> o .: "tie_breaker"
2373+ <*> o .:? "boost"
1957
2374
1958instance ToJSON CommonTermsQuery where
2375instance ToJSON CommonTermsQuery where
1959 toJSON (CommonTermsQuery (FieldName fieldName)
2376 toJSON (CommonTermsQuery (FieldName fieldName)
@@ -1969,6 +2386,18 @@ instance ToJSON CommonTermsQuery where
1969 , "disable_coord" .= disableCoord
2386 , "disable_coord" .= disableCoord
1970 , "high_freq_operator" .= hfo ]
2387 , "high_freq_operator" .= hfo ]
1971
2388
2389+instance FromJSON CommonTermsQuery where
2390+ parseJSON = withObject "CommonTermsQuery" parse
2391+ where parse = fieldTagged $ \fn o ->
2392+ CommonTermsQuery fn
2393+ <$> o .: "query"
2394+ <*> o .: "cutoff_frequency"
2395+ <*> o .: "low_freq_operator"
2396+ <*> o .: "high_freq_operator"
2397+ <*> o .:? "minimum_should_match"
2398+ <*> o .:? "boost"
2399+ <*> o .:? "analyzer"
2400+ <*> o .:? "disable_coord"
1972
2401
1973instance ToJSON CommonMinimumMatch where
2402instance ToJSON CommonMinimumMatch where
1974 toJSON (CommonMinimumMatch mm) = toJSON mm
2403 toJSON (CommonMinimumMatch mm) = toJSON mm
@@ -1976,12 +2405,28 @@ instance ToJSON CommonMinimumMatch where
1976 object [ "low_freq" .= lowF
2405 object [ "low_freq" .= lowF
1977 , "high_freq" .= highF ]
2406 , "high_freq" .= highF ]
1978
2407
2408+instance FromJSON CommonMinimumMatch where
2409+ parseJSON v = parseMinimum v
2410+ <|> parseMinimumHighLow v
2411+ where parseMinimum = fmap CommonMinimumMatch . parseJSON
2412+ parseMinimumHighLow = fmap CommonMinimumMatchHighLow . withObject "CommonMinimumMatchHighLow" (\o ->
2413+ MinimumMatchHighLow
2414+ <$> o .: "low_freq"
2415+ <*> o .: "high_freq")
2416+
2417+
1979instance ToJSON BoostingQuery where
2418instance ToJSON BoostingQuery where
1980 toJSON (BoostingQuery bqPositiveQuery bqNegativeQuery bqNegativeBoost) =
2419 toJSON (BoostingQuery bqPositiveQuery bqNegativeQuery bqNegativeBoost) =
1981 object [ "positive" .= bqPositiveQuery
2420 object [ "positive" .= bqPositiveQuery
1982 , "negative" .= bqNegativeQuery
2421 , "negative" .= bqNegativeQuery
1983 , "negative_boost" .= bqNegativeBoost ]
2422 , "negative_boost" .= bqNegativeBoost ]
1984
2423
2424+instance FromJSON BoostingQuery where
2425+ parseJSON = withObject "BoostingQuery" parse
2426+ where parse o = BoostingQuery
2427+ <$> o .: "positive"
2428+ <*> o .: "negative"
2429+ <*> o .: "negative_boost"
1985
2430
1986instance ToJSON BoolQuery where
2431instance ToJSON BoolQuery where
1987 toJSON (BoolQuery mustM notM shouldM bqMin boost disableCoord) =
2432 toJSON (BoolQuery mustM notM shouldM bqMin boost disableCoord) =
@@ -1993,6 +2438,15 @@ instance ToJSON BoolQuery where
1993 , "boost" .= boost
2438 , "boost" .= boost
1994 , "disable_coord" .= disableCoord ]
2439 , "disable_coord" .= disableCoord ]
1995
2440
2441+instance FromJSON BoolQuery where
2442+ parseJSON = withObject "BoolQuery" parse
2443+ where parse o = BoolQuery
2444+ <$> o .:? "must" .!= []
2445+ <*> o .:? "must_not" .!= []
2446+ <*> o .:? "should" .!= []
2447+ <*> o .:? "minimum_should_match"
2448+ <*> o .:? "boost"
2449+ <*> o .:? "disable_coord"
1996
2450
1997instance ToJSON MatchQuery where
2451instance ToJSON MatchQuery where
1998 toJSON (MatchQuery (FieldName fieldName)
2452 toJSON (MatchQuery (FieldName fieldName)
@@ -2010,6 +2464,19 @@ instance ToJSON MatchQuery where
2010 , "lenient" .= lenient
2464 , "lenient" .= lenient
2011 , "boost" .= boost ]
2465 , "boost" .= boost ]
2012
2466
2467+instance FromJSON MatchQuery where
2468+ parseJSON = withObject "MatchQuery" parse
2469+ where parse = fieldTagged $ \fn o ->
2470+ MatchQuery fn
2471+ <$> o .: "query"
2472+ <*> o .: "operator"
2473+ <*> o .: "zero_terms_query"
2474+ <*> o .:? "cutoff_frequency"
2475+ <*> o .:? "type"
2476+ <*> o .:? "analyzer"
2477+ <*> o .:? "max_expansions"
2478+ <*> o .:? "lenient"
2479+ <*> o .:? "boost"
2013
2480
2014instance ToJSON MultiMatchQuery where
2481instance ToJSON MultiMatchQuery where
2015 toJSON (MultiMatchQuery fields (QueryString query) boolOp
2482 toJSON (MultiMatchQuery fields (QueryString query) boolOp
@@ -2026,6 +2493,20 @@ instance ToJSON MultiMatchQuery where
2026 , "max_expansions" .= maxEx
2493 , "max_expansions" .= maxEx
2027 , "lenient" .= lenient ]
2494 , "lenient" .= lenient ]
2028
2495
2496+instance FromJSON MultiMatchQuery where
2497+ parseJSON = withObject "MultiMatchQuery" parse
2498+ where parse raw = do o <- raw .: "multi_match"
2499+ MultiMatchQuery
2500+ <$> o .:? "fields" .!= []
2501+ <*> o .: "query"
2502+ <*> o .: "operator"
2503+ <*> o .: "zero_terms_query"
2504+ <*> o .:? "tiebreaker"
2505+ <*> o .:? "type"
2506+ <*> o .:? "cutoff_frequency"
2507+ <*> o .:? "analyzer"
2508+ <*> o .:? "max_expansions"
2509+ <*> o .:? "lenient"
2029
2510
2030instance ToJSON MultiMatchQueryType where
2511instance ToJSON MultiMatchQueryType where
2031 toJSON MultiMatchBestFields = "best_fields"
2512 toJSON MultiMatchBestFields = "best_fields"
@@ -2034,107 +2515,44 @@ instance ToJSON MultiMatchQueryType where
2034 toJSON MultiMatchPhrase = "phrase"
2515 toJSON MultiMatchPhrase = "phrase"
2035 toJSON MultiMatchPhrasePrefix = "phrase_prefix"
2516 toJSON MultiMatchPhrasePrefix = "phrase_prefix"
2036
2517
2518+instance FromJSON MultiMatchQueryType where
2519+ parseJSON = withText "MultiMatchPhrasePrefix" parse
2520+ where parse "best_fields" = pure MultiMatchBestFields
2521+ parse "most_fields" = pure MultiMatchMostFields
2522+ parse "cross_fields" = pure MultiMatchCrossFields
2523+ parse "phrase" = pure MultiMatchPhrase
2524+ parse "phrase_prefix" = pure MultiMatchPhrasePrefix
2525+ parse t = fail ("Unexpected MultiMatchPhrasePrefix: " <> show t)
2526+
2037instance ToJSON BooleanOperator where
2527instance ToJSON BooleanOperator where
2038 toJSON And = String "and"
2528 toJSON And = String "and"
2039 toJSON Or = String "or"
2529 toJSON Or = String "or"
2040
2530
2531+instance FromJSON BooleanOperator where
2532+ parseJSON = withText "BooleanOperator" parse
2533+ where parse "and" = pure And
2534+ parse "or" = pure Or
2535+ parse o = fail ("Unexpected BooleanOperator: " <> show o)
2536+
2041instance ToJSON ZeroTermsQuery where
2537instance ToJSON ZeroTermsQuery where
2042 toJSON ZeroTermsNone = String "none"
2538 toJSON ZeroTermsNone = String "none"
2043 toJSON ZeroTermsAll = String "all"
2539 toJSON ZeroTermsAll = String "all"
2044
2540
2541+instance FromJSON ZeroTermsQuery where
2542+ parseJSON = withText "ZeroTermsQuery" parse
2543+ where parse "none" = pure ZeroTermsNone
2544+ parse "all" = pure ZeroTermsAll
2545+ parse q = fail ("Unexpected ZeroTermsQuery: " <> show q)
2546+
2045instance ToJSON MatchQueryType where
2547instance ToJSON MatchQueryType where
2046 toJSON MatchPhrase = "phrase"
2548 toJSON MatchPhrase = "phrase"
2047 toJSON MatchPhrasePrefix = "phrase_prefix"
2549 toJSON MatchPhrasePrefix = "phrase_prefix"
2048
2550
2049−instance ToJSON FieldName where
2551+instance FromJSON MatchQueryType where
2050− toJSON (FieldName fieldName) = String fieldName
2552+ parseJSON = withText "MatchQueryType" parse
2051−
2553+ where parse "phrase" = pure MatchPhrase
2052−instance ToJSON ReplicaCount where
2554+ parse "phrase_prefix" = pure MatchPhrasePrefix
2053− toJSON = genericToJSON defaultOptions
2555+ parse t = fail ("Unexpected MatchQueryType: " <> show t)
2054−instance ToJSON ShardCount where
2055− toJSON = genericToJSON defaultOptions
2056−instance ToJSON CutoffFrequency where
2057− toJSON = genericToJSON defaultOptions
2058−instance ToJSON Analyzer where
2059− toJSON = genericToJSON defaultOptions
2060−instance ToJSON MaxExpansions where
2061− toJSON = genericToJSON defaultOptions
2062−instance ToJSON Lenient where
2063− toJSON = genericToJSON defaultOptions
2064−instance ToJSON Boost where
2065− toJSON = genericToJSON defaultOptions
2066−instance ToJSON Version where
2067− toJSON = genericToJSON defaultOptions
2068−instance ToJSON Tiebreaker where
2069− toJSON = genericToJSON defaultOptions
2070−instance ToJSON MinimumMatch where
2071− toJSON = genericToJSON defaultOptions
2072−instance ToJSON DisableCoord where
2073− toJSON = genericToJSON defaultOptions
2074−instance ToJSON PrefixLength where
2075− toJSON = genericToJSON defaultOptions
2076−instance ToJSON Fuzziness where
2077− toJSON = genericToJSON defaultOptions
2078−instance ToJSON IgnoreTermFrequency where
2079− toJSON = genericToJSON defaultOptions
2080−instance ToJSON MaxQueryTerms where
2081− toJSON = genericToJSON defaultOptions
2082−instance ToJSON TypeName where
2083− toJSON = genericToJSON defaultOptions
2084−instance ToJSON IndexName where
2085− toJSON = genericToJSON defaultOptions
2086−instance ToJSON TemplateName where
2087− toJSON = genericToJSON defaultOptions
2088−instance ToJSON TemplatePattern where
2089− toJSON = genericToJSON defaultOptions
2090−instance ToJSON BoostTerms where
2091− toJSON = genericToJSON defaultOptions
2092−instance ToJSON MaxWordLength where
2093− toJSON = genericToJSON defaultOptions
2094−instance ToJSON MinWordLength where
2095− toJSON = genericToJSON defaultOptions
2096−instance ToJSON MaxDocFrequency where
2097− toJSON = genericToJSON defaultOptions
2098−instance ToJSON MinDocFrequency where
2099− toJSON = genericToJSON defaultOptions
2100−instance ToJSON PhraseSlop where
2101− toJSON = genericToJSON defaultOptions
2102−instance ToJSON StopWord where
2103− toJSON = genericToJSON defaultOptions
2104−instance ToJSON QueryPath where
2105− toJSON = genericToJSON defaultOptions
2106−instance ToJSON MinimumTermFrequency where
2107− toJSON = genericToJSON defaultOptions
2108−instance ToJSON PercentMatch where
2109− toJSON = genericToJSON defaultOptions
2110−instance ToJSON MappingName where
2111− toJSON = genericToJSON defaultOptions
2112−instance ToJSON DocId where
2113− toJSON = genericToJSON defaultOptions
2114−instance ToJSON QueryString where
2115− toJSON = genericToJSON defaultOptions
2116−instance ToJSON AllowLeadingWildcard where
2117− toJSON = genericToJSON defaultOptions
2118−instance ToJSON LowercaseExpanded where
2119− toJSON = genericToJSON defaultOptions
2120−instance ToJSON AnalyzeWildcard where
2121− toJSON = genericToJSON defaultOptions
2122−instance ToJSON GeneratePhraseQueries where
2123− toJSON = genericToJSON defaultOptions
2124−instance ToJSON Locale where
2125− toJSON = genericToJSON defaultOptions
2126−instance ToJSON EnablePositionIncrements where
2127− toJSON = genericToJSON defaultOptions
2128−
2129−instance FromJSON Version where
2130− parseJSON = genericParseJSON defaultOptions
2131−instance FromJSON IndexName where
2132− parseJSON = genericParseJSON defaultOptions
2133−instance FromJSON MappingName where
2134− parseJSON = genericParseJSON defaultOptions
2135−instance FromJSON DocId where
2136− parseJSON = genericParseJSON defaultOptions
2137−
2138
2556
2139instance FromJSON Status where
2557instance FromJSON Status where
2140 parseJSON (Object v) = Status <$>
2558 parseJSON (Object v) = Status <$>
@@ -2188,6 +2606,62 @@ instance FromJSON EsError where
2188 v .: "error"
2606 v .: "error"
2189 parseJSON _ = empty
2607 parseJSON _ = empty
2190
2608
2609+instance FromJSON IndexAliasesSummary where
2610+ parseJSON = withObject "IndexAliasesSummary" parse
2611+ where parse o = IndexAliasesSummary . mconcat <$> mapM (uncurry go) (HM.toList o)
2612+ go ixn = withObject "index aliases" $ \ia -> do
2613+ aliases <- ia .: "aliases"
2614+ forM (HM.toList aliases) $ \(aName, v) -> do
2615+ let indexAlias = IndexAlias (IndexName ixn) (IndexAliasName (IndexName aName))
2616+ IndexAliasSummary indexAlias <$> parseJSON v
2617+
2618+
2619+instance ToJSON IndexAliasAction where
2620+ toJSON (AddAlias ia opts) = object ["add" .= (iaObj <> optsObj)]
2621+ where Object iaObj = toJSON ia
2622+ Object optsObj = toJSON opts
2623+ toJSON (RemoveAlias ia) = object ["remove" .= iaObj]
2624+ where Object iaObj = toJSON ia
2625+
2626+instance ToJSON IndexAlias where
2627+ toJSON IndexAlias {..} = object ["index" .= srcIndex
2628+ , "alias" .= indexAlias
2629+ ]
2630+
2631+instance ToJSON IndexAliasCreate where
2632+ toJSON IndexAliasCreate {..} = Object (filterObj <> routingObj)
2633+ where filterObj = maybe mempty (HM.singleton "filter" . toJSON) aliasCreateFilter
2634+ Object routingObj = maybe (Object mempty) toJSON aliasCreateRouting
2635+
2636+instance ToJSON AliasRouting where
2637+ toJSON (AllAliasRouting v) = object ["routing" .= v]
2638+ toJSON (GranularAliasRouting srch idx) = object (catMaybes prs)
2639+ where prs = [("search_routing" .=) <$> srch
2640+ ,("index_routing" .=) <$> idx]
2641+
2642+instance FromJSON AliasRouting where
2643+ parseJSON = withObject "AliasRouting" parse
2644+ where parse o = parseAll o <|> parseGranular o
2645+ parseAll o = AllAliasRouting <$> o .: "routing"
2646+ parseGranular o = do
2647+ sr <- o .:? "search_routing"
2648+ ir <- o .:? "index_routing"
2649+ if isNothing sr && isNothing ir
2650+ then fail "Both search_routing and index_routing can't be blank"
2651+ else return (GranularAliasRouting sr ir)
2652+
2653+instance FromJSON IndexAliasCreate where
2654+ parseJSON v = withObject "IndexAliasCreate" parse v
2655+ where parse o = IndexAliasCreate <$> optional (parseJSON v)
2656+ <*> o .:? "filter"
2657+
2658+instance ToJSON SearchAliasRouting where
2659+ toJSON (SearchAliasRouting rvs) = toJSON (T.intercalate "," (routingValue <$> toList rvs))
2660+
2661+instance FromJSON SearchAliasRouting where
2662+ parseJSON = withText "SearchAliasRouting" parse
2663+ where parse t = SearchAliasRouting <$> parseNEJSON (String <$> T.splitOn "," t)
2664+
2191instance ToJSON Search where
2665instance ToJSON Search where
2192 toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
2666 toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
2193 omitNulls [ "query" .= query
2667 omitNulls [ "query" .= query
@@ -2270,6 +2744,9 @@ fastVectorHighPairs (Just
2270 ++ commonHighlightPairs fvCom
2744 ++ commonHighlightPairs fvCom
2271 ++ nonPostingsToPairs fvNonPostSettings
2745 ++ nonPostingsToPairs fvNonPostSettings
2272
2746
2747+deleteSeveral :: (Eq k, Hashable k) => [k] -> HM.HashMap k v -> HM.HashMap k v
2748+deleteSeveral ks hm = foldr HM.delete hm ks
2749+
2273commonHighlightPairs :: Maybe CommonHighlight -> [Pair]
2750commonHighlightPairs :: Maybe CommonHighlight -> [Pair]
2274commonHighlightPairs Nothing = []
2751commonHighlightPairs Nothing = []
2275commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder
2752commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder
@@ -2290,6 +2767,9 @@ nonPostingsToPairs (Just (NonPostings npFragSize npNumOfFrags)) =
2290 [ "fragment_size" .= npFragSize
2767 [ "fragment_size" .= npFragSize
2291 , "number_of_fragments" .= npNumOfFrags]
2768 , "number_of_fragments" .= npNumOfFrags]
2292
2769
2770+parseNEJSON :: (FromJSON a) => [Value] -> Parser (NonEmpty a)
2771+parseNEJSON [] = fail "Expected non-empty list"
2772+parseNEJSON (x:xs) = DT.mapM parseJSON (x :| xs)
2293
2773
2294
2774
2295instance ToJSON HighlightEncoder where
2775instance ToJSON HighlightEncoder where
@@ -2343,6 +2823,13 @@ instance ToJSON ScoreType where
2343 toJSON ScoreTypeSum = "sum"
2823 toJSON ScoreTypeSum = "sum"
2344 toJSON ScoreTypeNone = "none"
2824 toJSON ScoreTypeNone = "none"
2345
2825
2826+instance FromJSON ScoreType where
2827+ parseJSON = withText "ScoreType" parse
2828+ where parse "max" = pure ScoreTypeMax
2829+ parse "avg" = pure ScoreTypeAvg
2830+ parse "sum" = pure ScoreTypeSum
2831+ parse "none" = pure ScoreTypeNone
2832+ parse t = fail ("Unexpected ScoreType: " <> show t)
2346
2833
2347instance ToJSON Distance where
2834instance ToJSON Distance where
2348 toJSON (Distance dCoefficient dUnit) =
2835 toJSON (Distance dCoefficient dUnit) =
@@ -2351,6 +2838,18 @@ instance ToJSON Distance where
2351 (String unitText) = toJSON dUnit
2838 (String unitText) = toJSON dUnit
2352 boltedTogether = mappend coefText unitText
2839 boltedTogether = mappend coefText unitText
2353
2840
2841+instance FromJSON Distance where
2842+ parseJSON = withText "Distance" parse
2843+ where parse t = Distance <$> parseCoeff nT
2844+ <*> parseJSON (String unitT)
2845+ where (nT, unitT) = T.span validForNumber t
2846+ -- may be a better way to do this
2847+ validForNumber '-' = True
2848+ validForNumber '.' = True
2849+ validForNumber 'e' = True
2850+ validForNumber c = isNumber c
2851+ parseCoeff "" = fail "Empty string cannot be parsed as number"
2852+ parseCoeff s = return (read (T.unpack s))
2354
2853
2355instance ToJSON DistanceUnit where
2854instance ToJSON DistanceUnit where
2356 toJSON Miles = String "mi"
2855 toJSON Miles = String "mi"
@@ -2364,16 +2863,42 @@ instance ToJSON DistanceUnit where
2364 toJSON NauticalMiles = String "nmi"
2863 toJSON NauticalMiles = String "nmi"
2365
2864
2366
2865
2866+instance FromJSON DistanceUnit where
2867+ parseJSON = withText "DistanceUnit" parse
2868+ where parse "mi" = pure Miles
2869+ parse "yd" = pure Yards
2870+ parse "ft" = pure Feet
2871+ parse "in" = pure Inches
2872+ parse "km" = pure Kilometers
2873+ parse "m" = pure Meters
2874+ parse "cm" = pure Centimeters
2875+ parse "mm" = pure Millimeters
2876+ parse "nmi" = pure NauticalMiles
2877+ parse u = fail ("Unrecognized DistanceUnit: " <> show u)
2878+
2367instance ToJSON DistanceType where
2879instance ToJSON DistanceType where
2368 toJSON Arc = String "arc"
2880 toJSON Arc = String "arc"
2369 toJSON SloppyArc = String "sloppy_arc"
2881 toJSON SloppyArc = String "sloppy_arc"
2370 toJSON Plane = String "plane"
2882 toJSON Plane = String "plane"
2371
2883
2884+instance FromJSON DistanceType where
2885+ parseJSON = withText "DistanceType" parse
2886+ where parse "arc" = pure Arc
2887+ parse "sloppy_arc" = pure SloppyArc
2888+ parse "plane" = pure Plane
2889+ parse t = fail ("Unrecognized DistanceType: " <> show t)
2890+
2372
2891
2373instance ToJSON OptimizeBbox where
2892instance ToJSON OptimizeBbox where
2374 toJSON NoOptimizeBbox = String "none"
2893 toJSON NoOptimizeBbox = String "none"
2375 toJSON (OptimizeGeoFilterType gft) = toJSON gft
2894 toJSON (OptimizeGeoFilterType gft) = toJSON gft
2376
2895
2896+instance FromJSON OptimizeBbox where
2897+ parseJSON v = withText "NoOptimizeBbox" parseNoOptimize v
2898+ <|> parseOptimize v
2899+ where parseNoOptimize "none" = pure NoOptimizeBbox
2900+ parseNoOptimize _ = mzero
2901+ parseOptimize = fmap OptimizeGeoFilterType . parseJSON
2377
2902
2378instance ToJSON GeoBoundingBoxConstraint where
2903instance ToJSON GeoBoundingBoxConstraint where
2379 toJSON (GeoBoundingBoxConstraint
2904 toJSON (GeoBoundingBoxConstraint
@@ -2382,23 +2907,45 @@ instance ToJSON GeoBoundingBoxConstraint where
2382 , "_cache" .= cache
2907 , "_cache" .= cache
2383 , "type" .= type']
2908 , "type" .= type']
2384
2909
2910+instance FromJSON GeoBoundingBoxConstraint where
2911+ parseJSON = withObject "GeoBoundingBoxConstraint" parse
2912+ where parse o = case HM.toList (deleteSeveral ["type", "_cache"] o) of
2913+ [(fn, v)] -> GeoBoundingBoxConstraint (FieldName fn)
2914+ <$> parseJSON v
2915+ <*> o .:? "_cache" .!= defaultCache
2916+ <*> o .: "type"
2917+ _ -> fail "Could not find field name for GeoBoundingBoxConstraint"
2385
2918
2386instance ToJSON GeoFilterType where
2919instance ToJSON GeoFilterType where
2387 toJSON GeoFilterMemory = String "memory"
2920 toJSON GeoFilterMemory = String "memory"
2388 toJSON GeoFilterIndexed = String "indexed"
2921 toJSON GeoFilterIndexed = String "indexed"
2389
2922
2923+instance FromJSON GeoFilterType where
2924+ parseJSON = withText "GeoFilterType" parse
2925+ where parse "memory" = pure GeoFilterMemory
2926+ parse "indexed" = pure GeoFilterIndexed
2927+ parse t = fail ("Unrecognized GeoFilterType: " <> show t)
2390
2928
2391instance ToJSON GeoBoundingBox where
2929instance ToJSON GeoBoundingBox where
2392 toJSON (GeoBoundingBox gbbTopLeft gbbBottomRight) =
2930 toJSON (GeoBoundingBox gbbTopLeft gbbBottomRight) =
2393 object ["top_left" .= gbbTopLeft
2931 object ["top_left" .= gbbTopLeft
2394 , "bottom_right" .= gbbBottomRight]
2932 , "bottom_right" .= gbbBottomRight]
2395
2933
2934+instance FromJSON GeoBoundingBox where
2935+ parseJSON = withObject "GeoBoundingBox" parse
2936+ where parse o = GeoBoundingBox
2937+ <$> o .: "top_left"
2938+ <*> o .: "bottom_right"
2396
2939
2397instance ToJSON LatLon where
2940instance ToJSON LatLon where
2398 toJSON (LatLon lLat lLon) =
2941 toJSON (LatLon lLat lLon) =
2399 object ["lat" .= lLat
2942 object ["lat" .= lLat
2400 , "lon" .= lLon]
2943 , "lon" .= lLon]
2401
2944
2945+instance FromJSON LatLon where
2946+ parseJSON = withObject "LatLon" parse
2947+ where parse o = LatLon <$> o .: "lat"
2948+ <*> o .: "lon"
2402
2949
2403-- index for smaller ranges, fielddata for longer ranges
2950-- index for smaller ranges, fielddata for longer ranges
2404instance ToJSON RangeExecution where
2951instance ToJSON RangeExecution where
@@ -2406,6 +2953,12 @@ instance ToJSON RangeExecution where
2406 toJSON RangeExecutionFielddata = "fielddata"
2953 toJSON RangeExecutionFielddata = "fielddata"
2407
2954
2408
2955
2956+instance FromJSON RangeExecution where
2957+ parseJSON = withText "RangeExecution" parse
2958+ where parse "index" = pure RangeExecutionIndex
2959+ parse "fielddata" = pure RangeExecutionFielddata
2960+ parse t = error ("Unrecognized RangeExecution " <> show t)
2961+
2409instance ToJSON RegexpFlags where
2962instance ToJSON RegexpFlags where
2410 toJSON AllRegexpFlags = String "ALL"
2963 toJSON AllRegexpFlags = String "ALL"
2411 toJSON NoRegexpFlags = String "NONE"
2964 toJSON NoRegexpFlags = String "NONE"
@@ -2418,10 +2971,32 @@ instance ToJSON RegexpFlags where
2418 flagStr Intersection = "INTERSECTION"
2971 flagStr Intersection = "INTERSECTION"
2419 flagStr Interval = "INTERVAL"
2972 flagStr Interval = "INTERVAL"
2420
2973
2974+instance FromJSON RegexpFlags where
2975+ parseJSON = withText "RegexpFlags" parse
2976+ where parse "ALL" = pure AllRegexpFlags
2977+ parse "NONE" = pure NoRegexpFlags
2978+ parse t = SomeRegexpFlags <$> parseNEJSON (String <$> T.splitOn "|" t)
2979+
2980+instance FromJSON RegexpFlag where
2981+ parseJSON = withText "RegexpFlag" parse
2982+ where parse "ANYSTRING" = pure AnyString
2983+ parse "AUTOMATON" = pure Automaton
2984+ parse "COMPLEMENT" = pure Complement
2985+ parse "EMPTY" = pure Empty
2986+ parse "INTERSECTION" = pure Intersection
2987+ parse "INTERVAL" = pure Interval
2988+ parse f = fail ("Unknown RegexpFlag: " <> show f)
2989+
2421instance ToJSON Term where
2990instance ToJSON Term where
2422 toJSON (Term field value) = object ["term" .= object
2991 toJSON (Term field value) = object ["term" .= object
2423 [field .= value]]
2992 [field .= value]]
2424
2993
2994+instance FromJSON Term where
2995+ parseJSON = withObject "Term" parse
2996+ where parse o = do termObj <- o .: "term"
2997+ case HM.toList termObj of
2998+ [(fn, v)] -> Term fn <$> parseJSON v
2999+ _ -> fail "Expected object with 1 field-named key"
2425
3000
2426instance ToJSON BoolMatch where
3001instance ToJSON BoolMatch where
2427 toJSON (MustMatch term cache) = object ["must" .= term,
3002 toJSON (MustMatch term cache) = object ["must" .= term,
@@ -2431,6 +3006,15 @@ instance ToJSON BoolMatch where
2431 toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
3006 toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
2432 "_cache" .= cache]
3007 "_cache" .= cache]
2433
3008
3009+instance FromJSON BoolMatch where
3010+ parseJSON = withObject "BoolMatch" parse
3011+ where parse o = mustMatch `taggedWith` "must"
3012+ <|> mustNotMatch `taggedWith` "must_not"
3013+ <|> shouldMatch `taggedWith` "should"
3014+ where taggedWith parser k = parser =<< o .: k
3015+ mustMatch t = MustMatch t <$> o .:? "_cache" .!= defaultCache
3016+ mustNotMatch t = MustNotMatch t <$> o .:? "_cache" .!= defaultCache
3017+ shouldMatch t = ShouldMatch t <$> o .:? "_cache" .!= defaultCache
2434
3018
2435instance (FromJSON a) => FromJSON (SearchResult a) where
3019instance (FromJSON a) => FromJSON (SearchResult a) where
2436 parseJSON (Object v) = SearchResult <$>
3020 parseJSON (Object v) = SearchResult <$>
tests/tests.hs+376−46
@@ -1,6 +1,8 @@
1−{-# LANGUAGE DeriveGeneric #-}
1+{-# LANGUAGE DeriveGeneric #-}
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2−{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
5+{-# LANGUAGE TemplateHaskell #-}
4{-# OPTIONS_GHC -fno-warn-orphans #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
5module Main where
7module Main where
6
8
@@ -9,21 +11,26 @@ import Control.Exception
9import Control.Monad
11import Control.Monad
10import Control.Monad.Reader
12import Control.Monad.Reader
11import Data.Aeson
13import Data.Aeson
14+import Data.Aeson.Types (parseEither)
15+import Data.DeriveTH
12import qualified Data.HashMap.Strict as HM
16import qualified Data.HashMap.Strict as HM
13import Data.List (nub)
17import Data.List (nub)
18+import qualified Data.List as L
14import Data.List.NonEmpty (NonEmpty (..))
19import Data.List.NonEmpty (NonEmpty (..))
15import qualified Data.List.NonEmpty as NE
20import qualified Data.List.NonEmpty as NE
16import qualified Data.Map.Strict as M
21import qualified Data.Map.Strict as M
17import Data.Monoid
22import Data.Monoid
23+import Data.Proxy
18import Data.Text (Text)
24import Data.Text (Text)
19import qualified Data.Text as T
25import qualified Data.Text as T
20import Data.Time.Calendar (Day (..))
26import Data.Time.Calendar (Day (..))
21import Data.Time.Clock (UTCTime (..),
27import Data.Time.Clock (UTCTime (..),
22 secondsToDiffTime)
28 secondsToDiffTime)
29+import Data.Typeable
23import qualified Data.Vector as V
30import qualified Data.Vector as V
24import Database.Bloodhound
31import Database.Bloodhound
25import GHC.Generics (Generic)
32import GHC.Generics (Generic)
26−import Network.HTTP.Client
33+import Network.HTTP.Client hiding (Proxy)
27import qualified Network.HTTP.Types.Status as NHTS
34import qualified Network.HTTP.Types.Status as NHTS
28import Prelude hiding (filter)
35import Prelude hiding (filter)
29import Test.Hspec
36import Test.Hspec
@@ -31,6 +38,7 @@ import Test.QuickCheck.Property.Monoid (T (..), eq, prop_Monoid)
31
38
32import Test.Hspec.QuickCheck (prop)
39import Test.Hspec.QuickCheck (prop)
33import Test.QuickCheck
40import Test.QuickCheck
41+import Test.QuickCheck.Instances ()
34
42
35testServer :: Server
43testServer :: Server
36testServer = Server "http://localhost:9200"
44testServer = Server "http://localhost:9200"
@@ -101,6 +109,12 @@ is v = testServerBranch >>= \x -> return $ x == Just (serverBranch v)
101when' :: Monad m => m Bool -> m () -> m ()
109when' :: Monad m => m Bool -> m () -> m ()
102when' b f = b >>= \x -> when x f
110when' b f = b >>= \x -> when x f
103
111
112+propJSON :: forall a. (Arbitrary a, ToJSON a, FromJSON a, Show a, Eq a, Typeable a) => Proxy a -> Spec
113+propJSON _ = prop testName $ \(a :: a) ->
114+ parseEither parseJSON (toJSON a) === Right a
115+ where testName = show ty <> " FromJSON/ToJSON roundtrips"
116+ ty = typeOf (undefined :: a)
117+
104data Location = Location { lat :: Double
118data Location = Location { lat :: Double
105 , lon :: Double } deriving (Eq, Generic, Show)
119 , lon :: Double } deriving (Eq, Generic, Show)
106
120
@@ -197,15 +211,15 @@ insertWithSpaceInId = do
197 _ <- refreshIndex testIndex
211 _ <- refreshIndex testIndex
198 return ()
212 return ()
199
213
200−searchTweet :: Search -> BH IO (Either String Tweet)
214+searchTweet :: Search -> BH IO (Either EsError Tweet)
201searchTweet search = do
215searchTweet search = do
202 result <- searchTweets search
216 result <- searchTweets search
203− let myTweet :: Either String Tweet
217+ let myTweet :: Either EsError Tweet
204 myTweet = grabFirst result
218 myTweet = grabFirst result
205 return myTweet
219 return myTweet
206
220
207−searchTweets :: Search -> BH IO (Either String (SearchResult Tweet))
221+searchTweets :: Search -> BH IO (Either EsError (SearchResult Tweet))
208−searchTweets search = eitherDecode . responseBody <$> searchByIndex testIndex search
222+searchTweets search = parseEsResponse =<< searchByIndex testIndex search
209
223
210searchExpectNoResults :: Search -> BH IO ()
224searchExpectNoResults :: Search -> BH IO ()
211searchExpectNoResults search = do
225searchExpectNoResults search = do
@@ -239,19 +253,19 @@ searchTermsAggHint hints = do
239 forM_ hints $ searchExpectAggs . search
253 forM_ hints $ searchExpectAggs . search
240 forM_ hints (\x -> searchValidBucketAgg (search x) "users" toTerms)
254 forM_ hints (\x -> searchValidBucketAgg (search x) "users" toTerms)
241
255
242−searchTweetHighlight :: Search -> BH IO (Either String (Maybe HitHighlight))
256+searchTweetHighlight :: Search -> BH IO (Either EsError (Maybe HitHighlight))
243searchTweetHighlight search = do
257searchTweetHighlight search = do
244 result <- searchTweets search
258 result <- searchTweets search
245 let myHighlight = fmap (hitHighlight . head . hits . searchHits) result
259 let myHighlight = fmap (hitHighlight . head . hits . searchHits) result
246 return myHighlight
260 return myHighlight
247
261
248−searchExpectSource :: Source -> Either String Value -> BH IO ()
262+searchExpectSource :: Source -> Either EsError Value -> BH IO ()
249searchExpectSource src expected = do
263searchExpectSource src expected = do
250 _ <- insertData
264 _ <- insertData
251 let query = QueryMatchQuery $ mkMatchQuery (FieldName "_all") (QueryString "haskell")
265 let query = QueryMatchQuery $ mkMatchQuery (FieldName "_all") (QueryString "haskell")
252 let search = (mkSearch (Just query) Nothing) { source = Just src }
266 let search = (mkSearch (Just query) Nothing) { source = Just src }
253 reply <- searchAll search
267 reply <- searchAll search
254− let result = eitherDecode (responseBody reply) :: Either String (SearchResult Value)
268+ result <- parseEsResponse reply-- :: Either EsError (SearchResult Value)
255 let value = grabFirst result
269 let value = grabFirst result
256 liftIO $
270 liftIO $
257 value `shouldBe` expected
271 value `shouldBe` expected
@@ -265,42 +279,12 @@ instance ToJSON BulkTest where
265noDuplicates :: Eq a => [a] -> Bool
279noDuplicates :: Eq a => [a] -> Bool
266noDuplicates xs = nub xs == xs
280noDuplicates xs = nub xs == xs
267
281
268−instance Arbitrary RegexpFlags where
269− arbitrary = oneof [ pure AllRegexpFlags
270− , pure NoRegexpFlags
271− , SomeRegexpFlags <$> arbitrary
272− ]
273−
274instance Arbitrary a => Arbitrary (NonEmpty a) where
282instance Arbitrary a => Arbitrary (NonEmpty a) where
275 arbitrary = liftA2 (:|) arbitrary arbitrary
283 arbitrary = liftA2 (:|) arbitrary arbitrary
276
284
277−instance Arbitrary RegexpFlag where
278− arbitrary = oneof [ pure AnyString
279− , pure Automaton
280− , pure Complement
281− , pure Empty
282− , pure Intersection
283− , pure Interval
284− ]
285−
286arbitraryScore :: Gen Score
285arbitraryScore :: Gen Score
287arbitraryScore = fmap getPositive <$> arbitrary
286arbitraryScore = fmap getPositive <$> arbitrary
288
287
289−instance Arbitrary Text where
290− arbitrary = T.pack <$> arbitrary
291−
292−instance (Arbitrary k, Arbitrary v, Ord k) => Arbitrary (M.Map k v) where
293− arbitrary = M.fromList <$> arbitrary
294−
295−instance Arbitrary IndexName where
296− arbitrary = IndexName <$> arbitrary
297−
298−instance Arbitrary MappingName where
299− arbitrary = MappingName <$> arbitrary
300−
301−instance Arbitrary DocId where
302− arbitrary = DocId <$> arbitrary
303−
304instance Arbitrary a => Arbitrary (Hit a) where
288instance Arbitrary a => Arbitrary (Hit a) where
305 arbitrary = Hit <$> arbitrary
289 arbitrary = Hit <$> arbitrary
306 <*> arbitrary
290 <*> arbitrary
@@ -311,22 +295,212 @@ instance Arbitrary a => Arbitrary (Hit a) where
311
295
312
296
313instance Arbitrary a => Arbitrary (SearchHits a) where
297instance Arbitrary a => Arbitrary (SearchHits a) where
314− arbitrary = sized $ \n -> resize (n `div` 2) $ do
298+ arbitrary = reduceSize $ do
315 tot <- getPositive <$> arbitrary
299 tot <- getPositive <$> arbitrary
316 score <- arbitraryScore
300 score <- arbitraryScore
317 hs <- arbitrary
301 hs <- arbitrary
318 return $ SearchHits tot score hs
302 return $ SearchHits tot score hs
319
303
304+reduceSize :: Gen a -> Gen a
305+reduceSize f = sized $ \n -> resize (n `div` 2) f
306+
320getSource :: EsResult a -> Maybe a
307getSource :: EsResult a -> Maybe a
321getSource = fmap _source . foundResult
308getSource = fmap _source . foundResult
322
309
323−grabFirst :: Either String (SearchResult a) -> Either String a
310+grabFirst :: Either EsError (SearchResult a) -> Either EsError a
324grabFirst r =
311grabFirst r =
325 case fmap (hitSource . head . hits . searchHits) r of
312 case fmap (hitSource . head . hits . searchHits) r of
326 (Left e) -> Left e
313 (Left e) -> Left e
327− (Right Nothing) -> Left "Source was missing"
314+ (Right Nothing) -> Left (EsError 500 "Source was missing")
328 (Right (Just x)) -> Right x
315 (Right (Just x)) -> Right x
329
316
317+-------------------------------------------------------------------------------
318+arbitraryAlphaNum :: Gen Char
319+arbitraryAlphaNum = oneof [choose ('a', 'z')
320+ ,choose ('A','Z')
321+ , choose ('0', '9')]
322+
323+instance Arbitrary RoutingValue where
324+ arbitrary = RoutingValue . T.pack <$> listOf1 arbitraryAlphaNum
325+
326+instance Arbitrary AliasRouting where
327+ arbitrary = oneof [allAlias
328+ ,one
329+ ,theOther
330+ ,both]
331+ where one = GranularAliasRouting
332+ <$> (Just <$> arbitrary)
333+ <*> pure Nothing
334+ theOther = GranularAliasRouting Nothing
335+ <$> (Just <$> arbitrary)
336+ both = GranularAliasRouting
337+ <$> (Just <$> arbitrary)
338+ <*> (Just <$> arbitrary)
339+ allAlias = AllAliasRouting <$> arbitrary
340+
341+instance Arbitrary FieldName where
342+ arbitrary = FieldName . T.pack <$> listOf1 arbitraryAlphaNum
343+
344+instance Arbitrary RegexpFlags where
345+ arbitrary = oneof [ pure AllRegexpFlags
346+ , pure NoRegexpFlags
347+ , SomeRegexpFlags <$> genUniqueFlags
348+ ]
349+ where genUniqueFlags = NE.fromList . nub <$> listOf1 arbitrary
350+
351+instance Arbitrary IndexAliasCreate where
352+ arbitrary = IndexAliasCreate <$> arbitrary <*> reduceSize arbitrary
353+
354+instance Arbitrary Query where
355+ arbitrary = reduceSize $ oneof [ TermQuery <$> arbitrary <*> arbitrary
356+ , TermsQuery <$> arbitrary <*> arbitrary
357+ , QueryMatchQuery <$> arbitrary
358+ , QueryMultiMatchQuery <$> arbitrary
359+ , QueryBoolQuery <$> arbitrary
360+ , QueryBoostingQuery <$> arbitrary
361+ , QueryCommonTermsQuery <$> arbitrary
362+ , ConstantScoreFilter <$> arbitrary <*> arbitrary
363+ , ConstantScoreQuery <$> arbitrary <*> arbitrary
364+ , QueryDisMaxQuery <$> arbitrary
365+ , QueryFilteredQuery <$> arbitrary
366+ , QueryFuzzyLikeThisQuery <$> arbitrary
367+ , QueryFuzzyLikeFieldQuery <$> arbitrary
368+ , QueryFuzzyQuery <$> arbitrary
369+ , QueryHasChildQuery <$> arbitrary
370+ , QueryHasParentQuery <$> arbitrary
371+ , IdsQuery <$> arbitrary <*> arbitrary
372+ , QueryIndicesQuery <$> arbitrary
373+ , MatchAllQuery <$> arbitrary
374+ , QueryMoreLikeThisQuery <$> arbitrary
375+ , QueryMoreLikeThisFieldQuery <$> arbitrary
376+ , QueryNestedQuery <$> arbitrary
377+ , QueryPrefixQuery <$> arbitrary
378+ , QueryQueryStringQuery <$> arbitrary
379+ , QuerySimpleQueryStringQuery <$> arbitrary
380+ , QueryRangeQuery <$> arbitrary
381+ , QueryRegexpQuery <$> arbitrary
382+ ]
383+
384+instance Arbitrary Filter where
385+ arbitrary = reduceSize $ oneof [ AndFilter <$> arbitrary <*> arbitrary
386+ , OrFilter <$> arbitrary <*> arbitrary
387+ , NotFilter <$> arbitrary <*> arbitrary
388+ , pure IdentityFilter
389+ , BoolFilter <$> arbitrary
390+ , ExistsFilter <$> arbitrary
391+ , GeoBoundingBoxFilter <$> arbitrary
392+ , GeoDistanceFilter <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
393+ , GeoDistanceRangeFilter <$> arbitrary <*> arbitrary
394+ , GeoPolygonFilter <$> arbitrary <*> arbitrary
395+ , IdsFilter <$> arbitrary <*> arbitrary
396+ , LimitFilter <$> arbitrary
397+ , MissingFilter <$> arbitrary <*> arbitrary <*> arbitrary
398+ , PrefixFilter <$> arbitrary <*> arbitrary <*> arbitrary
399+ , QueryFilter <$> arbitrary <*> arbitrary
400+ , RangeFilter <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
401+ , RegexpFilter <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
402+ , TermFilter <$> arbitrary <*> arbitrary]
403+
404+$(derive makeArbitrary ''IndexName)
405+$(derive makeArbitrary ''MappingName)
406+$(derive makeArbitrary ''DocId)
407+$(derive makeArbitrary ''Version)
408+$(derive makeArbitrary ''IndexAliasRouting)
409+$(derive makeArbitrary ''ShardCount)
410+$(derive makeArbitrary ''ReplicaCount)
411+$(derive makeArbitrary ''TemplateName)
412+$(derive makeArbitrary ''TemplatePattern)
413+$(derive makeArbitrary ''QueryString)
414+$(derive makeArbitrary ''CacheName)
415+$(derive makeArbitrary ''CacheKey)
416+$(derive makeArbitrary ''Existence)
417+$(derive makeArbitrary ''CutoffFrequency)
418+$(derive makeArbitrary ''Analyzer)
419+$(derive makeArbitrary ''MaxExpansions)
420+$(derive makeArbitrary ''Lenient)
421+$(derive makeArbitrary ''Tiebreaker)
422+$(derive makeArbitrary ''Boost)
423+$(derive makeArbitrary ''BoostTerms)
424+$(derive makeArbitrary ''MinimumMatch)
425+$(derive makeArbitrary ''DisableCoord)
426+$(derive makeArbitrary ''IgnoreTermFrequency)
427+$(derive makeArbitrary ''MinimumTermFrequency)
428+$(derive makeArbitrary ''MaxQueryTerms)
429+$(derive makeArbitrary ''Fuzziness)
430+$(derive makeArbitrary ''PrefixLength)
431+$(derive makeArbitrary ''TypeName)
432+$(derive makeArbitrary ''PercentMatch)
433+$(derive makeArbitrary ''StopWord)
434+$(derive makeArbitrary ''QueryPath)
435+$(derive makeArbitrary ''AllowLeadingWildcard)
436+$(derive makeArbitrary ''LowercaseExpanded)
437+$(derive makeArbitrary ''EnablePositionIncrements)
438+$(derive makeArbitrary ''AnalyzeWildcard)
439+$(derive makeArbitrary ''GeneratePhraseQueries)
440+$(derive makeArbitrary ''Locale)
441+$(derive makeArbitrary ''MaxWordLength)
442+$(derive makeArbitrary ''MinWordLength)
443+$(derive makeArbitrary ''PhraseSlop)
444+$(derive makeArbitrary ''MinDocFrequency)
445+$(derive makeArbitrary ''MaxDocFrequency)
446+$(derive makeArbitrary ''Regexp)
447+$(derive makeArbitrary ''SimpleQueryStringQuery)
448+$(derive makeArbitrary ''FieldOrFields)
449+$(derive makeArbitrary ''SimpleQueryFlag)
450+$(derive makeArbitrary ''RegexpQuery)
451+$(derive makeArbitrary ''QueryStringQuery)
452+$(derive makeArbitrary ''RangeQuery)
453+$(derive makeArbitrary ''RangeValue)
454+$(derive makeArbitrary ''PrefixQuery)
455+$(derive makeArbitrary ''NestedQuery)
456+$(derive makeArbitrary ''MoreLikeThisFieldQuery)
457+$(derive makeArbitrary ''MoreLikeThisQuery)
458+$(derive makeArbitrary ''IndicesQuery)
459+$(derive makeArbitrary ''HasParentQuery)
460+$(derive makeArbitrary ''HasChildQuery)
461+$(derive makeArbitrary ''FuzzyQuery)
462+$(derive makeArbitrary ''FuzzyLikeFieldQuery)
463+$(derive makeArbitrary ''FuzzyLikeThisQuery)
464+$(derive makeArbitrary ''FilteredQuery)
465+$(derive makeArbitrary ''DisMaxQuery)
466+$(derive makeArbitrary ''CommonTermsQuery)
467+$(derive makeArbitrary ''DistanceRange)
468+$(derive makeArbitrary ''MultiMatchQuery)
469+$(derive makeArbitrary ''LessThanD)
470+$(derive makeArbitrary ''LessThanEqD)
471+$(derive makeArbitrary ''GreaterThanD)
472+$(derive makeArbitrary ''GreaterThanEqD)
473+$(derive makeArbitrary ''LessThan)
474+$(derive makeArbitrary ''LessThanEq)
475+$(derive makeArbitrary ''GreaterThan)
476+$(derive makeArbitrary ''GreaterThanEq)
477+$(derive makeArbitrary ''GeoPoint)
478+$(derive makeArbitrary ''NullValue)
479+$(derive makeArbitrary ''MinimumMatchHighLow)
480+$(derive makeArbitrary ''CommonMinimumMatch)
481+$(derive makeArbitrary ''BoostingQuery)
482+$(derive makeArbitrary ''BoolQuery)
483+$(derive makeArbitrary ''MatchQuery)
484+$(derive makeArbitrary ''MultiMatchQueryType)
485+$(derive makeArbitrary ''BooleanOperator)
486+$(derive makeArbitrary ''ZeroTermsQuery)
487+$(derive makeArbitrary ''MatchQueryType)
488+$(derive makeArbitrary ''SearchAliasRouting)
489+$(derive makeArbitrary ''ScoreType)
490+$(derive makeArbitrary ''Distance)
491+$(derive makeArbitrary ''DistanceUnit)
492+$(derive makeArbitrary ''DistanceType)
493+$(derive makeArbitrary ''OptimizeBbox)
494+$(derive makeArbitrary ''GeoBoundingBoxConstraint)
495+$(derive makeArbitrary ''GeoFilterType)
496+$(derive makeArbitrary ''GeoBoundingBox)
497+$(derive makeArbitrary ''LatLon)
498+$(derive makeArbitrary ''RangeExecution)
499+$(derive makeArbitrary ''RegexpFlag)
500+$(derive makeArbitrary ''BoolMatch)
501+$(derive makeArbitrary ''Term)
502+
503+
330main :: IO ()
504main :: IO ()
331main = hspec $ do
505main = hspec $ do
332
506
@@ -437,9 +611,29 @@ main = hspec $ do
437 liftIO $
611 liftIO $
438 myTweet `shouldBe` Right exampleTweet
612 myTweet `shouldBe` Right exampleTweet
439
613
614+ it "handles constant score queries" $ withTestEnv $ do
615+ _ <- insertData
616+ let query = TermsQuery "user" ("bitemyapp" :| [])
617+ let cfQuery = ConstantScoreQuery query (Boost 1.0)
618+ let filter = IdentityFilter
619+ let search = mkSearch (Just cfQuery) (Just filter)
620+ myTweet <- searchTweet search
621+ liftIO $
622+ myTweet `shouldBe` Right exampleTweet
623+ it "handles constant score filters" $ withTestEnv $ do
624+ _ <- insertData
625+ let query = TermsQuery "user" ("bitemyapp" :| [])
626+ let cfFilter = ConstantScoreFilter IdentityFilter (Boost 1.0)
627+ let boolQuery = mkBoolQuery [query, cfFilter] [] []
628+ let search = mkSearch (Just (QueryBoolQuery boolQuery)) Nothing
629+ myTweet <- searchTweet search
630+ liftIO $
631+ myTweet `shouldBe` Right exampleTweet
632+
633+
440 it "returns document for terms query and identity filter" $ withTestEnv $ do
634 it "returns document for terms query and identity filter" $ withTestEnv $ do
441 _ <- insertData
635 _ <- insertData
442− let query = TermsQuery (NE.fromList [(Term "user" "bitemyapp")])
636+ let query = TermsQuery "user" ("bitemyapp" :| [])
443 let filter = IdentityFilter <&&> IdentityFilter
637 let filter = IdentityFilter <&&> IdentityFilter
444 let search = mkSearch (Just query) (Just filter)
638 let search = mkSearch (Just query) (Just filter)
445 myTweet <- searchTweet search
639 myTweet <- searchTweet search
@@ -772,7 +966,7 @@ main = hspec $ do
772 it "doesn't include source when sources are disabled" $ withTestEnv $ do
966 it "doesn't include source when sources are disabled" $ withTestEnv $ do
773 searchExpectSource
967 searchExpectSource
774 NoSource
968 NoSource
775− (Left "Source was missing")
969+ (Left (EsError 500 "Source was missing"))
776
970
777 it "includes a source" $ withTestEnv $ do
971 it "includes a source" $ withTestEnv $ do
778 searchExpectSource
972 searchExpectSource
@@ -869,3 +1063,139 @@ main = hspec $ do
869 regular_search `shouldBe` Right exampleTweet -- Check that the size restrtiction is being honored
1063 regular_search `shouldBe` Right exampleTweet -- Check that the size restrtiction is being honored
870 liftIO $
1064 liftIO $
871 scan_search `shouldMatchList` [Just exampleTweet, Just otherTweet]
1065 scan_search `shouldMatchList` [Just exampleTweet, Just otherTweet]
1066+
1067+ describe "index aliases" $ do
1068+ it "handles the simple case of aliasing an existing index" $ do
1069+ let alias = IndexAlias (testIndex) (IndexAliasName (IndexName "bloodhound-tests-twitter-1-alias"))
1070+ let create = IndexAliasCreate Nothing Nothing
1071+ let action = AddAlias alias create
1072+
1073+ withTestEnv $ do
1074+ resetIndex
1075+ resp <- updateIndexAliases (action :| [])
1076+ liftIO $ NHTS.statusCode (responseStatus resp) `shouldBe` 200
1077+ let cleanup = withTestEnv (updateIndexAliases (RemoveAlias alias :| []))
1078+ (do aliases <- withTestEnv getIndexAliases
1079+ let expected = IndexAliasSummary alias create
1080+ case aliases of
1081+ Right (IndexAliasesSummary summs) ->
1082+ L.find ((== alias) . indexAliasSummaryAlias) summs `shouldBe` Just expected
1083+ Left e -> expectationFailure ("Expected an IndexAliasesSummary but got " <> show e)) `finally` cleanup
1084+
1085+ it "handles an alias with routing and a filter" $ do
1086+ let alias = IndexAlias (testIndex) (IndexAliasName (IndexName "bloodhound-tests-twitter-1-alias"))
1087+ let sar = SearchAliasRouting (RoutingValue "search val" :| [])
1088+ let iar = IndexAliasRouting (RoutingValue "index val")
1089+ let routing = GranularAliasRouting (Just sar) (Just iar)
1090+ let filter = LimitFilter 42
1091+ let create = IndexAliasCreate (Just routing) (Just filter)
1092+ let action = AddAlias alias create
1093+
1094+ withTestEnv $ do
1095+ resetIndex
1096+ resp <- updateIndexAliases (action :| [])
1097+ liftIO $ NHTS.statusCode (responseStatus resp) `shouldBe` 200
1098+ let cleanup = withTestEnv (updateIndexAliases (RemoveAlias alias :| []))
1099+ (do aliases <- withTestEnv getIndexAliases
1100+ let expected = IndexAliasSummary alias create
1101+ case aliases of
1102+ Right (IndexAliasesSummary summs) ->
1103+ L.find ((== alias) . indexAliasSummaryAlias) summs `shouldBe` Just expected
1104+ Left e -> expectationFailure ("Expected an IndexAliasesSummary but got " <> show e)) `finally` cleanup
1105+
1106+ describe "JSON instances" $ do
1107+ propJSON (Proxy :: Proxy Version)
1108+ propJSON (Proxy :: Proxy IndexName)
1109+ propJSON (Proxy :: Proxy MappingName)
1110+ propJSON (Proxy :: Proxy DocId)
1111+ propJSON (Proxy :: Proxy IndexAliasRouting)
1112+ propJSON (Proxy :: Proxy RoutingValue)
1113+ propJSON (Proxy :: Proxy ShardCount)
1114+ propJSON (Proxy :: Proxy ReplicaCount)
1115+ propJSON (Proxy :: Proxy TemplateName)
1116+ propJSON (Proxy :: Proxy TemplatePattern)
1117+ propJSON (Proxy :: Proxy QueryString)
1118+ propJSON (Proxy :: Proxy FieldName)
1119+ propJSON (Proxy :: Proxy CacheName)
1120+ propJSON (Proxy :: Proxy CacheKey)
1121+ propJSON (Proxy :: Proxy Existence)
1122+ propJSON (Proxy :: Proxy CutoffFrequency)
1123+ propJSON (Proxy :: Proxy Analyzer)
1124+ propJSON (Proxy :: Proxy MaxExpansions)
1125+ propJSON (Proxy :: Proxy Lenient)
1126+ propJSON (Proxy :: Proxy Tiebreaker)
1127+ propJSON (Proxy :: Proxy Boost)
1128+ propJSON (Proxy :: Proxy BoostTerms)
1129+ propJSON (Proxy :: Proxy MaxExpansions)
1130+ propJSON (Proxy :: Proxy MinimumMatch)
1131+ propJSON (Proxy :: Proxy DisableCoord)
1132+ propJSON (Proxy :: Proxy IgnoreTermFrequency)
1133+ propJSON (Proxy :: Proxy MinimumTermFrequency)
1134+ propJSON (Proxy :: Proxy MaxQueryTerms)
1135+ propJSON (Proxy :: Proxy Fuzziness)
1136+ propJSON (Proxy :: Proxy PrefixLength)
1137+ propJSON (Proxy :: Proxy TypeName)
1138+ propJSON (Proxy :: Proxy PercentMatch)
1139+ propJSON (Proxy :: Proxy StopWord)
1140+ propJSON (Proxy :: Proxy QueryPath)
1141+ propJSON (Proxy :: Proxy AllowLeadingWildcard)
1142+ propJSON (Proxy :: Proxy LowercaseExpanded)
1143+ propJSON (Proxy :: Proxy EnablePositionIncrements)
1144+ propJSON (Proxy :: Proxy AnalyzeWildcard)
1145+ propJSON (Proxy :: Proxy GeneratePhraseQueries)
1146+ propJSON (Proxy :: Proxy Locale)
1147+ propJSON (Proxy :: Proxy MaxWordLength)
1148+ propJSON (Proxy :: Proxy MinWordLength)
1149+ propJSON (Proxy :: Proxy PhraseSlop)
1150+ propJSON (Proxy :: Proxy MinDocFrequency)
1151+ propJSON (Proxy :: Proxy MaxDocFrequency)
1152+ propJSON (Proxy :: Proxy Filter)
1153+ propJSON (Proxy :: Proxy Query)
1154+ propJSON (Proxy :: Proxy SimpleQueryStringQuery)
1155+ propJSON (Proxy :: Proxy FieldOrFields)
1156+ propJSON (Proxy :: Proxy SimpleQueryFlag)
1157+ propJSON (Proxy :: Proxy RegexpQuery)
1158+ propJSON (Proxy :: Proxy QueryStringQuery)
1159+ propJSON (Proxy :: Proxy RangeQuery)
1160+ propJSON (Proxy :: Proxy PrefixQuery)
1161+ propJSON (Proxy :: Proxy NestedQuery)
1162+ propJSON (Proxy :: Proxy MoreLikeThisFieldQuery)
1163+ propJSON (Proxy :: Proxy MoreLikeThisQuery)
1164+ propJSON (Proxy :: Proxy IndicesQuery)
1165+ propJSON (Proxy :: Proxy HasParentQuery)
1166+ propJSON (Proxy :: Proxy HasChildQuery)
1167+ propJSON (Proxy :: Proxy FuzzyQuery)
1168+ propJSON (Proxy :: Proxy FuzzyLikeFieldQuery)
1169+ propJSON (Proxy :: Proxy FuzzyLikeThisQuery)
1170+ propJSON (Proxy :: Proxy FilteredQuery)
1171+ propJSON (Proxy :: Proxy DisMaxQuery)
1172+ propJSON (Proxy :: Proxy CommonTermsQuery)
1173+ propJSON (Proxy :: Proxy CommonMinimumMatch)
1174+ propJSON (Proxy :: Proxy BoostingQuery)
1175+ propJSON (Proxy :: Proxy BoolQuery)
1176+ propJSON (Proxy :: Proxy MatchQuery)
1177+ propJSON (Proxy :: Proxy MultiMatchQueryType)
1178+ propJSON (Proxy :: Proxy BooleanOperator)
1179+ propJSON (Proxy :: Proxy ZeroTermsQuery)
1180+ propJSON (Proxy :: Proxy MatchQueryType)
1181+ propJSON (Proxy :: Proxy AliasRouting)
1182+ propJSON (Proxy :: Proxy IndexAliasCreate)
1183+ propJSON (Proxy :: Proxy SearchAliasRouting)
1184+ propJSON (Proxy :: Proxy ScoreType)
1185+ propJSON (Proxy :: Proxy Distance)
1186+ propJSON (Proxy :: Proxy DistanceUnit)
1187+ propJSON (Proxy :: Proxy DistanceType)
1188+ propJSON (Proxy :: Proxy OptimizeBbox)
1189+ propJSON (Proxy :: Proxy GeoBoundingBoxConstraint)
1190+ propJSON (Proxy :: Proxy GeoFilterType)
1191+ propJSON (Proxy :: Proxy GeoBoundingBox)
1192+ propJSON (Proxy :: Proxy LatLon)
1193+ propJSON (Proxy :: Proxy RangeExecution)
1194+ prop "RegexpFlags FromJSON/ToJSON roundtrips, removing dups " $ \rfs ->
1195+ let expected = case rfs of
1196+ SomeRegexpFlags fs -> SomeRegexpFlags (NE.fromList (nub (NE.toList fs)))
1197+ x -> x
1198+ in parseEither parseJSON (toJSON rfs) === Right expected
1199+ propJSON (Proxy :: Proxy BoolMatch)
1200+ propJSON (Proxy :: Proxy Term)
1201+ propJSON (Proxy :: Proxy MultiMatchQuery)