@@ -58,12 +58,23 @@ module Database.Bloodhound.Types
5858 , Existence(..)
5959 , NullValue(..)
6060 , IndexSettings(..)
61+ , UpdatableIndexSetting(..)
62+ , IndexSettingsSummary(..)
63+ , AllocationPolicy(..)
64+ , ReplicaBounds(..)
65+ , Bytes(..)
66+ , FSType(..)
67+ , InitialShardCount(..)
68+ , NodeAttrFilter(..)
69+ , NodeAttrName(..)
70+ , CompoundFormat(..)
6171 , IndexTemplate(..)
6272 , Server(..)
6373 , Reply
6474 , EsResult(..)
6575 , EsResultFound(..)
6676 , EsError(..)
77+ , EsProtocolException(..)
6778 , IndexAlias(..)
6879 , IndexAliasName(..)
6980 , IndexAliasAction(..)
@@ -83,7 +94,7 @@ module Database.Bloodhound.Types
8394 , Search(..)
8495 , SearchType(..)
8596 , SearchResult(..)
86− , ScrollId
97+ , ScrollId(..)
8798 , SearchHits(..)
8899 , TrackSortScores
89100 , From(..)
@@ -225,6 +236,12 @@ module Database.Bloodhound.Types
225236 , ValueCountAggregation(..)
226237 , FilterAggregation(..)
227238 , DateHistogramAggregation(..)
239+ , DateRangeAggregation(..)
240+ , DateRangeAggRange(..)
241+ , DateMathExpr(..)
242+ , DateMathAnchor(..)
243+ , DateMathModifier(..)
244+ , DateMathUnit(..)
228245
229246 , Highlights(..)
230247 , FieldHighlight(..)
@@ -240,6 +257,7 @@ module Database.Bloodhound.Types
240257
241258 , TermsResult(..)
242259 , DateHistogramResult(..)
260+ , DateRangeResult(..)
243261 ) where
244262
245263import Control.Applicative
@@ -261,7 +279,9 @@ import qualified Data.Map.Strict as M
261279import Data.Maybe
262280import Data.Text (Text)
263281import qualified Data.Text as T
264−import Data.Time.Clock (UTCTime)
282+import Data.Time.Calendar
283+import Data.Time.Clock (NominalDiffTime, UTCTime)
284+import Data.Time.Clock.POSIX
265285import qualified Data.Traversable as DT
266286import Data.Typeable (Typeable)
267287import qualified Data.Vector as V
@@ -349,7 +369,7 @@ data Status = Status { ok :: Maybe Bool
349369 , status :: Int
350370 , name :: Text
351371 , version :: Version
352− , tagline :: Text } deriving (Eq, Show)
372+ , tagline :: Text } deriving (Eq, Show, Generic)
353373
354374{-| 'IndexSettings' is used to configure the shards and replicas when you create
355375 an Elasticsearch Index.
@@ -359,12 +379,111 @@ data Status = Status { ok :: Maybe Bool
359379
360380data IndexSettings =
361381 IndexSettings { indexShards :: ShardCount
362− , indexReplicas :: ReplicaCount } deriving (Eq, Show)
382+ , indexReplicas :: ReplicaCount } deriving (Eq, Show, Generic, Typeable)
363383
364384{-| 'defaultIndexSettings' is an 'IndexSettings' with 3 shards and 2 replicas. -}
365385defaultIndexSettings :: IndexSettings
366386defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
367387
388+{-| 'UpdatableIndexSetting' are settings which may be updated after an index is created.
389+
390+ <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html>
391+-}
392+data UpdatableIndexSetting = NumberOfReplicas ReplicaCount
393+ -- ^ The number of replicas each shard has.
394+ | AutoExpandReplicas ReplicaBounds
395+ | BlocksReadOnly Bool
396+ -- ^ Set to True to have the index read only. False to allow writes and metadata changes.
397+ | BlocksRead Bool
398+ -- ^ Set to True to disable read operations against the index.
399+ | BlocksWrite Bool
400+ -- ^ Set to True to disable write operations against the index.
401+ | BlocksMetaData Bool
402+ -- ^ Set to True to disable metadata operations against the index.
403+ | RefreshInterval NominalDiffTime
404+ -- ^ The async refresh interval of a shard
405+ | IndexConcurrency Int
406+ | FailOnMergeFailure Bool
407+ | TranslogFlushThresholdOps Int
408+ -- ^ When to flush on operations.
409+ | TranslogFlushThresholdSize Bytes
410+ -- ^ When to flush based on translog (bytes) size.
411+ | TranslogFlushThresholdPeriod NominalDiffTime
412+ -- ^ When to flush based on a period of not flushing.
413+ | TranslogDisableFlush Bool
414+ -- ^ Disables flushing. Note, should be set for a short interval and then enabled.
415+ | CacheFilterMaxSize (Maybe Bytes)
416+ -- ^ The maximum size of filter cache (per segment in shard).
417+ | CacheFilterExpire (Maybe NominalDiffTime)
418+ -- ^ The expire after access time for filter cache.
419+ | GatewaySnapshotInterval NominalDiffTime
420+ -- ^ The gateway snapshot interval (only applies to shared gateways).
421+ | RoutingAllocationInclude (NonEmpty NodeAttrFilter)
422+ -- ^ A node matching any rule will be allowed to host shards from the index.
423+ | RoutingAllocationExclude (NonEmpty NodeAttrFilter)
424+ -- ^ A node matching any rule will NOT be allowed to host shards from the index.
425+ | RoutingAllocationRequire (NonEmpty NodeAttrFilter)
426+ -- ^ Only nodes matching all rules will be allowed to host shards from the index.
427+ | RoutingAllocationEnable AllocationPolicy
428+ -- ^ Enables shard allocation for a specific index.
429+ | RoutingAllocationShardsPerNode ShardCount
430+ -- ^ Controls the total number of shards (replicas and primaries) allowed to be allocated on a single node.
431+ | RecoveryInitialShards InitialShardCount
432+ -- ^ When using local gateway a particular shard is recovered only if there can be allocated quorum shards in the cluster.
433+ | GCDeletes NominalDiffTime
434+ | TTLDisablePurge Bool
435+ -- ^ Disables temporarily the purge of expired docs.
436+ | TranslogFSType FSType
437+ | IndexCompoundFormat CompoundFormat
438+ | IndexCompoundOnFlush Bool
439+ | WarmerEnabled Bool
440+ deriving (Eq, Show, Generic, Typeable)
441+
442+data AllocationPolicy = AllocAll
443+ -- ^ Allows shard allocation for all shards.
444+ | AllocPrimaries
445+ -- ^ Allows shard allocation only for primary shards.
446+ | AllocNewPrimaries
447+ -- ^ Allows shard allocation only for primary shards for new indices.
448+ | AllocNone
449+ -- ^ No shard allocation is allowed
450+ deriving (Eq, Show, Generic, Typeable)
451+
452+data ReplicaBounds = ReplicasBounded Int Int
453+ | ReplicasLowerBounded Int
454+ | ReplicasUnbounded
455+ deriving (Eq, Show, Generic, Typeable)
456+
457+newtype Bytes = Bytes Int deriving (Eq, Show, Generic, Typeable, Ord, ToJSON, FromJSON)
458+
459+data FSType = FSSimple
460+ | FSBuffered deriving (Eq, Show, Generic, Typeable, Ord)
461+
462+data InitialShardCount = QuorumShards
463+ | QuorumMinus1Shards
464+ | FullShards
465+ | FullMinus1Shards
466+ | ExplicitShards Int
467+ deriving (Eq, Show, Generic, Typeable)
468+
469+data NodeAttrFilter = NodeAttrFilter { nodeAttrFilterName :: NodeAttrName
470+ , nodeAttrFilterValues :: NonEmpty Text}
471+ deriving (Eq, Show, Generic, Ord)
472+
473+newtype NodeAttrName = NodeAttrName Text deriving (Eq, Show, Ord, Generic, Typeable)
474+
475+data CompoundFormat = CompoundFileFormat Bool
476+ | MergeSegmentVsTotalIndex Double
477+ -- ^ percentage between 0 and 1 where 0 is false, 1 is true
478+ deriving (Eq, Show, Generic, Typeable)
479+
480+newtype NominalDiffTimeJSON = NominalDiffTimeJSON { ndtJSON :: NominalDiffTime }
481+
482+data IndexSettingsSummary = IndexSettingsSummary { sSummaryIndexName :: IndexName
483+ , sSummaryFixedSettings :: IndexSettings
484+ , sSummaryUpdateable :: [UpdatableIndexSetting]}
485+ deriving (Eq, Show, Generic, Typeable)
486+
368487{-| 'Reply' and 'Method' are type synonyms from 'Network.HTTP.Types.Method.Method' -}
369488type Reply = Network.HTTP.Client.Response L.ByteString
370489type Method = NHTM.Method
@@ -373,7 +492,7 @@ type Method = NHTM.Method
373492
374493 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
375494-}
376−data OpenCloseIndex = OpenIndex | CloseIndex deriving (Eq, Show)
495+data OpenCloseIndex = OpenIndex | CloseIndex deriving (Eq, Show, Generic, Typeable)
377496
378497data FieldType = GeoPointType
379498 | GeoShapeType
@@ -381,10 +500,10 @@ data FieldType = GeoPointType
381500 | IntegerType
382501 | LongType
383502 | ShortType
384− | ByteType deriving (Eq, Show)
503+ | ByteType deriving (Eq, Show, Generic, Typeable)
385504
386505data FieldDefinition =
387− FieldDefinition { fieldType :: FieldType } deriving (Eq, Show)
506+ FieldDefinition { fieldType :: FieldType } deriving (Eq, Show, Generic, Typeable)
388507
389508{-| An 'IndexTemplate' defines a template that will automatically be
390509 applied to new indices created. The templates include both
@@ -402,7 +521,7 @@ data IndexTemplate =
402521
403522data MappingField =
404523 MappingField { mappingFieldName :: FieldName
405− , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
524+ , fieldDefinition :: FieldDefinition } deriving (Eq, Show, Generic, Typeable)
406525
407526{-| Support for type reification of 'Mapping's is currently incomplete, for
408527 now the mapping API verbiage expects a 'ToJSON'able blob.
@@ -412,7 +531,7 @@ data MappingField =
412531 and keeping different kinds of documents separated if possible.
413532-}
414533data Mapping = Mapping { typeName :: TypeName
415− , mappingFields :: [MappingField] } deriving (Eq, Show)
534+ , mappingFields :: [MappingField] } deriving (Eq, Show, Generic, Typeable)
416535
417536{-| 'BulkOperation' is a sum type for expressing the four kinds of bulk
418537 operation index, create, delete, and update. 'BulkIndex' behaves like an
@@ -424,7 +543,7 @@ data BulkOperation =
424543 BulkIndex IndexName MappingName DocId Value
425544 | BulkCreate IndexName MappingName DocId Value
426545 | BulkDelete IndexName MappingName DocId
427− | BulkUpdate IndexName MappingName DocId Value deriving (Eq, Show)
546+ | BulkUpdate IndexName MappingName DocId Value deriving (Eq, Show, Generic, Typeable)
428547
429548{-| 'EsResult' describes the standard wrapper JSON document that you see in
430549 successful Elasticsearch lookups or lookups that couldn't find the document.
@@ -432,55 +551,65 @@ data BulkOperation =
432551data EsResult a = EsResult { _index :: Text
433552 , _type :: Text
434553 , _id :: Text
435− , foundResult :: Maybe (EsResultFound a)} deriving (Eq, Show)
554+ , foundResult :: Maybe (EsResultFound a)} deriving (Eq, Show, Generic, Typeable)
436555
437556{-| 'EsResultFound' contains the document and its metadata inside of an
438557 'EsResult' when the document was successfully found.
439558-}
440559data EsResultFound a = EsResultFound { _version :: DocVersion
441− , _source :: a } deriving (Eq, Show)
560+ , _source :: a } deriving (Eq, Show, Generic, Typeable)
442561
443562{-| 'EsError' is the generic type that will be returned when there was a
444563 problem. If you can't parse the expected response, its a good idea to
445564 try parsing this.
446565-}
447566data EsError = EsError { errorStatus :: Int
448− , errorMessage :: Text } deriving (Eq, Show)
567+ , errorMessage :: Text } deriving (Eq, Show, Generic, Typeable)
568+
569+{-| 'EsProtocolException' ideally should never be thrown. It will only
570+be thrown when Bloodhound can't parse a response returned by the
571+ElasticSearch server. This should be reported as a bug to the bug
572+tracker. Be sure to include the body.
573+-}
574+data EsProtocolException = EsProtocolException { esProtoExBody :: L.ByteString }
575+ deriving (Eq, Show, Generic, Typeable)
576+
577+instance Exception EsProtocolException
449578
450579data IndexAlias = IndexAlias { srcIndex :: IndexName
451− , indexAlias :: IndexAliasName } deriving (Eq, Show)
580+ , indexAlias :: IndexAliasName } deriving (Eq, Show, Generic, Typeable)
452581
453−newtype IndexAliasName = IndexAliasName { indexAliasName :: IndexName } deriving (Eq, Show, ToJSON)
582+newtype IndexAliasName = IndexAliasName { indexAliasName :: IndexName } deriving (Eq, Show, Generic, ToJSON)
454583
455584data IndexAliasAction = AddAlias IndexAlias IndexAliasCreate
456− | RemoveAlias IndexAlias deriving (Show, Eq, Typeable)
585+ | RemoveAlias IndexAlias deriving (Show, Eq, Generic, Typeable)
457586
458587data IndexAliasCreate = IndexAliasCreate { aliasCreateRouting :: Maybe AliasRouting
459588 , aliasCreateFilter :: Maybe Filter}
460− deriving (Show, Eq, Typeable)
589+ deriving (Show, Eq, Generic, Typeable)
461590
462591data AliasRouting = AllAliasRouting RoutingValue
463592 | GranularAliasRouting (Maybe SearchAliasRouting) (Maybe IndexAliasRouting)
464− deriving (Show, Eq, Typeable)
593+ deriving (Show, Eq, Generic, Typeable)
465594
466−newtype SearchAliasRouting = SearchAliasRouting (NonEmpty RoutingValue) deriving (Show, Eq, Typeable)
595+newtype SearchAliasRouting = SearchAliasRouting (NonEmpty RoutingValue) deriving (Show, Eq, Generic, Typeable)
467596
468−newtype IndexAliasRouting = IndexAliasRouting RoutingValue deriving (Show, Eq, ToJSON, FromJSON, Typeable)
597+newtype IndexAliasRouting = IndexAliasRouting RoutingValue deriving (Show, Eq, Generic, ToJSON, FromJSON, Typeable)
469598
470−newtype RoutingValue = RoutingValue { routingValue :: Text } deriving (Show, Eq, ToJSON, FromJSON, Typeable)
599+newtype RoutingValue = RoutingValue { routingValue :: Text } deriving (Show, Eq, Generic, ToJSON, FromJSON, Typeable)
471600
472−newtype IndexAliasesSummary = IndexAliasesSummary { indexAliasesSummary :: [IndexAliasSummary] } deriving (Show, Eq, Typeable)
601+newtype IndexAliasesSummary = IndexAliasesSummary { indexAliasesSummary :: [IndexAliasSummary] } deriving (Show, Eq, Generic, Typeable)
473602
474603{-| 'IndexAliasSummary' is a summary of an index alias configured for a server. -}
475604data IndexAliasSummary = IndexAliasSummary { indexAliasSummaryAlias :: IndexAlias
476− , indexAliasSummaryCreate :: IndexAliasCreate} deriving (Show, Eq)
605+ , indexAliasSummaryCreate :: IndexAliasCreate} deriving (Show, Eq, Generic, Typeable)
477606
478607{-| 'DocVersion' is an integer version number for a document between 1
479608and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
480609-}
481610newtype DocVersion = DocVersion {
482611 docVersionNumber :: Int
483− } deriving (Eq, Show, Ord, ToJSON)
612+ } deriving (Eq, Show, Generic, Ord, ToJSON)
484613
485614-- | Smart constructor for in-range doc version
486615mkDocVersion :: Int -> Maybe DocVersion
@@ -494,7 +623,7 @@ mkDocVersion i
494623own version numbers instead of ones from ES.
495624-}
496625newtype ExternalDocVersion = ExternalDocVersion DocVersion
497− deriving (Eq, Show, Ord, Bounded, Enum, ToJSON)
626+ deriving (Eq, Show, Generic, Ord, Bounded, Enum, ToJSON)
498627
499628{-| 'VersionControl' is specified when indexing documents as a
500629optimistic concurrency control.
@@ -528,12 +657,12 @@ data VersionControl = NoVersionControl
528657 -- given version will be the new version. This is
529658 -- typically used for correcting errors. Use with
530659 -- care, as this could result in data loss.
531− deriving (Show, Eq, Ord)
660+ deriving (Show, Eq, Generic, Ord)
532661
533662{-| 'DocumentParent' is used to specify a parent document.
534663-}
535664newtype DocumentParent = DocumentParent DocId
536− deriving (Eq, Show)
665+ deriving (Eq, Show, Generic, Typeable)
537666
538667{-| 'IndexDocumentSettings' are special settings supplied when indexing
539668a document. For the best backwards compatiblity when new fields are
@@ -542,7 +671,7 @@ added, you should probably prefer to start with 'defaultIndexDocumentSettings'
542671data IndexDocumentSettings =
543672 IndexDocumentSettings { idsVersionControl :: VersionControl
544673 , idsParent :: Maybe DocumentParent
545− } deriving (Eq, Show)
674+ } deriving (Eq, Show, Generic, Typeable)
546675
547676{-| Reasonable default settings. Chooses no version control and no parent.
548677-}
@@ -562,7 +691,7 @@ type Sort = [SortSpec]
562691<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
563692-}
564693data SortSpec = DefaultSortSpec DefaultSort
565− | GeoDistanceSortSpec SortOrder GeoPoint DistanceUnit deriving (Eq, Show)
694+ | GeoDistanceSortSpec SortOrder GeoPoint DistanceUnit deriving (Eq, Show, Generic, Typeable)
566695
567696{-| 'DefaultSort' is usually the kind of 'SortSpec' you'll want. There's a
568697 'mkSort' convenience function for when you want to specify only the most
@@ -577,7 +706,7 @@ data DefaultSort =
577706 , ignoreUnmapped :: Bool
578707 , sortMode :: Maybe SortMode
579708 , missingSort :: Maybe Missing
580− , nestedFilter :: Maybe Filter } deriving (Eq, Show)
709+ , nestedFilter :: Maybe Filter } deriving (Eq, Show, Generic, Typeable)
581710
582711{-| 'SortOrder' is 'Ascending' or 'Descending', as you might expect. These get
583712 encoded into "asc" or "desc" when turned into JSON.
@@ -585,7 +714,7 @@ data DefaultSort =
585714<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
586715-}
587716data SortOrder = Ascending
588− | Descending deriving (Eq, Show)
717+ | Descending deriving (Eq, Show, Generic, Typeable)
589718
590719{-| 'Missing' prescribes how to handle missing fields. A missing field can be
591720 sorted last, first, or using a custom value as a substitute.
@@ -594,7 +723,7 @@ data SortOrder = Ascending
594723-}
595724data Missing = LastMissing
596725 | FirstMissing
597− | CustomMissing Text deriving (Eq, Show)
726+ | CustomMissing Text deriving (Eq, Show, Generic, Typeable)
598727
599728{-| 'SortMode' prescribes how to handle sorting array/multi-valued fields.
600729
@@ -603,7 +732,7 @@ http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-req
603732data SortMode = SortMin
604733 | SortMax
605734 | SortSum
606− | SortAvg deriving (Eq, Show)
735+ | SortAvg deriving (Eq, Show, Generic, Typeable)
607736
608737{-| 'mkSort' defaults everything but the 'FieldName' and the 'SortOrder' so
609738 that you can concisely describe the usual kind of 'SortSpec's you want.
@@ -625,19 +754,19 @@ type PrefixValue = Text
625754{-| 'BooleanOperator' is the usual And/Or operators with an ES compatible
626755 JSON encoding baked in. Used all over the place.
627756-}
628−data BooleanOperator = And | Or deriving (Eq, Show, Typeable)
757+data BooleanOperator = And | Or deriving (Eq, Show, Generic, Typeable)
629758
630759{-| 'ShardCount' is part of 'IndexSettings'
631760-}
632−newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
761+newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic, ToJSON, Typeable)
633762
634763{-| 'ReplicaCount' is part of 'IndexSettings'
635764-}
636−newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
765+newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic, ToJSON, Typeable)
637766
638767{-| 'Server' is used with the client functions to point at the ES instance
639768-}
640−newtype Server = Server Text deriving (Eq, Show)
769+newtype Server = Server Text deriving (Eq, Show, Generic, Typeable)
641770
642771{-| 'IndexName' is used to describe which index to query/create/delete
643772-}
@@ -669,27 +798,27 @@ newtype QueryString = QueryString Text deriving (Eq, Generic, Show, ToJSON, From
669798{-| 'FieldName' is used all over the place wherever a specific field within
670799 a document needs to be specified, usually in 'Query's or 'Filter's.
671800-}
672−newtype FieldName = FieldName Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
801+newtype FieldName = FieldName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
673802
674803
675804{-| 'Script' is often used in place of 'FieldName' to specify more
676805complex ways of extracting a value from a document.
677806-}
678−newtype Script = Script { scriptText :: Text } deriving (Eq, Show)
807+newtype Script = Script { scriptText :: Text } deriving (Eq, Show, Generic, Typeable)
679808
680809{-| 'CacheName' is used in 'RegexpFilter' for describing the
681810 'CacheKey' keyed caching behavior.
682811-}
683−newtype CacheName = CacheName Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
812+newtype CacheName = CacheName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
684813
685814{-| 'CacheKey' is used in 'RegexpFilter' to key regex caching.
686815-}
687816newtype CacheKey =
688− CacheKey Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
817+ CacheKey Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
689818newtype Existence =
690− Existence Bool deriving (Eq, Show, ToJSON, FromJSON, Typeable)
819+ Existence Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
691820newtype NullValue =
692− NullValue Bool deriving (Eq, Show, ToJSON, FromJSON, Typeable)
821+ NullValue Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
693822newtype CutoffFrequency =
694823 CutoffFrequency Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
695824newtype Analyzer =
@@ -773,14 +902,17 @@ newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show, Generic, ToJSO
773902newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
774903newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
775904
905+-- | Newtype wrapper to parse ES's concerning tendency to in some APIs return a floating point number of milliseconds since epoch ಠ_ಠ
906+newtype POSIXMS = POSIXMS { posixMS :: UTCTime }
907+
776908{-| 'unpackId' is a silly convenience function that gets used once.
777909-}
778910unpackId :: DocId -> Text
779911unpackId (DocId docId) = docId
780912
781913type TrackSortScores = Bool
782−newtype From = From Int deriving (Eq, Show, ToJSON)
783−newtype Size = Size Int deriving (Eq, Show, ToJSON)
914+newtype From = From Int deriving (Eq, Show, Generic, ToJSON)
915+newtype Size = Size Int deriving (Eq, Show, Generic, ToJSON)
784916
785917data Search = Search { queryBody :: Maybe Query
786918 , filterBody :: Maybe Filter
@@ -793,7 +925,7 @@ data Search = Search { queryBody :: Maybe Query
793925 , size :: Size
794926 , searchType :: SearchType
795927 , fields :: Maybe [FieldName]
796− , source :: Maybe Source } deriving (Eq, Show)
928+ , source :: Maybe Source } deriving (Eq, Show, Generic, Typeable)
797929
798930data SearchType = SearchTypeQueryThenFetch
799931 | SearchTypeDfsQueryThenFetch
@@ -801,40 +933,40 @@ data SearchType = SearchTypeQueryThenFetch
801933 | SearchTypeScan
802934 | SearchTypeQueryAndFetch
803935 | SearchTypeDfsQueryAndFetch
804− deriving (Eq, Show)
936+ deriving (Eq, Show, Generic, Typeable)
805937
806938data Source =
807939 NoSource
808940 | SourcePatterns PatternOrPatterns
809941 | SourceIncludeExclude Include Exclude
810− deriving (Show, Eq)
942+ deriving (Show, Eq, Generic, Typeable)
811943
812944data PatternOrPatterns = PopPattern Pattern
813− | PopPatterns [Pattern] deriving (Eq, Show)
945+ | PopPatterns [Pattern] deriving (Eq, Show, Generic, Typeable)
814946
815−data Include = Include [Pattern] deriving (Eq, Show)
816−data Exclude = Exclude [Pattern] deriving (Eq, Show)
947+data Include = Include [Pattern] deriving (Eq, Show, Generic, Typeable)
948+data Exclude = Exclude [Pattern] deriving (Eq, Show, Generic, Typeable)
817949
818−newtype Pattern = Pattern Text deriving (Eq, Show)
950+newtype Pattern = Pattern Text deriving (Eq, Show, Generic, Typeable)
819951
820952data Highlights = Highlights { globalsettings :: Maybe HighlightSettings
821953 , highlightFields :: [FieldHighlight]
822− } deriving (Show, Eq)
954+ } deriving (Show, Eq, Generic, Typeable)
823955
824956data FieldHighlight = FieldHighlight FieldName (Maybe HighlightSettings)
825− deriving (Show, Eq)
957+ deriving (Show, Eq, Generic, Typeable)
826958
827959
828960data HighlightSettings = Plain PlainHighlight
829961 | Postings PostingsHighlight
830962 | FastVector FastVectorHighlight
831− deriving (Show, Eq)
963+ deriving (Show, Eq, Generic, Typeable)
832964data PlainHighlight =
833965 PlainHighlight { plainCommon :: Maybe CommonHighlight
834− , plainNonPost :: Maybe NonPostings } deriving (Show, Eq)
966+ , plainNonPost :: Maybe NonPostings } deriving (Show, Eq, Generic, Typeable)
835967
836968 -- This requires that index_options are set to 'offset' in the mapping.
837−data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Show, Eq)
969+data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Show, Eq, Generic, Typeable)
838970
839971-- This requires that term_vector is set to 'with_positions_offsets' in the mapping.
840972data FastVectorHighlight =
@@ -845,7 +977,7 @@ data FastVectorHighlight =
845977 , fragmentOffset :: Maybe Int
846978 , matchedFields :: [Text]
847979 , phraseLimit :: Maybe Int
848− } deriving (Show, Eq)
980+ } deriving (Show, Eq, Generic, Typeable)
849981
850982data CommonHighlight =
851983 CommonHighlight { order :: Maybe Text
@@ -855,21 +987,21 @@ data CommonHighlight =
855987 , noMatchSize :: Maybe Int
856988 , highlightQuery :: Maybe Query
857989 , requireFieldMatch :: Maybe Bool
858− } deriving (Show, Eq)
990+ } deriving (Show, Eq, Generic, Typeable)
859991
860992-- Settings that are only applicable to FastVector and Plain highlighters.
861993data NonPostings =
862994 NonPostings { fragmentSize :: Maybe Int
863− , numberOfFragments :: Maybe Int} deriving (Show, Eq)
995+ , numberOfFragments :: Maybe Int} deriving (Show, Eq, Generic, Typeable)
864996
865997data HighlightEncoder = DefaultEncoder
866998 | HTMLEncoder
867− deriving (Show, Eq)
999+ deriving (Show, Eq, Generic, Typeable)
8681000
8691001-- NOTE: Should the tags use some kind of HTML type, rather than Text?
8701002data HighlightTag = TagSchema Text
8711003 | CustomTags ([Text], [Text]) -- Only uses more than the first value in the lists if fvh
872− deriving (Show, Eq)
1004+ deriving (Show, Eq, Generic, Typeable)
8731005
8741006
8751007data Query =
@@ -900,19 +1032,19 @@ data Query =
9001032 | QuerySimpleQueryStringQuery SimpleQueryStringQuery
9011033 | QueryRangeQuery RangeQuery
9021034 | QueryRegexpQuery RegexpQuery
903− deriving (Eq, Show, Typeable)
1035+ deriving (Eq, Show, Generic, Typeable)
9041036
9051037data RegexpQuery =
9061038 RegexpQuery { regexpQueryField :: FieldName
9071039 , regexpQuery :: Regexp
9081040 , regexpQueryFlags :: RegexpFlags
9091041 , regexpQueryBoost :: Maybe Boost
910− } deriving (Eq, Show, Typeable)
1042+ } deriving (Eq, Show, Generic, Typeable)
9111043
9121044data RangeQuery =
9131045 RangeQuery { rangeQueryField :: FieldName
9141046 , rangeQueryRange :: RangeValue
915− , rangeQueryBoost :: Boost } deriving (Eq, Show, Typeable)
1047+ , rangeQueryBoost :: Boost } deriving (Eq, Show, Generic, Typeable)
9161048
9171049mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
9181050mkRangeQuery f r = RangeQuery f r (Boost 1.0)
@@ -926,7 +1058,7 @@ data SimpleQueryStringQuery =
9261058 , simpleQueryStringFlags :: Maybe (NonEmpty SimpleQueryFlag)
9271059 , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
9281060 , simpleQueryStringLocale :: Maybe Locale
929− } deriving (Eq, Show, Typeable)
1061+ } deriving (Eq, Show, Generic, Typeable)
9301062
9311063data SimpleQueryFlag =
9321064 SimpleQueryAll
@@ -940,7 +1072,7 @@ data SimpleQueryFlag =
9401072 | SimpleQueryWhitespace
9411073 | SimpleQueryFuzzy
9421074 | SimpleQueryNear
943− | SimpleQuerySlop deriving (Eq, Show, Typeable)
1075+ | SimpleQuerySlop deriving (Eq, Show, Generic, Typeable)
9441076
9451077-- use_dis_max and tie_breaker when fields are plural?
9461078data QueryStringQuery =
@@ -962,7 +1094,7 @@ data QueryStringQuery =
9621094 , queryStringMinimumShouldMatch :: Maybe MinimumMatch
9631095 , queryStringLenient :: Maybe Lenient
9641096 , queryStringLocale :: Maybe Locale
965− } deriving (Eq, Show, Typeable)
1097+ } deriving (Eq, Show, Generic, Typeable)
9661098
9671099mkQueryStringQuery :: QueryString -> QueryStringQuery
9681100mkQueryStringQuery qs =
@@ -973,19 +1105,19 @@ mkQueryStringQuery qs =
9731105 Nothing Nothing
9741106
9751107data FieldOrFields = FofField FieldName
976− | FofFields (NonEmpty FieldName) deriving (Eq, Show, Typeable)
1108+ | FofFields (NonEmpty FieldName) deriving (Eq, Show, Generic, Typeable)
9771109
9781110data PrefixQuery =
9791111 PrefixQuery
9801112 { prefixQueryField :: FieldName
9811113 , prefixQueryPrefixValue :: Text
982− , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show, Typeable)
1114+ , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show, Generic, Typeable)
9831115
9841116data NestedQuery =
9851117 NestedQuery
9861118 { nestedQueryPath :: QueryPath
9871119 , nestedQueryScoreType :: ScoreType
988− , nestedQuery :: Query } deriving (Eq, Show, Typeable)
1120+ , nestedQuery :: Query } deriving (Eq, Show, Generic, Typeable)
9891121
9901122data MoreLikeThisFieldQuery =
9911123 MoreLikeThisFieldQuery
@@ -1003,7 +1135,7 @@ data MoreLikeThisFieldQuery =
10031135 , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
10041136 , moreLikeThisFieldBoost :: Maybe Boost
10051137 , moreLikeThisFieldAnalyzer :: Maybe Analyzer
1006− } deriving (Eq, Show, Typeable)
1138+ } deriving (Eq, Show, Generic, Typeable)
10071139
10081140data MoreLikeThisQuery =
10091141 MoreLikeThisQuery
@@ -1021,32 +1153,32 @@ data MoreLikeThisQuery =
10211153 , moreLikeThisBoostTerms :: Maybe BoostTerms
10221154 , moreLikeThisBoost :: Maybe Boost
10231155 , moreLikeThisAnalyzer :: Maybe Analyzer
1024− } deriving (Eq, Show, Typeable)
1156+ } deriving (Eq, Show, Generic, Typeable)
10251157
10261158data IndicesQuery =
10271159 IndicesQuery
10281160 { indicesQueryIndices :: [IndexName]
10291161 , indicesQuery :: Query
10301162 -- default "all"
1031− , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show, Typeable)
1163+ , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show, Generic, Typeable)
10321164
10331165data HasParentQuery =
10341166 HasParentQuery
10351167 { hasParentQueryType :: TypeName
10361168 , hasParentQuery :: Query
1037− , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Typeable)
1169+ , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Generic, Typeable)
10381170
10391171data HasChildQuery =
10401172 HasChildQuery
10411173 { hasChildQueryType :: TypeName
10421174 , hasChildQuery :: Query
1043− , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Typeable)
1175+ , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Generic, Typeable)
10441176
10451177data ScoreType =
10461178 ScoreTypeMax
10471179 | ScoreTypeSum
10481180 | ScoreTypeAvg
1049− | ScoreTypeNone deriving (Eq, Show, Typeable)
1181+ | ScoreTypeNone deriving (Eq, Show, Generic, Typeable)
10501182
10511183data FuzzyQuery =
10521184 FuzzyQuery { fuzzyQueryField :: FieldName
@@ -1055,7 +1187,7 @@ data FuzzyQuery =
10551187 , fuzzyQueryMaxExpansions :: MaxExpansions
10561188 , fuzzyQueryFuzziness :: Fuzziness
10571189 , fuzzyQueryBoost :: Maybe Boost
1058− } deriving (Eq, Show, Typeable)
1190+ } deriving (Eq, Show, Generic, Typeable)
10591191
10601192data FuzzyLikeFieldQuery =
10611193 FuzzyLikeFieldQuery
@@ -1068,7 +1200,7 @@ data FuzzyLikeFieldQuery =
10681200 , fuzzyLikeFieldPrefixLength :: PrefixLength
10691201 , fuzzyLikeFieldBoost :: Boost
10701202 , fuzzyLikeFieldAnalyzer :: Maybe Analyzer
1071− } deriving (Eq, Show, Typeable)
1203+ } deriving (Eq, Show, Generic, Typeable)
10721204
10731205data FuzzyLikeThisQuery =
10741206 FuzzyLikeThisQuery
@@ -1080,19 +1212,19 @@ data FuzzyLikeThisQuery =
10801212 , fuzzyLikePrefixLength :: PrefixLength
10811213 , fuzzyLikeBoost :: Boost
10821214 , fuzzyLikeAnalyzer :: Maybe Analyzer
1083− } deriving (Eq, Show, Typeable)
1215+ } deriving (Eq, Show, Generic, Typeable)
10841216
10851217data FilteredQuery =
10861218 FilteredQuery
10871219 { filteredQuery :: Query
1088− , filteredFilter :: Filter } deriving (Eq, Show, Typeable)
1220+ , filteredFilter :: Filter } deriving (Eq, Show, Generic, Typeable)
10891221
10901222data DisMaxQuery =
10911223 DisMaxQuery { disMaxQueries :: [Query]
10921224 -- default 0.0
10931225 , disMaxTiebreaker :: Tiebreaker
10941226 , disMaxBoost :: Maybe Boost
1095− } deriving (Eq, Show, Typeable)
1227+ } deriving (Eq, Show, Generic, Typeable)
10961228
10971229data MatchQuery =
10981230 MatchQuery { matchQueryField :: FieldName
@@ -1104,7 +1236,7 @@ data MatchQuery =
11041236 , matchQueryAnalyzer :: Maybe Analyzer
11051237 , matchQueryMaxExpansions :: Maybe MaxExpansions
11061238 , matchQueryLenient :: Maybe Lenient
1107− , matchQueryBoost :: Maybe Boost } deriving (Eq, Show, Typeable)
1239+ , matchQueryBoost :: Maybe Boost } deriving (Eq, Show, Generic, Typeable)
11081240
11091241{-| 'mkMatchQuery' is a convenience function that defaults the less common parameters,
11101242 enabling you to provide only the 'FieldName' and 'QueryString' to make a 'MatchQuery'
@@ -1114,7 +1246,7 @@ mkMatchQuery field query = MatchQuery field query Or ZeroTermsNone Nothing Nothi
11141246
11151247data MatchQueryType =
11161248 MatchPhrase
1117− | MatchPhrasePrefix deriving (Eq, Show, Typeable)
1249+ | MatchPhrasePrefix deriving (Eq, Show, Generic, Typeable)
11181250
11191251data MultiMatchQuery =
11201252 MultiMatchQuery { multiMatchQueryFields :: [FieldName]
@@ -1126,7 +1258,7 @@ data MultiMatchQuery =
11261258 , multiMatchQueryCutoffFrequency :: Maybe CutoffFrequency
11271259 , multiMatchQueryAnalyzer :: Maybe Analyzer
11281260 , multiMatchQueryMaxExpansions :: Maybe MaxExpansions
1129− , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show, Typeable)
1261+ , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show, Generic, Typeable)
11301262
11311263{-| 'mkMultiMatchQuery' is a convenience function that defaults the less common parameters,
11321264 enabling you to provide only the list of 'FieldName's and 'QueryString' to
@@ -1143,7 +1275,7 @@ data MultiMatchQueryType =
11431275 | MultiMatchMostFields
11441276 | MultiMatchCrossFields
11451277 | MultiMatchPhrase
1146− | MultiMatchPhrasePrefix deriving (Eq, Show, Typeable)
1278+ | MultiMatchPhrasePrefix deriving (Eq, Show, Generic, Typeable)
11471279
11481280data BoolQuery =
11491281 BoolQuery { boolQueryMustMatch :: [Query]
@@ -1152,7 +1284,7 @@ data BoolQuery =
11521284 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
11531285 , boolQueryBoost :: Maybe Boost
11541286 , boolQueryDisableCoord :: Maybe DisableCoord
1155− } deriving (Eq, Show, Typeable)
1287+ } deriving (Eq, Show, Generic, Typeable)
11561288
11571289mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
11581290mkBoolQuery must mustNot should =
@@ -1161,7 +1293,7 @@ mkBoolQuery must mustNot should =
11611293data BoostingQuery =
11621294 BoostingQuery { positiveQuery :: Query
11631295 , negativeQuery :: Query
1164− , negativeBoost :: Boost } deriving (Eq, Show, Typeable)
1296+ , negativeBoost :: Boost } deriving (Eq, Show, Generic, Typeable)
11651297
11661298data CommonTermsQuery =
11671299 CommonTermsQuery { commonField :: FieldName
@@ -1173,16 +1305,16 @@ data CommonTermsQuery =
11731305 , commonBoost :: Maybe Boost
11741306 , commonAnalyzer :: Maybe Analyzer
11751307 , commonDisableCoord :: Maybe DisableCoord
1176− } deriving (Eq, Show, Typeable)
1308+ } deriving (Eq, Show, Generic, Typeable)
11771309
11781310data CommonMinimumMatch =
11791311 CommonMinimumMatchHighLow MinimumMatchHighLow
11801312 | CommonMinimumMatch MinimumMatch
1181− deriving (Eq, Show, Typeable)
1313+ deriving (Eq, Show, Generic, Typeable)
11821314
11831315data MinimumMatchHighLow =
11841316 MinimumMatchHighLow { lowFreq :: MinimumMatch
1185− , highFreq :: MinimumMatch } deriving (Eq, Show, Typeable)
1317+ , highFreq :: MinimumMatch } deriving (Eq, Show, Generic, Typeable)
11861318
11871319data Filter = AndFilter [Filter] Cache
11881320 | OrFilter [Filter] Cache
@@ -1202,36 +1334,36 @@ data Filter = AndFilter [Filter] Cache
12021334 | RangeFilter FieldName RangeValue RangeExecution Cache
12031335 | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
12041336 | TermFilter Term Cache
1205− deriving (Eq, Show, Typeable)
1337+ deriving (Eq, Show, Generic, Typeable)
12061338
12071339data ZeroTermsQuery = ZeroTermsNone
1208− | ZeroTermsAll deriving (Eq, Show, Typeable)
1340+ | ZeroTermsAll deriving (Eq, Show, Generic, Typeable)
12091341
12101342data RangeExecution = RangeExecutionIndex
1211− | RangeExecutionFielddata deriving (Eq, Show, Typeable)
1343+ | RangeExecutionFielddata deriving (Eq, Show, Generic, Typeable)
12121344
1213−newtype Regexp = Regexp Text deriving (Eq, Show, FromJSON)
1345+newtype Regexp = Regexp Text deriving (Eq, Show, Generic, Typeable, FromJSON)
12141346
12151347data RegexpFlags = AllRegexpFlags
12161348 | NoRegexpFlags
1217− | SomeRegexpFlags (NonEmpty RegexpFlag) deriving (Eq, Show)
1349+ | SomeRegexpFlags (NonEmpty RegexpFlag) deriving (Eq, Show, Generic, Typeable)
12181350
12191351data RegexpFlag = AnyString
12201352 | Automaton
12211353 | Complement
12221354 | Empty
12231355 | Intersection
1224− | Interval deriving (Eq, Show)
1356+ | Interval deriving (Eq, Show, Generic, Typeable)
12251357
1226−newtype LessThan = LessThan Double deriving (Eq, Show)
1227−newtype LessThanEq = LessThanEq Double deriving (Eq, Show)
1228−newtype GreaterThan = GreaterThan Double deriving (Eq, Show)
1229−newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show)
1358+newtype LessThan = LessThan Double deriving (Eq, Show, Generic, Typeable)
1359+newtype LessThanEq = LessThanEq Double deriving (Eq, Show, Generic, Typeable)
1360+newtype GreaterThan = GreaterThan Double deriving (Eq, Show, Generic, Typeable)
1361+newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show, Generic, Typeable)
12301362
1231−newtype LessThanD = LessThanD UTCTime deriving (Eq, Show)
1232−newtype LessThanEqD = LessThanEqD UTCTime deriving (Eq, Show)
1233−newtype GreaterThanD = GreaterThanD UTCTime deriving (Eq, Show)
1234−newtype GreaterThanEqD = GreaterThanEqD UTCTime deriving (Eq, Show)
1363+newtype LessThanD = LessThanD UTCTime deriving (Eq, Show, Generic, Typeable)
1364+newtype LessThanEqD = LessThanEqD UTCTime deriving (Eq, Show, Generic, Typeable)
1365+newtype GreaterThanD = GreaterThanD UTCTime deriving (Eq, Show, Generic, Typeable)
1366+newtype GreaterThanEqD = GreaterThanEqD UTCTime deriving (Eq, Show, Generic, Typeable)
12351367
12361368data RangeValue = RangeDateLte LessThanEqD
12371369 | RangeDateLt LessThanD
@@ -1249,7 +1381,7 @@ data RangeValue = RangeDateLte LessThanEqD
12491381 | RangeDoubleGteLte GreaterThanEq LessThanEq
12501382 | RangeDoubleGteLt GreaterThanEq LessThan
12511383 | RangeDoubleGtLte GreaterThan LessThanEq
1252− deriving (Eq, Show)
1384+ deriving (Eq, Show, Generic, Typeable)
12531385
12541386rangeValueToPair :: RangeValue -> [Pair]
12551387rangeValueToPair rv = case rv of
@@ -1271,33 +1403,33 @@ rangeValueToPair rv = case rv of
12711403 RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
12721404
12731405data Term = Term { termField :: Text
1274− , termValue :: Text } deriving (Eq, Show, Typeable)
1406+ , termValue :: Text } deriving (Eq, Show, Generic, Typeable)
12751407
12761408data BoolMatch = MustMatch Term Cache
12771409 | MustNotMatch Term Cache
1278− | ShouldMatch [Term] Cache deriving (Eq, Show, Typeable)
1410+ | ShouldMatch [Term] Cache deriving (Eq, Show, Generic, Typeable)
12791411
12801412-- "memory" or "indexed"
12811413data GeoFilterType = GeoFilterMemory
1282− | GeoFilterIndexed deriving (Eq, Show, Typeable)
1414+ | GeoFilterIndexed deriving (Eq, Show, Generic, Typeable)
12831415
12841416data LatLon = LatLon { lat :: Double
1285− , lon :: Double } deriving (Eq, Show, Typeable)
1417+ , lon :: Double } deriving (Eq, Show, Generic, Typeable)
12861418
12871419data GeoBoundingBox =
12881420 GeoBoundingBox { topLeft :: LatLon
1289− , bottomRight :: LatLon } deriving (Eq, Show, Typeable)
1421+ , bottomRight :: LatLon } deriving (Eq, Show, Generic, Typeable)
12901422
12911423data GeoBoundingBoxConstraint =
12921424 GeoBoundingBoxConstraint { geoBBField :: FieldName
12931425 , constraintBox :: GeoBoundingBox
12941426 , bbConstraintcache :: Cache
12951427 , geoType :: GeoFilterType
1296− } deriving (Eq, Show, Typeable)
1428+ } deriving (Eq, Show, Generic, Typeable)
12971429
12981430data GeoPoint =
12991431 GeoPoint { geoField :: FieldName
1300− , latLon :: LatLon} deriving (Eq, Show, Typeable)
1432+ , latLon :: LatLon} deriving (Eq, Show, Generic, Typeable)
13011433
13021434data DistanceUnit = Miles
13031435 | Yards
@@ -1307,22 +1439,22 @@ data DistanceUnit = Miles
13071439 | Meters
13081440 | Centimeters
13091441 | Millimeters
1310− | NauticalMiles deriving (Eq, Show, Typeable)
1442+ | NauticalMiles deriving (Eq, Show, Generic, Typeable)
13111443
13121444data DistanceType = Arc
13131445 | SloppyArc -- doesn't exist <1.0
1314− | Plane deriving (Eq, Show, Typeable)
1446+ | Plane deriving (Eq, Show, Generic, Typeable)
13151447
13161448data OptimizeBbox = OptimizeGeoFilterType GeoFilterType
1317− | NoOptimizeBbox deriving (Eq, Show, Typeable)
1449+ | NoOptimizeBbox deriving (Eq, Show, Generic, Typeable)
13181450
13191451data Distance =
13201452 Distance { coefficient :: Double
1321− , unit :: DistanceUnit } deriving (Eq, Show, Typeable)
1453+ , unit :: DistanceUnit } deriving (Eq, Show, Generic, Typeable)
13221454
13231455data DistanceRange =
13241456 DistanceRange { distanceFrom :: Distance
1325− , distanceTo :: Distance } deriving (Eq, Show)
1457+ , distanceTo :: Distance } deriving (Eq, Show, Generic, Typeable)
13261458
13271459data SearchResult a =
13281460 SearchResult { took :: Int
@@ -1330,16 +1462,16 @@ data SearchResult a =
13301462 , shards :: ShardResult
13311463 , searchHits :: SearchHits a
13321464 , aggregations :: Maybe AggregationResults
1333− , scrollId :: Maybe ScrollId } deriving (Eq, Show)
1465+ , scrollId :: Maybe ScrollId } deriving (Eq, Show, Generic, Typeable)
13341466
1335−type ScrollId = Text -- Fixme: Newtype
1467+newtype ScrollId = ScrollId Text deriving (Eq, Show, Generic, Ord, ToJSON, FromJSON)
13361468
13371469type Score = Maybe Double
13381470
13391471data SearchHits a =
13401472 SearchHits { hitsTotal :: Int
13411473 , maxScore :: Score
1342− , hits :: [Hit a] } deriving (Eq, Show)
1474+ , hits :: [Hit a] } deriving (Eq, Show, Generic, Typeable)
13431475
13441476
13451477instance Monoid (SearchHits a) where
@@ -1354,18 +1486,26 @@ data Hit a =
13541486 , hitDocId :: DocId
13551487 , hitScore :: Score
13561488 , hitSource :: Maybe a
1357− , hitHighlight :: Maybe HitHighlight } deriving (Eq, Show)
1489+ , hitHighlight :: Maybe HitHighlight } deriving (Eq, Show, Generic, Typeable)
13581490
13591491data ShardResult =
13601492 ShardResult { shardTotal :: Int
13611493 , shardsSuccessful :: Int
1362− , shardsFailed :: Int } deriving (Eq, Show, Generic)
1494+ , shardsFailed :: Int } deriving (Eq, Show, Generic, Typeable)
13631495
13641496type HitHighlight = M.Map Text [Text]
13651497
13661498showText :: Show a => a -> Text
13671499showText = T.pack . show
13681500
1501+readMay :: Read a => String -> Maybe a
1502+readMay s = case reads s of
1503+ (a, ""):_ -> Just a
1504+ _ -> Nothing
1505+
1506+parseReadText :: Read a => Text -> Parser a
1507+parseReadText = maybe mzero return . readMay . T.unpack
1508+
13691509type Aggregations = M.Map Text Aggregation
13701510
13711511emptyAggregations :: Aggregations
@@ -1375,19 +1515,19 @@ mkAggregations :: Text -> Aggregation -> Aggregations
13751515mkAggregations name aggregation = M.insert name aggregation emptyAggregations
13761516
13771517data TermOrder = TermOrder{ termSortField :: Text
1378− , termSortOrder :: SortOrder } deriving (Eq, Show)
1518+ , termSortOrder :: SortOrder } deriving (Eq, Show, Generic, Typeable)
13791519
13801520data TermInclusion = TermInclusion Text
1381− | TermPattern Text Text deriving (Eq, Show)
1521+ | TermPattern Text Text deriving (Eq, Show, Generic, Typeable)
13821522
13831523data CollectionMode = BreadthFirst
1384− | DepthFirst deriving (Eq, Show)
1524+ | DepthFirst deriving (Eq, Show, Generic, Typeable)
13851525
13861526data ExecutionHint = Ordinals
13871527 | GlobalOrdinals
13881528 | GlobalOrdinalsHash
13891529 | GlobalOrdinalsLowCardinality
1390− | Map deriving (Eq, Show)
1530+ | Map deriving (Eq, Show, Generic, Typeable)
13911531
13921532data TimeInterval = Weeks
13931533 | Days
@@ -1403,12 +1543,13 @@ data Interval = Year
14031543 | Hour
14041544 | Minute
14051545 | Second
1406− | FractionalInterval Float TimeInterval deriving (Eq, Show)
1546+ | FractionalInterval Float TimeInterval deriving (Eq, Show, Generic, Typeable)
14071547
14081548data Aggregation = TermsAgg TermsAggregation
14091549 | DateHistogramAgg DateHistogramAggregation
14101550 | ValueCountAgg ValueCountAggregation
1411− | FilterAgg FilterAggregation deriving (Eq, Show)
1551+ | FilterAgg FilterAggregation
1552+ | DateRangeAgg DateRangeAggregation deriving (Eq, Show, Generic, Typeable)
14121553
14131554
14141555data TermsAggregation = TermsAggregation { term :: Either Text Text
@@ -1421,7 +1562,7 @@ data TermsAggregation = TermsAggregation { term :: Either Text Text
14211562 , termCollectMode :: Maybe CollectionMode
14221563 , termExecutionHint :: Maybe ExecutionHint
14231564 , termAggs :: Maybe Aggregations
1424− } deriving (Eq, Show)
1565+ } deriving (Eq, Show, Generic, Typeable)
14251566
14261567data DateHistogramAggregation = DateHistogramAggregation { dateField :: FieldName
14271568 , dateInterval :: Interval
@@ -1432,15 +1573,45 @@ data DateHistogramAggregation = DateHistogramAggregation { dateField :: Fie
14321573 , datePreOffset :: Maybe Text
14331574 , datePostOffset :: Maybe Text
14341575 , dateAggs :: Maybe Aggregations
1435− } deriving (Eq, Show)
1576+ } deriving (Eq, Show, Generic, Typeable)
1577+
1578+
1579+data DateRangeAggregation = DateRangeAggregation { draField :: FieldName
1580+ , draFormat :: Maybe Text
1581+ , draRanges :: NonEmpty DateRangeAggRange
1582+ } deriving (Eq, Show, Generic, Typeable)
1583+
1584+data DateRangeAggRange = DateRangeFrom DateMathExpr
1585+ | DateRangeTo DateMathExpr
1586+ | DateRangeFromAndTo DateMathExpr DateMathExpr deriving (Eq, Show, Generic, Typeable)
1587+
1588+-- | See <https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math> for more information.
1589+data DateMathExpr = DateMathExpr DateMathAnchor [DateMathModifier] deriving (Eq, Show, Generic, Typeable)
1590+
1591+
1592+-- | Starting point for a date range. This along with the 'DateMathModifiers' gets you the date ES will start from.
1593+data DateMathAnchor = DMNow
1594+ | DMDate Day deriving (Eq, Show, Generic, Typeable)
1595+
1596+data DateMathModifier = AddTime Int DateMathUnit
1597+ | SubtractTime Int DateMathUnit
1598+ | RoundDownTo DateMathUnit deriving (Eq, Show, Generic, Typeable)
1599+
1600+data DateMathUnit = DMYear
1601+ | DMMonth
1602+ | DMWeek
1603+ | DMDay
1604+ | DMHour
1605+ | DMMinute
1606+ | DMSecond deriving (Eq, Show, Generic, Typeable)
14361607
14371608-- | See <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html> for more information.
14381609data ValueCountAggregation = FieldValueCount FieldName
1439− | ScriptValueCount Script deriving (Eq, Show)
1610+ | ScriptValueCount Script deriving (Eq, Show, Generic, Typeable)
14401611
14411612-- | Single-bucket filter aggregations. See <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filter-aggregation.html#search-aggregations-bucket-filter-aggregation> for more information.
14421613data FilterAggregation = FilterAggregation { faFilter :: Filter
1443− , faAggs :: Maybe Aggregations} deriving (Eq, Show)
1614+ , faAggs :: Maybe Aggregations} deriving (Eq, Show, Generic, Typeable)
14441615
14451616mkTermsAggregation :: Text -> TermsAggregation
14461617mkTermsAggregation t = TermsAggregation (Left t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
@@ -1537,6 +1708,39 @@ instance ToJSON Aggregation where
15371708 toJSON (FilterAgg (FilterAggregation filt ags)) =
15381709 omitNulls [ "filter" .= filt
15391710 , "aggs" .= ags]
1711+ toJSON (DateRangeAgg a) = object [ "date_range" .= a
1712+ ]
1713+
1714+instance ToJSON DateRangeAggregation where
1715+ toJSON DateRangeAggregation {..} =
1716+ omitNulls [ "field" .= draField
1717+ , "format" .= draFormat
1718+ , "ranges" .= toList draRanges
1719+ ]
1720+
1721+instance ToJSON DateRangeAggRange where
1722+ toJSON (DateRangeFrom e) = object [ "from" .= e ]
1723+ toJSON (DateRangeTo e) = object [ "to" .= e ]
1724+ toJSON (DateRangeFromAndTo f t) = object [ "from" .= f, "to" .= t ]
1725+
1726+instance ToJSON DateMathExpr where
1727+ toJSON (DateMathExpr a mods) = String (fmtA a <> mconcat (fmtMod <$> mods))
1728+ where fmtA DMNow = "now"
1729+ fmtA (DMDate date) = case toGregorian date of
1730+ (y,m,d) -> showText y <> "-" <>
1731+ showText m <> "-" <>
1732+ showText d <> "||"
1733+ fmtMod (AddTime n u) = "+" <> showText n <> fmtU u
1734+ fmtMod (SubtractTime n u) = "-" <> showText n <> fmtU u
1735+ fmtMod (RoundDownTo u) = "/" <> fmtU u
1736+ fmtU DMYear = "y"
1737+ fmtU DMMonth = "M"
1738+ fmtU DMWeek = "w"
1739+ fmtU DMDay = "d"
1740+ fmtU DMHour = "h"
1741+ fmtU DMMinute = "m"
1742+ fmtU DMSecond = "s"
1743+
15401744
15411745type AggregationResults = M.Map Text Value
15421746
@@ -1557,6 +1761,14 @@ data DateHistogramResult = DateHistogramResult { dateKey :: Int
15571761 , dateDocCount :: Int
15581762 , dateHistogramAggs :: Maybe AggregationResults } deriving (Show)
15591763
1764+data DateRangeResult = DateRangeResult { dateRangeKey :: Text
1765+ , dateRangeFrom :: Maybe UTCTime
1766+ , dateRangeFromAsString :: Maybe Text
1767+ , dateRangeTo :: Maybe UTCTime
1768+ , dateRangeToAsString :: Maybe Text
1769+ , dateRangeDocCount :: Int
1770+ , dateRangeAggs :: Maybe AggregationResults } deriving (Show, Eq, Generic, Typeable)
1771+
15601772toTerms :: Text -> AggregationResults -> Maybe (Bucket TermsResult)
15611773toTerms t a = M.lookup t a >>= deserialize
15621774 where deserialize = parseMaybe parseJSON
@@ -1575,6 +1787,11 @@ instance BucketAggregation DateHistogramResult where
15751787 docCount = dateDocCount
15761788 aggs = dateHistogramAggs
15771789
1790+instance BucketAggregation DateRangeResult where
1791+ key = dateRangeKey
1792+ docCount = dateRangeDocCount
1793+ aggs = dateRangeAggs
1794+
15781795instance (FromJSON a, BucketAggregation a) => FromJSON (Bucket a) where
15791796 parseJSON (Object v) = Bucket <$>
15801797 v .: "buckets"
@@ -1595,6 +1812,22 @@ instance FromJSON DateHistogramResult where
15951812 v .:? "aggregations"
15961813 parseJSON _ = mempty
15971814
1815+instance FromJSON DateRangeResult where
1816+ parseJSON = withObject "DateRangeResult" parse
1817+ where parse v = DateRangeResult <$>
1818+ v .: "key" <*>
1819+ (fmap posixMS <$> v .:? "from") <*>
1820+ v .:? "from_as_string" <*>
1821+ (fmap posixMS <$> v .:? "to") <*>
1822+ v .:? "to_as_string" <*>
1823+ v .: "doc_count" <*>
1824+ v .:? "aggregations"
1825+
1826+instance FromJSON POSIXMS where
1827+ parseJSON = withScientific "POSIXMS" (return . parse)
1828+ where parse n = let n' = truncate n :: Integer
1829+ in POSIXMS (posixSecondsToUTCTime (fromInteger (n' `div` 1000)))
1830+
15981831instance Monoid Filter where
15991832 mempty = IdentityFilter
16001833 mappend a b = AndFilter [a, b] defaultCache
@@ -1890,7 +2123,7 @@ instance FromJSON Query where
18902123 <|> idsQuery `taggedWith` "ids"
18912124 <|> queryQueryStringQuery `taggedWith` "query_string"
18922125 <|> queryMatchQuery `taggedWith` "match"
1893− <|> queryMultiMatchQuery --TODO: is this a precedence issue?
2126+ <|> queryMultiMatchQuery
18942127 <|> queryBoolQuery `taggedWith` "bool"
18952128 <|> queryBoostingQuery `taggedWith` "boosting"
18962129 <|> queryCommonTermsQuery `taggedWith` "common"
@@ -2571,6 +2804,232 @@ instance ToJSON IndexSettings where
25712804 ]
25722805 ]
25732806
2807+instance FromJSON IndexSettings where
2808+ parseJSON = withObject "IndexSettings" parse
2809+ where parse o = do s <- o .: "settings"
2810+ i <- s .: "index"
2811+ IndexSettings <$> i .: "number_of_shards"
2812+ <*> i .: "number_of_replicas"
2813+
2814+instance ToJSON UpdatableIndexSetting where
2815+ toJSON (NumberOfReplicas x) = oPath ("index" :| ["number_of_replicas"]) x
2816+ toJSON (AutoExpandReplicas x) = oPath ("index" :| ["auto_expand_replicas"]) x
2817+ toJSON (RefreshInterval x) = oPath ("index" :| ["refresh_interval"]) (NominalDiffTimeJSON x)
2818+ toJSON (IndexConcurrency x) = oPath ("index" :| ["concurrency"]) x
2819+ toJSON (FailOnMergeFailure x) = oPath ("index" :| ["fail_on_merge_failure"]) x
2820+ toJSON (TranslogFlushThresholdOps x) = oPath ("index" :| ["translog", "flush_threshold_ops"]) x
2821+ toJSON (TranslogFlushThresholdSize x) = oPath ("index" :| ["translog", "flush_threshold_size"]) x
2822+ toJSON (TranslogFlushThresholdPeriod x) = oPath ("index" :| ["translog", "flush_threshold_period"]) (NominalDiffTimeJSON x)
2823+ toJSON (TranslogDisableFlush x) = oPath ("index" :| ["translog", "disable_flush"]) x
2824+ toJSON (CacheFilterMaxSize x) = oPath ("index" :| ["cache", "filter", "max_size"]) x
2825+ toJSON (CacheFilterExpire x) = oPath ("index" :| ["cache", "filter", "expire"]) (NominalDiffTimeJSON <$> x)
2826+ toJSON (GatewaySnapshotInterval x) = oPath ("index" :| ["gateway", "snapshot_interval"]) (NominalDiffTimeJSON x)
2827+ toJSON (RoutingAllocationInclude fs) = oPath ("index" :| ["routing", "allocation", "include"]) (attrFilterJSON fs)
2828+ toJSON (RoutingAllocationExclude fs) = oPath ("index" :| ["routing", "allocation", "exclude"]) (attrFilterJSON fs)
2829+ toJSON (RoutingAllocationRequire fs) = oPath ("index" :| ["routing", "allocation", "require"]) (attrFilterJSON fs)
2830+ toJSON (RoutingAllocationEnable x) = oPath ("index" :| ["routing", "allocation", "enable"]) x
2831+ toJSON (RoutingAllocationShardsPerNode x) = oPath ("index" :| ["routing", "allocation", "total_shards_per_node"]) x
2832+ toJSON (RecoveryInitialShards x) = oPath ("index" :| ["recovery", "initial_shards"]) x
2833+ toJSON (GCDeletes x) = oPath ("index" :| ["gc_deletes"]) (NominalDiffTimeJSON x)
2834+ toJSON (TTLDisablePurge x) = oPath ("index" :| ["ttl", "disable_purge"]) x
2835+ toJSON (TranslogFSType x) = oPath ("index" :| ["translog", "fs", "type"]) x
2836+ toJSON (IndexCompoundFormat x) = oPath ("index" :| ["compound_format"]) x
2837+ toJSON (IndexCompoundOnFlush x) = oPath ("index" :| ["compound_on_flush"]) x
2838+ toJSON (WarmerEnabled x) = oPath ("index" :| ["warmer", "enabled"]) x
2839+ toJSON (BlocksReadOnly x) = oPath ("blocks" :| ["read_only"]) x
2840+ toJSON (BlocksRead x) = oPath ("blocks" :| ["read"]) x
2841+ toJSON (BlocksWrite x) = oPath ("blocks" :| ["write"]) x
2842+ toJSON (BlocksMetaData x) = oPath ("blocks" :| ["metadata"]) x
2843+
2844+instance FromJSON UpdatableIndexSetting where
2845+ parseJSON = withObject "UpdatableIndexSetting" parse
2846+ where parse o = numberOfReplicas `taggedAt` ["index", "number_of_replicas"]
2847+ <|> autoExpandReplicas `taggedAt` ["index", "auto_expand_replicas"]
2848+ <|> refreshInterval `taggedAt` ["index", "refresh_interval"]
2849+ <|> indexConcurrency `taggedAt` ["index", "concurrency"]
2850+ <|> failOnMergeFailure `taggedAt` ["index", "fail_on_merge_failure"]
2851+ <|> translogFlushThresholdOps `taggedAt` ["index", "translog", "flush_threshold_ops"]
2852+ <|> translogFlushThresholdSize `taggedAt` ["index", "translog", "flush_threshold_size"]
2853+ <|> translogFlushThresholdPeriod `taggedAt` ["index", "translog", "flush_threshold_period"]
2854+ <|> translogDisableFlush `taggedAt` ["index", "translog", "disable_flush"]
2855+ <|> cacheFilterMaxSize `taggedAt` ["index", "cache", "filter", "max_size"]
2856+ <|> cacheFilterExpire `taggedAt` ["index", "cache", "filter", "expire"]
2857+ <|> gatewaySnapshotInterval `taggedAt` ["index", "gateway", "snapshot_interval"]
2858+ <|> routingAllocationInclude `taggedAt` ["index", "routing", "allocation", "include"]
2859+ <|> routingAllocationExclude `taggedAt` ["index", "routing", "allocation", "exclude"]
2860+ <|> routingAllocationRequire `taggedAt` ["index", "routing", "allocation", "require"]
2861+ <|> routingAllocationEnable `taggedAt` ["index", "routing", "allocation", "enable"]
2862+ <|> routingAllocationShardsPerNode `taggedAt` ["index", "routing", "allocation", "total_shards_per_node"]
2863+ <|> recoveryInitialShards `taggedAt` ["index", "recovery", "initial_shards"]
2864+ <|> gcDeletes `taggedAt` ["index", "gc_deletes"]
2865+ <|> ttlDisablePurge `taggedAt` ["index", "ttl", "disable_purge"]
2866+ <|> translogFSType `taggedAt` ["index", "translog", "fs", "type"]
2867+ <|> compoundFormat `taggedAt` ["index", "compound_format"]
2868+ <|> compoundOnFlush `taggedAt` ["index", "compound_on_flush"]
2869+ <|> warmerEnabled `taggedAt` ["index", "warmer", "enabled"]
2870+ <|> blocksReadOnly `taggedAt` ["blocks", "read_only"]
2871+ <|> blocksRead `taggedAt` ["blocks", "read"]
2872+ <|> blocksWrite `taggedAt` ["blocks", "write"]
2873+ <|> blocksMetaData `taggedAt` ["blocks", "metadata"]
2874+ where taggedAt f ks = taggedAt' f (Object o) ks
2875+ taggedAt' f v [] = f =<< (parseJSON v <|> (parseJSON =<< unStringlyTypeJSON v))
2876+ taggedAt' f v (k:ks) = withObject "Object" (\o -> do v' <- o .: k
2877+ taggedAt' f v' ks) v
2878+ numberOfReplicas = pure . NumberOfReplicas
2879+ autoExpandReplicas = pure . AutoExpandReplicas
2880+ refreshInterval = pure . RefreshInterval . ndtJSON
2881+ indexConcurrency = pure . IndexConcurrency
2882+ failOnMergeFailure = pure . FailOnMergeFailure
2883+ translogFlushThresholdOps = pure . TranslogFlushThresholdOps
2884+ translogFlushThresholdSize = pure . TranslogFlushThresholdSize
2885+ translogFlushThresholdPeriod = pure . TranslogFlushThresholdPeriod . ndtJSON
2886+ translogDisableFlush = pure . TranslogDisableFlush
2887+ cacheFilterMaxSize = pure . CacheFilterMaxSize
2888+ cacheFilterExpire = pure . CacheFilterExpire . fmap ndtJSON
2889+ gatewaySnapshotInterval = pure . GatewaySnapshotInterval . ndtJSON
2890+ routingAllocationInclude = fmap RoutingAllocationInclude . parseAttrFilter
2891+ routingAllocationExclude = fmap RoutingAllocationExclude . parseAttrFilter
2892+ routingAllocationRequire = fmap RoutingAllocationRequire . parseAttrFilter
2893+ routingAllocationEnable = pure . RoutingAllocationEnable
2894+ routingAllocationShardsPerNode = pure . RoutingAllocationShardsPerNode
2895+ recoveryInitialShards = pure . RecoveryInitialShards
2896+ gcDeletes = pure . GCDeletes . ndtJSON
2897+ ttlDisablePurge = pure . TTLDisablePurge
2898+ translogFSType = pure . TranslogFSType
2899+ compoundFormat = pure . IndexCompoundFormat
2900+ compoundOnFlush = pure . IndexCompoundOnFlush
2901+ warmerEnabled = pure . WarmerEnabled
2902+ blocksReadOnly = pure . BlocksReadOnly
2903+ blocksRead = pure . BlocksRead
2904+ blocksWrite = pure . BlocksWrite
2905+ blocksMetaData = pure . BlocksMetaData
2906+
2907+instance FromJSON IndexSettingsSummary where
2908+ parseJSON = withObject "IndexSettingsSummary" parse
2909+ where parse o = case HM.toList o of
2910+ [(ixn, v@(Object o'))] -> IndexSettingsSummary (IndexName ixn)
2911+ <$> parseJSON v
2912+ <*> (fmap (filter (not . redundant)) . parseSettings =<< o' .: "settings")
2913+ _ -> fail "Expected single-key object with index name"
2914+ redundant (NumberOfReplicas _) = True
2915+ redundant _ = False
2916+
2917+-- | For some reason in the settings API, all leaf values get returned
2918+-- as strings. This function attepmts to recover from this for all
2919+-- non-recursive JSON types. If nothing can be done or the same value
2920+-- would be return, it returns 'mzero'
2921+unStringlyTypeJSON :: MonadPlus m => Value -> m Value
2922+unStringlyTypeJSON (String "true") = return (Bool True)
2923+unStringlyTypeJSON (String "false") = return (Bool False)
2924+unStringlyTypeJSON (String "null") = return Null
2925+unStringlyTypeJSON (String t) = case readMay (T.unpack t) of
2926+ Just n -> return (Number n)
2927+ Nothing -> mzero
2928+unStringlyTypeJSON _ = mzero
2929+
2930+
2931+parseSettings :: Object -> Parser [UpdatableIndexSetting]
2932+parseSettings o = do
2933+ o' <- o .: "index"
2934+ -- slice the index object into singleton hashmaps and try to parse each
2935+ parses <- forM (HM.toList o') $ \(k, v) -> do
2936+ -- blocks are now nested into the "index" key, which is not how they're serialized
2937+ let atRoot = Object (HM.singleton k v)
2938+ let atIndex = Object (HM.singleton "index" atRoot)
2939+ optional (parseJSON atRoot <|> parseJSON atIndex)
2940+ return (catMaybes parses)
2941+
2942+oPath :: ToJSON a => NonEmpty Text -> a -> Value
2943+oPath (k :| []) v = object [k .= v]
2944+oPath (k:| (h:t)) v = object [k .= oPath (h :| t) v]
2945+
2946+attrFilterJSON :: NonEmpty NodeAttrFilter -> Value
2947+attrFilterJSON fs = object [ n .= T.intercalate "," (toList vs)
2948+ | NodeAttrFilter (NodeAttrName n) vs <- toList fs]
2949+
2950+parseAttrFilter :: Value -> Parser (NonEmpty NodeAttrFilter)
2951+parseAttrFilter = withObject "NonEmpty NodeAttrFilter" parse
2952+ where parse o = case HM.toList o of
2953+ [] -> fail "Expected non-empty list of NodeAttrFilters"
2954+ x:xs -> DT.mapM (uncurry parse') (x :| xs)
2955+ parse' n = withText "Text" $ \t ->
2956+ case T.splitOn "," t of
2957+ fv:fvs -> return (NodeAttrFilter (NodeAttrName n) (fv :| fvs))
2958+ [] -> fail "Expected non-empty list of filter values"
2959+
2960+instance ToJSON ReplicaBounds where
2961+ toJSON (ReplicasBounded a b) = String (showText a <> "-" <> showText b)
2962+ toJSON (ReplicasLowerBounded a) = String (showText a <> "-all")
2963+ toJSON ReplicasUnbounded = Bool False
2964+
2965+instance FromJSON ReplicaBounds where
2966+ parseJSON v = withText "ReplicaBounds" parseText v
2967+ <|> withBool "ReplicaBounds" parseBool v
2968+ where parseText t = case T.splitOn "-" t of
2969+ [a, "all"] -> ReplicasLowerBounded <$> parseReadText a
2970+ [a, b] -> ReplicasBounded <$> parseReadText a
2971+ <*> parseReadText b
2972+ _ -> fail ("Could not parse ReplicaBounds: " <> show t)
2973+ parseBool False = pure ReplicasUnbounded
2974+ parseBool _ = fail "ReplicasUnbounded cannot be represented with True"
2975+
2976+instance ToJSON AllocationPolicy where
2977+ toJSON AllocAll = String "all"
2978+ toJSON AllocPrimaries = String "primaries"
2979+ toJSON AllocNewPrimaries = String "new_primaries"
2980+ toJSON AllocNone = String "none"
2981+
2982+instance FromJSON AllocationPolicy where
2983+ parseJSON = withText "AllocationPolicy" parse
2984+ where parse "all" = pure AllocAll
2985+ parse "primaries" = pure AllocPrimaries
2986+ parse "new_primaries" = pure AllocNewPrimaries
2987+ parse "none" = pure AllocNone
2988+ parse t = fail ("Invlaid AllocationPolicy: " <> show t)
2989+
2990+instance ToJSON InitialShardCount where
2991+ toJSON QuorumShards = String "quorum"
2992+ toJSON QuorumMinus1Shards = String "quorum-1"
2993+ toJSON FullShards = String "full"
2994+ toJSON FullMinus1Shards = String "full-1"
2995+ toJSON (ExplicitShards x) = toJSON x
2996+
2997+instance FromJSON InitialShardCount where
2998+ parseJSON v = withText "InitialShardCount" parseText v
2999+ <|> ExplicitShards <$> parseJSON v
3000+ where parseText "quorum" = pure QuorumShards
3001+ parseText "quorum-1" = pure QuorumMinus1Shards
3002+ parseText "full" = pure FullShards
3003+ parseText "full-1" = pure FullMinus1Shards
3004+ parseText _ = mzero
3005+
3006+instance ToJSON FSType where
3007+ toJSON FSSimple = "simple"
3008+ toJSON FSBuffered = "buffered"
3009+
3010+instance FromJSON FSType where
3011+ parseJSON = withText "FSType" parse
3012+ where parse "simple" = pure FSSimple
3013+ parse "buffered" = pure FSBuffered
3014+ parse t = fail ("Invalid FSType: " <> show t)
3015+
3016+instance ToJSON CompoundFormat where
3017+ toJSON (CompoundFileFormat x) = Bool x
3018+ toJSON (MergeSegmentVsTotalIndex x) = toJSON x
3019+
3020+instance FromJSON CompoundFormat where
3021+ parseJSON v = CompoundFileFormat <$> parseJSON v
3022+ <|> MergeSegmentVsTotalIndex <$> parseJSON v
3023+
3024+instance ToJSON NominalDiffTimeJSON where
3025+ toJSON (NominalDiffTimeJSON t) = String (showText (round t :: Integer) <> "s")
3026+
3027+instance FromJSON NominalDiffTimeJSON where
3028+ parseJSON = withText "NominalDiffTime" parse
3029+ where parse t = case T.takeEnd 1 t of
3030+ "s" -> NominalDiffTimeJSON . fromInteger <$> parseReadText (T.dropEnd 1 t)
3031+ _ -> fail "Invalid or missing NominalDiffTime unit (expected s)"
3032+
25743033instance ToJSON IndexTemplate where
25753034 toJSON (IndexTemplate p s m) = merge
25763035 (object [ "template" .= p
@@ -2610,7 +3069,7 @@ instance FromJSON IndexAliasesSummary where
26103069 parseJSON = withObject "IndexAliasesSummary" parse
26113070 where parse o = IndexAliasesSummary . mconcat <$> mapM (uncurry go) (HM.toList o)
26123071 go ixn = withObject "index aliases" $ \ia -> do
2613− aliases <- ia .: "aliases"
3072+ aliases <- ia .:? "aliases" .!= mempty
26143073 forM (HM.toList aliases) $ \(aName, v) -> do
26153074 let indexAlias = IndexAlias (IndexName ixn) (IndexAliasName (IndexName aName))
26163075 IndexAliasSummary indexAlias <$> parseJSON v
@@ -3056,6 +3515,19 @@ instance FromJSON DocVersion where
30563515 i <- parseJSON v
30573516 maybe (fail "DocVersion out of range") return $ mkDocVersion i
30583517
3518+-- This insanity is because ES *sometimes* returns Replica/Shard counts as strings
3519+instance FromJSON ReplicaCount where
3520+ parseJSON v = parseAsInt v
3521+ <|> parseAsString v
3522+ where parseAsInt = fmap ReplicaCount . parseJSON
3523+ parseAsString = withText "ReplicaCount" (fmap ReplicaCount . parseReadText)
3524+
3525+instance FromJSON ShardCount where
3526+ parseJSON v = parseAsInt v
3527+ <|> parseAsString v
3528+ where parseAsInt = fmap ShardCount . parseJSON
3529+ parseAsString = withText "ShardCount" (fmap ShardCount . parseReadText)
3530+
30593531instance Bounded DocVersion where
30603532 minBound = DocVersion 1
30613533 maxBound = DocVersion 9200000000000000000 -- 9.2e+18