git.iko.soy/typeable/bloodhound
on v0.10.0.0 help sign in
3546 lines 153 kB history raw
1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE NoMonomorphismRestriction #-}
8{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE RecordWildCards #-}
10{-# LANGUAGE UndecidableInstances #-}
12-------------------------------------------------------------------------------
13-- |
14-- Module : Database.Bloodhound.Types
15-- Copyright : (C) 2014 Chris Allen
16-- License : BSD-style (see the file LICENSE)
17-- Maintainer : Chris Allen <cma@bitemyapp.com
18-- Stability : provisional
19-- Portability : DeriveGeneric, RecordWildCards
20--
21-- Data types for describing actions and data structures performed to interact
22-- with Elasticsearch. The two main buckets your queries against Elasticsearch
23-- will fall into are 'Query's and 'Filter's. 'Filter's are more like
24-- traditional database constraints and often have preferable performance
25-- properties. 'Query's support human-written textual queries, such as fuzzy
26-- queries.
27-------------------------------------------------------------------------------
31module Database.Bloodhound.Types
32 ( defaultCache
33 , defaultIndexSettings
34 , defaultIndexDocumentSettings
35 , mkSort
36 , showText
37 , unpackId
38 , mkMatchQuery
39 , mkMultiMatchQuery
40 , mkBoolQuery
41 , mkRangeQuery
42 , mkQueryStringQuery
43 , mkAggregations
44 , mkTermsAggregation
45 , mkTermsScriptAggregation
46 , mkDateHistogram
47 , mkDocVersion
48 , docVersionNumber
49 , toTerms
50 , toDateHistogram
51 , omitNulls
52 , BH(..)
53 , runBH
54 , BHEnv(..)
55 , MonadBH(..)
56 , Version(..)
57 , Status(..)
58 , Existence(..)
59 , NullValue(..)
60 , IndexSettings(..)
61 , UpdatableIndexSetting(..)
62 , IndexSettingsSummary(..)
63 , AllocationPolicy(..)
64 , ReplicaBounds(..)
65 , Bytes(..)
66 , FSType(..)
67 , InitialShardCount(..)
68 , NodeAttrFilter(..)
69 , NodeAttrName(..)
70 , CompoundFormat(..)
71 , IndexTemplate(..)
72 , Server(..)
73 , Reply
74 , EsResult(..)
75 , EsResultFound(..)
76 , EsError(..)
77 , EsProtocolException(..)
78 , IndexAlias(..)
79 , IndexAliasName(..)
80 , IndexAliasAction(..)
81 , IndexAliasCreate(..)
82 , IndexAliasSummary(..)
83 , IndexAliasesSummary(..)
84 , AliasRouting(..)
85 , SearchAliasRouting(..)
86 , IndexAliasRouting(..)
87 , RoutingValue(..)
88 , DocVersion
89 , ExternalDocVersion(..)
90 , VersionControl(..)
91 , DocumentParent(..)
92 , IndexDocumentSettings(..)
93 , Query(..)
94 , Search(..)
95 , SearchType(..)
96 , SearchResult(..)
97 , ScrollId(..)
98 , SearchHits(..)
99 , TrackSortScores
100 , From(..)
101 , Size(..)
102 , Source(..)
103 , PatternOrPatterns(..)
104 , Include(..)
105 , Exclude(..)
106 , Pattern(..)
107 , ShardResult(..)
108 , Hit(..)
109 , Filter(..)
110 , Seminearring(..)
111 , BoolMatch(..)
112 , Term(..)
113 , GeoPoint(..)
114 , GeoBoundingBoxConstraint(..)
115 , GeoBoundingBox(..)
116 , GeoFilterType(..)
117 , Distance(..)
118 , DistanceUnit(..)
119 , DistanceType(..)
120 , DistanceRange(..)
121 , OptimizeBbox(..)
122 , LatLon(..)
123 , RangeValue(..)
124 , RangeExecution(..)
125 , LessThan(..)
126 , LessThanEq(..)
127 , GreaterThan(..)
128 , GreaterThanEq(..)
129 , LessThanD(..)
130 , LessThanEqD(..)
131 , GreaterThanD(..)
132 , GreaterThanEqD(..)
133 , Regexp(..)
134 , RegexpFlags(..)
135 , RegexpFlag(..)
136 , FieldName(..)
137 , Script(..)
138 , IndexName(..)
139 , TemplateName(..)
140 , TemplatePattern(..)
141 , MappingName(..)
142 , DocId(..)
143 , CacheName(..)
144 , CacheKey(..)
145 , BulkOperation(..)
146 , ReplicaCount(..)
147 , ShardCount(..)
148 , Sort
149 , SortMode(..)
150 , SortOrder(..)
151 , SortSpec(..)
152 , DefaultSort(..)
153 , Missing(..)
154 , OpenCloseIndex(..)
155 , Method
156 , Boost(..)
157 , MatchQuery(..)
158 , MultiMatchQuery(..)
159 , BoolQuery(..)
160 , BoostingQuery(..)
161 , CommonTermsQuery(..)
162 , DisMaxQuery(..)
163 , FilteredQuery(..)
164 , FuzzyLikeThisQuery(..)
165 , FuzzyLikeFieldQuery(..)
166 , FuzzyQuery(..)
167 , HasChildQuery(..)
168 , HasParentQuery(..)
169 , IndicesQuery(..)
170 , MoreLikeThisQuery(..)
171 , MoreLikeThisFieldQuery(..)
172 , NestedQuery(..)
173 , PrefixQuery(..)
174 , QueryStringQuery(..)
175 , SimpleQueryStringQuery(..)
176 , RangeQuery(..)
177 , RegexpQuery(..)
178 , QueryString(..)
179 , BooleanOperator(..)
180 , ZeroTermsQuery(..)
181 , CutoffFrequency(..)
182 , Analyzer(..)
183 , MaxExpansions(..)
184 , Lenient(..)
185 , MatchQueryType(..)
186 , MultiMatchQueryType(..)
187 , Tiebreaker(..)
188 , MinimumMatch(..)
189 , DisableCoord(..)
190 , CommonMinimumMatch(..)
191 , MinimumMatchHighLow(..)
192 , PrefixLength(..)
193 , Fuzziness(..)
194 , IgnoreTermFrequency(..)
195 , MaxQueryTerms(..)
196 , ScoreType(..)
197 , Score
198 , Cache
199 , TypeName(..)
200 , BoostTerms(..)
201 , MaxWordLength(..)
202 , MinWordLength(..)
203 , MaxDocFrequency(..)
204 , MinDocFrequency(..)
205 , PhraseSlop(..)
206 , StopWord(..)
207 , QueryPath(..)
208 , MinimumTermFrequency(..)
209 , PercentMatch(..)
210 , FieldDefinition(..)
211 , MappingField(..)
212 , Mapping(..)
213 , AllowLeadingWildcard(..)
214 , LowercaseExpanded(..)
215 , GeneratePhraseQueries(..)
216 , Locale(..)
217 , AnalyzeWildcard(..)
218 , EnablePositionIncrements(..)
219 , SimpleQueryFlag(..)
220 , FieldOrFields(..)
221 , Monoid(..)
222 , ToJSON(..)
223 , Interval(..)
224 , TimeInterval(..)
225 , ExecutionHint(..)
226 , CollectionMode(..)
227 , TermOrder(..)
228 , TermInclusion(..)
230 , Aggregation(..)
231 , Aggregations
232 , AggregationResults
233 , Bucket(..)
234 , BucketAggregation(..)
235 , TermsAggregation(..)
236 , ValueCountAggregation(..)
237 , FilterAggregation(..)
238 , DateHistogramAggregation(..)
239 , DateRangeAggregation(..)
240 , DateRangeAggRange(..)
241 , DateMathExpr(..)
242 , DateMathAnchor(..)
243 , DateMathModifier(..)
244 , DateMathUnit(..)
246 , Highlights(..)
247 , FieldHighlight(..)
248 , HighlightSettings(..)
249 , PlainHighlight(..)
250 , PostingsHighlight(..)
251 , FastVectorHighlight(..)
252 , CommonHighlight(..)
253 , NonPostings(..)
254 , HighlightEncoder(..)
255 , HighlightTag(..)
256 , HitHighlight
258 , TermsResult(..)
259 , DateHistogramResult(..)
260 , DateRangeResult(..)
261 ) where
263import Control.Applicative
264import Control.Monad.Catch
265import Control.Monad.Except
266import Control.Monad.Reader
267import Control.Monad.State
268import Control.Monad.Writer
269import Data.Aeson
270import Data.Aeson.Types (Pair, Parser, emptyObject,
271 parseMaybe)
272import qualified Data.ByteString.Lazy.Char8 as L
273import Data.Char
274import Data.Hashable (Hashable)
275import qualified Data.HashMap.Strict as HM
276import Data.List (foldl', nub)
277import Data.List.NonEmpty (NonEmpty (..), toList)
278import qualified Data.Map.Strict as M
279import Data.Maybe
280import Data.Text (Text)
281import qualified Data.Text as T
282import Data.Time.Calendar
283import Data.Time.Clock (NominalDiffTime, UTCTime)
284import Data.Time.Clock.POSIX
285import qualified Data.Traversable as DT
286import Data.Typeable (Typeable)
287import qualified Data.Vector as V
288import GHC.Enum
289import GHC.Generics (Generic)
290import Network.HTTP.Client
291import qualified Network.HTTP.Types.Method as NHTM
293import Database.Bloodhound.Types.Class
295-- $setup
296-- >>> :set -XOverloadedStrings
297-- >>> import Database.Bloodhound
298-- >>> let testServer = (Server "http://localhost:9200")
299-- >>> let testIndex = IndexName "twitter"
300-- >>> let testMapping = MappingName "tweet"
301-- >>> let defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
303-- defaultIndexSettings is exported by Database.Bloodhound as well
304-- no trailing slashes in servers, library handles building the path.
306{-| Common environment for Elasticsearch calls. Connections will be
307 pipelined according to the provided HTTP connection manager.
308-}
309data BHEnv = BHEnv { bhServer :: Server
310 , bhManager :: Manager
311 }
313{-| All API calls to Elasticsearch operate within
314 MonadBH. The idea is that it can be easily embedded in your
315 own monad transformer stack. A default instance for a ReaderT and
316 alias 'BH' is provided for the simple case.
317-}
318class (Functor m, Applicative m, MonadIO m) => MonadBH m where
319 getBHEnv :: m BHEnv
321newtype BH m a = BH {
322 unBH :: ReaderT BHEnv m a
323 } deriving ( Functor
324 , Applicative
325 , Monad
326 , MonadIO
327 , MonadState s
328 , MonadWriter w
329 , MonadError e
330 , Alternative
331 , MonadPlus
332 , MonadFix
333 , MonadThrow
334 , MonadCatch
335 , MonadMask)
337instance MonadTrans BH where
338 lift = BH . lift
340instance (MonadReader r m) => MonadReader r (BH m) where
341 ask = lift ask
342 local f (BH (ReaderT m)) = BH $ ReaderT $ \r ->
343 local f (m r)
345instance (Functor m, Applicative m, MonadIO m) => MonadBH (BH m) where
346 getBHEnv = BH getBHEnv
349instance (Functor m, Applicative m, MonadIO m) => MonadBH (ReaderT BHEnv m) where
350 getBHEnv = ask
352runBH :: BHEnv -> BH m a -> m a
353runBH e f = runReaderT (unBH f) e
355{-| 'Version' is embedded in 'Status' -}
356data Version = Version { number :: Text
357 , build_hash :: Text
358 , build_timestamp :: UTCTime
359 , build_snapshot :: Bool
360 , lucene_version :: Text } deriving (Eq, Show, Generic, Typeable)
362{-| 'Status' is a data type for describing the JSON body returned by
363 Elasticsearch when you query its status. This was deprecated in 1.2.0.
365 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html#indices-status>
366-}
368data Status = Status { ok :: Maybe Bool
369 , status :: Int
370 , name :: Text
371 , version :: Version
372 , tagline :: Text } deriving (Eq, Show, Generic)
374{-| 'IndexSettings' is used to configure the shards and replicas when you create
375 an Elasticsearch Index.
377 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
378-}
380data IndexSettings =
381 IndexSettings { indexShards :: ShardCount
382 , indexReplicas :: ReplicaCount } deriving (Eq, Show, Generic, Typeable)
384{-| 'defaultIndexSettings' is an 'IndexSettings' with 3 shards and 2 replicas. -}
385defaultIndexSettings :: IndexSettings
386defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
388{-| 'UpdatableIndexSetting' are settings which may be updated after an index is created.
390 <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html>
391-}
392data 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)
442data 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)
452data ReplicaBounds = ReplicasBounded Int Int
453 | ReplicasLowerBounded Int
454 | ReplicasUnbounded
455 deriving (Eq, Show, Generic, Typeable)
457newtype Bytes = Bytes Int deriving (Eq, Show, Generic, Typeable, Ord, ToJSON, FromJSON)
459data FSType = FSSimple
460 | FSBuffered deriving (Eq, Show, Generic, Typeable, Ord)
462data InitialShardCount = QuorumShards
463 | QuorumMinus1Shards
464 | FullShards
465 | FullMinus1Shards
466 | ExplicitShards Int
467 deriving (Eq, Show, Generic, Typeable)
469data NodeAttrFilter = NodeAttrFilter { nodeAttrFilterName :: NodeAttrName
470 , nodeAttrFilterValues :: NonEmpty Text}
471 deriving (Eq, Show, Generic, Ord)
473newtype NodeAttrName = NodeAttrName Text deriving (Eq, Show, Ord, Generic, Typeable)
475data 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)
480newtype NominalDiffTimeJSON = NominalDiffTimeJSON { ndtJSON :: NominalDiffTime }
482data IndexSettingsSummary = IndexSettingsSummary { sSummaryIndexName :: IndexName
483 , sSummaryFixedSettings :: IndexSettings
484 , sSummaryUpdateable :: [UpdatableIndexSetting]}
485 deriving (Eq, Show, Generic, Typeable)
487{-| 'Reply' and 'Method' are type synonyms from 'Network.HTTP.Types.Method.Method' -}
488type Reply = Network.HTTP.Client.Response L.ByteString
489type Method = NHTM.Method
491{-| 'OpenCloseIndex' is a sum type for opening and closing indices.
493 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
494-}
495data OpenCloseIndex = OpenIndex | CloseIndex deriving (Eq, Show, Generic, Typeable)
497data FieldType = GeoPointType
498 | GeoShapeType
499 | FloatType
500 | IntegerType
501 | LongType
502 | ShortType
503 | ByteType deriving (Eq, Show, Generic, Typeable)
505data FieldDefinition =
506 FieldDefinition { fieldType :: FieldType } deriving (Eq, Show, Generic, Typeable)
508{-| An 'IndexTemplate' defines a template that will automatically be
509 applied to new indices created. The templates include both
510 'IndexSettings' and mappings, and a simple 'TemplatePattern' that
511 controls if the template will be applied to the index created.
512 Specify mappings as follows: @[toJSON TweetMapping, ...]@
514 https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html
515-}
516data IndexTemplate =
517 IndexTemplate { templatePattern :: TemplatePattern
518 , templateSettings :: Maybe IndexSettings
519 , templateMappings :: [Value]
520 }
522data MappingField =
523 MappingField { mappingFieldName :: FieldName
524 , fieldDefinition :: FieldDefinition } deriving (Eq, Show, Generic, Typeable)
526{-| Support for type reification of 'Mapping's is currently incomplete, for
527 now the mapping API verbiage expects a 'ToJSON'able blob.
529 Indexes have mappings, mappings are schemas for the documents contained in the
530 index. I'd recommend having only one mapping per index, always having a mapping,
531 and keeping different kinds of documents separated if possible.
532-}
533data Mapping = Mapping { typeName :: TypeName
534 , mappingFields :: [MappingField] } deriving (Eq, Show, Generic, Typeable)
536{-| 'BulkOperation' is a sum type for expressing the four kinds of bulk
537 operation index, create, delete, and update. 'BulkIndex' behaves like an
538 "upsert", 'BulkCreate' will fail if a document already exists at the DocId.
540 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html#docs-bulk>
541-}
542data BulkOperation =
543 BulkIndex IndexName MappingName DocId Value
544 | BulkCreate IndexName MappingName DocId Value
545 | BulkDelete IndexName MappingName DocId
546 | BulkUpdate IndexName MappingName DocId Value deriving (Eq, Show, Generic, Typeable)
548{-| 'EsResult' describes the standard wrapper JSON document that you see in
549 successful Elasticsearch lookups or lookups that couldn't find the document.
550-}
551data EsResult a = EsResult { _index :: Text
552 , _type :: Text
553 , _id :: Text
554 , foundResult :: Maybe (EsResultFound a)} deriving (Eq, Show, Generic, Typeable)
556{-| 'EsResultFound' contains the document and its metadata inside of an
557 'EsResult' when the document was successfully found.
558-}
559data EsResultFound a = EsResultFound { _version :: DocVersion
560 , _source :: a } deriving (Eq, Show, Generic, Typeable)
562{-| 'EsError' is the generic type that will be returned when there was a
563 problem. If you can't parse the expected response, its a good idea to
564 try parsing this.
565-}
566data EsError = EsError { errorStatus :: Int
567 , errorMessage :: Text } deriving (Eq, Show, Generic, Typeable)
569{-| 'EsProtocolException' ideally should never be thrown. It will only
570be thrown when Bloodhound can't parse a response returned by the
571ElasticSearch server. This should be reported as a bug to the bug
572tracker. Be sure to include the body.
573-}
574data EsProtocolException = EsProtocolException { esProtoExBody :: L.ByteString }
575 deriving (Eq, Show, Generic, Typeable)
577instance Exception EsProtocolException
579data IndexAlias = IndexAlias { srcIndex :: IndexName
580 , indexAlias :: IndexAliasName } deriving (Eq, Show, Generic, Typeable)
582newtype IndexAliasName = IndexAliasName { indexAliasName :: IndexName } deriving (Eq, Show, Generic, ToJSON)
584data IndexAliasAction = AddAlias IndexAlias IndexAliasCreate
585 | RemoveAlias IndexAlias deriving (Show, Eq, Generic, Typeable)
587data IndexAliasCreate = IndexAliasCreate { aliasCreateRouting :: Maybe AliasRouting
588 , aliasCreateFilter :: Maybe Filter}
589 deriving (Show, Eq, Generic, Typeable)
591data AliasRouting = AllAliasRouting RoutingValue
592 | GranularAliasRouting (Maybe SearchAliasRouting) (Maybe IndexAliasRouting)
593 deriving (Show, Eq, Generic, Typeable)
595newtype SearchAliasRouting = SearchAliasRouting (NonEmpty RoutingValue) deriving (Show, Eq, Generic, Typeable)
597newtype IndexAliasRouting = IndexAliasRouting RoutingValue deriving (Show, Eq, Generic, ToJSON, FromJSON, Typeable)
599newtype RoutingValue = RoutingValue { routingValue :: Text } deriving (Show, Eq, Generic, ToJSON, FromJSON, Typeable)
601newtype IndexAliasesSummary = IndexAliasesSummary { indexAliasesSummary :: [IndexAliasSummary] } deriving (Show, Eq, Generic, Typeable)
603{-| 'IndexAliasSummary' is a summary of an index alias configured for a server. -}
604data IndexAliasSummary = IndexAliasSummary { indexAliasSummaryAlias :: IndexAlias
605 , indexAliasSummaryCreate :: IndexAliasCreate} deriving (Show, Eq, Generic, Typeable)
607{-| 'DocVersion' is an integer version number for a document between 1
608and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
609-}
610newtype DocVersion = DocVersion {
611 docVersionNumber :: Int
612 } deriving (Eq, Show, Generic, Ord, ToJSON)
614-- | Smart constructor for in-range doc version
615mkDocVersion :: Int -> Maybe DocVersion
616mkDocVersion i
617 | i >= (docVersionNumber minBound) && i <= (docVersionNumber maxBound) =
618 Just $ DocVersion i
619 | otherwise = Nothing
622{-| 'ExternalDocVersion' is a convenience wrapper if your code uses its
623own version numbers instead of ones from ES.
624-}
625newtype ExternalDocVersion = ExternalDocVersion DocVersion
626 deriving (Eq, Show, Generic, Ord, Bounded, Enum, ToJSON)
628{-| 'VersionControl' is specified when indexing documents as a
629optimistic concurrency control.
630-}
631data VersionControl = NoVersionControl
632 -- ^ Don't send a version. This is a pure overwrite.
633 | InternalVersion DocVersion
634 -- ^ Use the default ES versioning scheme. Only
635 -- index the document if the version is the same
636 -- as the one specified. Only applicable to
637 -- updates, as you should be getting Version from
638 -- a search result.
639 | ExternalGT ExternalDocVersion
640 -- ^ Use your own version numbering. Only index
641 -- the document if the version is strictly higher
642 -- OR the document doesn't exist. The given
643 -- version will be used as the new version number
644 -- for the stored document. N.B. All updates must
645 -- increment this number, meaning there is some
646 -- global, external ordering of updates.
647 | ExternalGTE ExternalDocVersion
648 -- ^ Use your own version numbering. Only index
649 -- the document if the version is equal or higher
650 -- than the stored version. Will succeed if there
651 -- is no existing document. The given version will
652 -- be used as the new version number for the
653 -- stored document. Use with care, as this could
654 -- result in data loss.
655 | ForceVersion ExternalDocVersion
656 -- ^ The document will always be indexed and the
657 -- given version will be the new version. This is
658 -- typically used for correcting errors. Use with
659 -- care, as this could result in data loss.
660 deriving (Show, Eq, Generic, Ord)
662{-| 'DocumentParent' is used to specify a parent document.
663-}
664newtype DocumentParent = DocumentParent DocId
665 deriving (Eq, Show, Generic, Typeable)
667{-| 'IndexDocumentSettings' are special settings supplied when indexing
668a document. For the best backwards compatiblity when new fields are
669added, you should probably prefer to start with 'defaultIndexDocumentSettings'
670-}
671data IndexDocumentSettings =
672 IndexDocumentSettings { idsVersionControl :: VersionControl
673 , idsParent :: Maybe DocumentParent
674 } deriving (Eq, Show, Generic, Typeable)
676{-| Reasonable default settings. Chooses no version control and no parent.
677-}
678defaultIndexDocumentSettings :: IndexDocumentSettings
679defaultIndexDocumentSettings = IndexDocumentSettings NoVersionControl Nothing
681{-| 'Sort' is a synonym for a list of 'SortSpec's. Sort behavior is order
682 dependent with later sorts acting as tie-breakers for earlier sorts.
683-}
684type Sort = [SortSpec]
686{-| The two main kinds of 'SortSpec' are 'DefaultSortSpec' and
687 'GeoDistanceSortSpec'. The latter takes a 'SortOrder', 'GeoPoint', and
688 'DistanceUnit' to express "nearness" to a single geographical point as a
689 sort specification.
691<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
692-}
693data SortSpec = DefaultSortSpec DefaultSort
694 | GeoDistanceSortSpec SortOrder GeoPoint DistanceUnit deriving (Eq, Show, Generic, Typeable)
696{-| 'DefaultSort' is usually the kind of 'SortSpec' you'll want. There's a
697 'mkSort' convenience function for when you want to specify only the most
698 common parameters.
700<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
701-}
702data DefaultSort =
703 DefaultSort { sortFieldName :: FieldName
704 , sortOrder :: SortOrder
705 -- default False
706 , ignoreUnmapped :: Bool
707 , sortMode :: Maybe SortMode
708 , missingSort :: Maybe Missing
709 , nestedFilter :: Maybe Filter } deriving (Eq, Show, Generic, Typeable)
711{-| 'SortOrder' is 'Ascending' or 'Descending', as you might expect. These get
712 encoded into "asc" or "desc" when turned into JSON.
714<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
715-}
716data SortOrder = Ascending
717 | Descending deriving (Eq, Show, Generic, Typeable)
719{-| 'Missing' prescribes how to handle missing fields. A missing field can be
720 sorted last, first, or using a custom value as a substitute.
722<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_missing_values>
723-}
724data Missing = LastMissing
725 | FirstMissing
726 | CustomMissing Text deriving (Eq, Show, Generic, Typeable)
728{-| 'SortMode' prescribes how to handle sorting array/multi-valued fields.
730http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_sort_mode_option
731-}
732data SortMode = SortMin
733 | SortMax
734 | SortSum
735 | SortAvg deriving (Eq, Show, Generic, Typeable)
737{-| 'mkSort' defaults everything but the 'FieldName' and the 'SortOrder' so
738 that you can concisely describe the usual kind of 'SortSpec's you want.
739-}
740mkSort :: FieldName -> SortOrder -> DefaultSort
741mkSort fieldName sOrder = DefaultSort fieldName sOrder False Nothing Nothing Nothing
743{-| 'Cache' is for telling ES whether it should cache a 'Filter' not.
744 'Query's cannot be cached.
745-}
746type Cache = Bool -- caching on/off
747defaultCache :: Cache
748defaultCache = False
750{-| 'PrefixValue' is used in 'PrefixQuery' as the main query component.
751-}
752type PrefixValue = Text
754{-| 'BooleanOperator' is the usual And/Or operators with an ES compatible
755 JSON encoding baked in. Used all over the place.
756-}
757data BooleanOperator = And | Or deriving (Eq, Show, Generic, Typeable)
759{-| 'ShardCount' is part of 'IndexSettings'
760-}
761newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic, ToJSON, Typeable)
763{-| 'ReplicaCount' is part of 'IndexSettings'
764-}
765newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic, ToJSON, Typeable)
767{-| 'Server' is used with the client functions to point at the ES instance
768-}
769newtype Server = Server Text deriving (Eq, Show, Generic, Typeable)
771{-| 'IndexName' is used to describe which index to query/create/delete
772-}
773newtype IndexName = IndexName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
775{-| 'TemplateName' is used to describe which template to query/create/delete
776-}
777newtype TemplateName = TemplateName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
779{-| 'TemplatePattern' represents a pattern which is matched against index names
780-}
781newtype TemplatePattern = TemplatePattern Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
783{-| 'MappingName' is part of mappings which are how ES describes and schematizes
784 the data in the indices.
785-}
786newtype MappingName = MappingName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
788{-| 'DocId' is a generic wrapper value for expressing unique Document IDs.
789 Can be set by the user or created by ES itself. Often used in client
790 functions for poking at specific documents.
791-}
792newtype DocId = DocId Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
794{-| 'QueryString' is used to wrap query text bodies, be they human written or not.
795-}
796newtype QueryString = QueryString Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
798{-| 'FieldName' is used all over the place wherever a specific field within
799 a document needs to be specified, usually in 'Query's or 'Filter's.
800-}
801newtype FieldName = FieldName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
804{-| 'Script' is often used in place of 'FieldName' to specify more
805complex ways of extracting a value from a document.
806-}
807newtype Script = Script { scriptText :: Text } deriving (Eq, Show, Generic, Typeable)
809{-| 'CacheName' is used in 'RegexpFilter' for describing the
810 'CacheKey' keyed caching behavior.
811-}
812newtype CacheName = CacheName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
814{-| 'CacheKey' is used in 'RegexpFilter' to key regex caching.
815-}
816newtype CacheKey =
817 CacheKey Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
818newtype Existence =
819 Existence Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
820newtype NullValue =
821 NullValue Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
822newtype CutoffFrequency =
823 CutoffFrequency Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
824newtype Analyzer =
825 Analyzer Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
826newtype MaxExpansions =
827 MaxExpansions Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
829{-| 'Lenient', if set to true, will cause format based failures to be
830 ignored. I don't know what the bloody default is, Elasticsearch
831 documentation didn't say what it was. Let me know if you figure it out.
832-}
833newtype Lenient =
834 Lenient Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
835newtype Tiebreaker =
836 Tiebreaker Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
837newtype Boost =
838 Boost Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
839newtype BoostTerms =
840 BoostTerms Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
842{-| 'MinimumMatch' controls how many should clauses in the bool query should
843 match. Can be an absolute value (2) or a percentage (30%) or a
844 combination of both.
845-}
846newtype MinimumMatch =
847 MinimumMatch Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
848newtype DisableCoord =
849 DisableCoord Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
850newtype IgnoreTermFrequency =
851 IgnoreTermFrequency Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
852newtype MinimumTermFrequency =
853 MinimumTermFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
854newtype MaxQueryTerms =
855 MaxQueryTerms Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
856newtype Fuzziness =
857 Fuzziness Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
859{-| 'PrefixLength' is the prefix length used in queries, defaults to 0. -}
860newtype PrefixLength =
861 PrefixLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
862newtype TypeName =
863 TypeName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
864newtype PercentMatch =
865 PercentMatch Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
866newtype StopWord =
867 StopWord Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
868newtype QueryPath =
869 QueryPath Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
871{-| Allowing a wildcard at the beginning of a word (eg "*ing") is particularly
872 heavy, because all terms in the index need to be examined, just in case
873 they match. Leading wildcards can be disabled by setting
874 'AllowLeadingWildcard' to false. -}
875newtype AllowLeadingWildcard =
876 AllowLeadingWildcard Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
877newtype LowercaseExpanded =
878 LowercaseExpanded Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
879newtype EnablePositionIncrements =
880 EnablePositionIncrements Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
882{-| By default, wildcard terms in a query are not analyzed.
883 Setting 'AnalyzeWildcard' to true enables best-effort analysis.
884-}
885newtype AnalyzeWildcard = AnalyzeWildcard Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
887{-| 'GeneratePhraseQueries' defaults to false.
888-}
889newtype GeneratePhraseQueries =
890 GeneratePhraseQueries Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
892{-| 'Locale' is used for string conversions - defaults to ROOT.
893-}
894newtype Locale = Locale Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
895newtype MaxWordLength = MaxWordLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
896newtype MinWordLength = MinWordLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
898{-| 'PhraseSlop' sets the default slop for phrases, 0 means exact
899 phrase matches. Default is 0.
900-}
901newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
902newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
903newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
905-- | Newtype wrapper to parse ES's concerning tendency to in some APIs return a floating point number of milliseconds since epoch ಠ_ಠ
906newtype POSIXMS = POSIXMS { posixMS :: UTCTime }
908{-| 'unpackId' is a silly convenience function that gets used once.
909-}
910unpackId :: DocId -> Text
911unpackId (DocId docId) = docId
913type TrackSortScores = Bool
914newtype From = From Int deriving (Eq, Show, Generic, ToJSON)
915newtype Size = Size Int deriving (Eq, Show, Generic, ToJSON)
917data Search = Search { queryBody :: Maybe Query
918 , filterBody :: Maybe Filter
919 , sortBody :: Maybe Sort
920 , aggBody :: Maybe Aggregations
921 , highlight :: Maybe Highlights
922 -- default False
923 , trackSortScores :: TrackSortScores
924 , from :: From
925 , size :: Size
926 , searchType :: SearchType
927 , fields :: Maybe [FieldName]
928 , source :: Maybe Source } deriving (Eq, Show, Generic, Typeable)
930data SearchType = SearchTypeQueryThenFetch
931 | SearchTypeDfsQueryThenFetch
932 | SearchTypeCount
933 | SearchTypeScan
934 | SearchTypeQueryAndFetch
935 | SearchTypeDfsQueryAndFetch
936 deriving (Eq, Show, Generic, Typeable)
938data Source =
939 NoSource
940 | SourcePatterns PatternOrPatterns
941 | SourceIncludeExclude Include Exclude
942 deriving (Show, Eq, Generic, Typeable)
944data PatternOrPatterns = PopPattern Pattern
945 | PopPatterns [Pattern] deriving (Eq, Show, Generic, Typeable)
947data Include = Include [Pattern] deriving (Eq, Show, Generic, Typeable)
948data Exclude = Exclude [Pattern] deriving (Eq, Show, Generic, Typeable)
950newtype Pattern = Pattern Text deriving (Eq, Show, Generic, Typeable)
952data Highlights = Highlights { globalsettings :: Maybe HighlightSettings
953 , highlightFields :: [FieldHighlight]
954 } deriving (Show, Eq, Generic, Typeable)
956data FieldHighlight = FieldHighlight FieldName (Maybe HighlightSettings)
957 deriving (Show, Eq, Generic, Typeable)
960data HighlightSettings = Plain PlainHighlight
961 | Postings PostingsHighlight
962 | FastVector FastVectorHighlight
963 deriving (Show, Eq, Generic, Typeable)
964data PlainHighlight =
965 PlainHighlight { plainCommon :: Maybe CommonHighlight
966 , plainNonPost :: Maybe NonPostings } deriving (Show, Eq, Generic, Typeable)
968 -- This requires that index_options are set to 'offset' in the mapping.
969data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Show, Eq, Generic, Typeable)
971-- This requires that term_vector is set to 'with_positions_offsets' in the mapping.
972data FastVectorHighlight =
973 FastVectorHighlight { fvCommon :: Maybe CommonHighlight
974 , fvNonPostSettings :: Maybe NonPostings
975 , boundaryChars :: Maybe Text
976 , boundaryMaxScan :: Maybe Int
977 , fragmentOffset :: Maybe Int
978 , matchedFields :: [Text]
979 , phraseLimit :: Maybe Int
980 } deriving (Show, Eq, Generic, Typeable)
982data CommonHighlight =
983 CommonHighlight { order :: Maybe Text
984 , forceSource :: Maybe Bool
985 , tag :: Maybe HighlightTag
986 , encoder :: Maybe HighlightEncoder
987 , noMatchSize :: Maybe Int
988 , highlightQuery :: Maybe Query
989 , requireFieldMatch :: Maybe Bool
990 } deriving (Show, Eq, Generic, Typeable)
992-- Settings that are only applicable to FastVector and Plain highlighters.
993data NonPostings =
994 NonPostings { fragmentSize :: Maybe Int
995 , numberOfFragments :: Maybe Int} deriving (Show, Eq, Generic, Typeable)
997data HighlightEncoder = DefaultEncoder
998 | HTMLEncoder
999 deriving (Show, Eq, Generic, Typeable)
1001-- NOTE: Should the tags use some kind of HTML type, rather than Text?
1002data HighlightTag = TagSchema Text
1003 | CustomTags ([Text], [Text]) -- Only uses more than the first value in the lists if fvh
1004 deriving (Show, Eq, Generic, Typeable)
1007data Query =
1008 TermQuery Term (Maybe Boost)
1009 | TermsQuery Text (NonEmpty Text)
1010 | QueryMatchQuery MatchQuery
1011 | QueryMultiMatchQuery MultiMatchQuery
1012 | QueryBoolQuery BoolQuery
1013 | QueryBoostingQuery BoostingQuery
1014 | QueryCommonTermsQuery CommonTermsQuery
1015 | ConstantScoreFilter Filter Boost
1016 | ConstantScoreQuery Query Boost
1017 | QueryDisMaxQuery DisMaxQuery
1018 | QueryFilteredQuery FilteredQuery
1019 | QueryFuzzyLikeThisQuery FuzzyLikeThisQuery
1020 | QueryFuzzyLikeFieldQuery FuzzyLikeFieldQuery
1021 | QueryFuzzyQuery FuzzyQuery
1022 | QueryHasChildQuery HasChildQuery
1023 | QueryHasParentQuery HasParentQuery
1024 | IdsQuery MappingName [DocId]
1025 | QueryIndicesQuery IndicesQuery
1026 | MatchAllQuery (Maybe Boost)
1027 | QueryMoreLikeThisQuery MoreLikeThisQuery
1028 | QueryMoreLikeThisFieldQuery MoreLikeThisFieldQuery
1029 | QueryNestedQuery NestedQuery
1030 | QueryPrefixQuery PrefixQuery
1031 | QueryQueryStringQuery QueryStringQuery
1032 | QuerySimpleQueryStringQuery SimpleQueryStringQuery
1033 | QueryRangeQuery RangeQuery
1034 | QueryRegexpQuery RegexpQuery
1035 deriving (Eq, Show, Generic, Typeable)
1037data RegexpQuery =
1038 RegexpQuery { regexpQueryField :: FieldName
1039 , regexpQuery :: Regexp
1040 , regexpQueryFlags :: RegexpFlags
1041 , regexpQueryBoost :: Maybe Boost
1042 } deriving (Eq, Show, Generic, Typeable)
1044data RangeQuery =
1045 RangeQuery { rangeQueryField :: FieldName
1046 , rangeQueryRange :: RangeValue
1047 , rangeQueryBoost :: Boost } deriving (Eq, Show, Generic, Typeable)
1049mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
1050mkRangeQuery f r = RangeQuery f r (Boost 1.0)
1052data SimpleQueryStringQuery =
1053 SimpleQueryStringQuery
1054 { simpleQueryStringQuery :: QueryString
1055 , simpleQueryStringField :: Maybe FieldOrFields
1056 , simpleQueryStringOperator :: Maybe BooleanOperator
1057 , simpleQueryStringAnalyzer :: Maybe Analyzer
1058 , simpleQueryStringFlags :: Maybe (NonEmpty SimpleQueryFlag)
1059 , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
1060 , simpleQueryStringLocale :: Maybe Locale
1061 } deriving (Eq, Show, Generic, Typeable)
1063data SimpleQueryFlag =
1064 SimpleQueryAll
1065 | SimpleQueryNone
1066 | SimpleQueryAnd
1067 | SimpleQueryOr
1068 | SimpleQueryPrefix
1069 | SimpleQueryPhrase
1070 | SimpleQueryPrecedence
1071 | SimpleQueryEscape
1072 | SimpleQueryWhitespace
1073 | SimpleQueryFuzzy
1074 | SimpleQueryNear
1075 | SimpleQuerySlop deriving (Eq, Show, Generic, Typeable)
1077-- use_dis_max and tie_breaker when fields are plural?
1078data QueryStringQuery =
1079 QueryStringQuery
1080 { queryStringQuery :: QueryString
1081 , queryStringDefaultField :: Maybe FieldName
1082 , queryStringOperator :: Maybe BooleanOperator
1083 , queryStringAnalyzer :: Maybe Analyzer
1084 , queryStringAllowLeadingWildcard :: Maybe AllowLeadingWildcard
1085 , queryStringLowercaseExpanded :: Maybe LowercaseExpanded
1086 , queryStringEnablePositionIncrements :: Maybe EnablePositionIncrements
1087 , queryStringFuzzyMaxExpansions :: Maybe MaxExpansions
1088 , queryStringFuzziness :: Maybe Fuzziness
1089 , queryStringFuzzyPrefixLength :: Maybe PrefixLength
1090 , queryStringPhraseSlop :: Maybe PhraseSlop
1091 , queryStringBoost :: Maybe Boost
1092 , queryStringAnalyzeWildcard :: Maybe AnalyzeWildcard
1093 , queryStringGeneratePhraseQueries :: Maybe GeneratePhraseQueries
1094 , queryStringMinimumShouldMatch :: Maybe MinimumMatch
1095 , queryStringLenient :: Maybe Lenient
1096 , queryStringLocale :: Maybe Locale
1097 } deriving (Eq, Show, Generic, Typeable)
1099mkQueryStringQuery :: QueryString -> QueryStringQuery
1100mkQueryStringQuery qs =
1101 QueryStringQuery qs Nothing Nothing
1102 Nothing Nothing Nothing Nothing
1103 Nothing Nothing Nothing Nothing
1104 Nothing Nothing Nothing Nothing
1105 Nothing Nothing
1107data FieldOrFields = FofField FieldName
1108 | FofFields (NonEmpty FieldName) deriving (Eq, Show, Generic, Typeable)
1110data PrefixQuery =
1111 PrefixQuery
1112 { prefixQueryField :: FieldName
1113 , prefixQueryPrefixValue :: Text
1114 , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show, Generic, Typeable)
1116data NestedQuery =
1117 NestedQuery
1118 { nestedQueryPath :: QueryPath
1119 , nestedQueryScoreType :: ScoreType
1120 , nestedQuery :: Query } deriving (Eq, Show, Generic, Typeable)
1122data MoreLikeThisFieldQuery =
1123 MoreLikeThisFieldQuery
1124 { moreLikeThisFieldText :: Text
1125 , moreLikeThisFieldFields :: FieldName
1126 -- default 0.3 (30%)
1127 , moreLikeThisFieldPercentMatch :: Maybe PercentMatch
1128 , moreLikeThisFieldMinimumTermFreq :: Maybe MinimumTermFrequency
1129 , moreLikeThisFieldMaxQueryTerms :: Maybe MaxQueryTerms
1130 , moreLikeThisFieldStopWords :: Maybe (NonEmpty StopWord)
1131 , moreLikeThisFieldMinDocFrequency :: Maybe MinDocFrequency
1132 , moreLikeThisFieldMaxDocFrequency :: Maybe MaxDocFrequency
1133 , moreLikeThisFieldMinWordLength :: Maybe MinWordLength
1134 , moreLikeThisFieldMaxWordLength :: Maybe MaxWordLength
1135 , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
1136 , moreLikeThisFieldBoost :: Maybe Boost
1137 , moreLikeThisFieldAnalyzer :: Maybe Analyzer
1138 } deriving (Eq, Show, Generic, Typeable)
1140data MoreLikeThisQuery =
1141 MoreLikeThisQuery
1142 { moreLikeThisText :: Text
1143 , moreLikeThisFields :: Maybe (NonEmpty FieldName)
1144 -- default 0.3 (30%)
1145 , moreLikeThisPercentMatch :: Maybe PercentMatch
1146 , moreLikeThisMinimumTermFreq :: Maybe MinimumTermFrequency
1147 , moreLikeThisMaxQueryTerms :: Maybe MaxQueryTerms
1148 , moreLikeThisStopWords :: Maybe (NonEmpty StopWord)
1149 , moreLikeThisMinDocFrequency :: Maybe MinDocFrequency
1150 , moreLikeThisMaxDocFrequency :: Maybe MaxDocFrequency
1151 , moreLikeThisMinWordLength :: Maybe MinWordLength
1152 , moreLikeThisMaxWordLength :: Maybe MaxWordLength
1153 , moreLikeThisBoostTerms :: Maybe BoostTerms
1154 , moreLikeThisBoost :: Maybe Boost
1155 , moreLikeThisAnalyzer :: Maybe Analyzer
1156 } deriving (Eq, Show, Generic, Typeable)
1158data IndicesQuery =
1159 IndicesQuery
1160 { indicesQueryIndices :: [IndexName]
1161 , indicesQuery :: Query
1162 -- default "all"
1163 , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show, Generic, Typeable)
1165data HasParentQuery =
1166 HasParentQuery
1167 { hasParentQueryType :: TypeName
1168 , hasParentQuery :: Query
1169 , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Generic, Typeable)
1171data HasChildQuery =
1172 HasChildQuery
1173 { hasChildQueryType :: TypeName
1174 , hasChildQuery :: Query
1175 , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Generic, Typeable)
1177data ScoreType =
1178 ScoreTypeMax
1179 | ScoreTypeSum
1180 | ScoreTypeAvg
1181 | ScoreTypeNone deriving (Eq, Show, Generic, Typeable)
1183data FuzzyQuery =
1184 FuzzyQuery { fuzzyQueryField :: FieldName
1185 , fuzzyQueryValue :: Text
1186 , fuzzyQueryPrefixLength :: PrefixLength
1187 , fuzzyQueryMaxExpansions :: MaxExpansions
1188 , fuzzyQueryFuzziness :: Fuzziness
1189 , fuzzyQueryBoost :: Maybe Boost
1190 } deriving (Eq, Show, Generic, Typeable)
1192data FuzzyLikeFieldQuery =
1193 FuzzyLikeFieldQuery
1194 { fuzzyLikeField :: FieldName
1195 -- anaphora is good for the soul.
1196 , fuzzyLikeFieldText :: Text
1197 , fuzzyLikeFieldMaxQueryTerms :: MaxQueryTerms
1198 , fuzzyLikeFieldIgnoreTermFrequency :: IgnoreTermFrequency
1199 , fuzzyLikeFieldFuzziness :: Fuzziness
1200 , fuzzyLikeFieldPrefixLength :: PrefixLength
1201 , fuzzyLikeFieldBoost :: Boost
1202 , fuzzyLikeFieldAnalyzer :: Maybe Analyzer
1203 } deriving (Eq, Show, Generic, Typeable)
1205data FuzzyLikeThisQuery =
1206 FuzzyLikeThisQuery
1207 { fuzzyLikeFields :: [FieldName]
1208 , fuzzyLikeText :: Text
1209 , fuzzyLikeMaxQueryTerms :: MaxQueryTerms
1210 , fuzzyLikeIgnoreTermFrequency :: IgnoreTermFrequency
1211 , fuzzyLikeFuzziness :: Fuzziness
1212 , fuzzyLikePrefixLength :: PrefixLength
1213 , fuzzyLikeBoost :: Boost
1214 , fuzzyLikeAnalyzer :: Maybe Analyzer
1215 } deriving (Eq, Show, Generic, Typeable)
1217data FilteredQuery =
1218 FilteredQuery
1219 { filteredQuery :: Query
1220 , filteredFilter :: Filter } deriving (Eq, Show, Generic, Typeable)
1222data DisMaxQuery =
1223 DisMaxQuery { disMaxQueries :: [Query]
1224 -- default 0.0
1225 , disMaxTiebreaker :: Tiebreaker
1226 , disMaxBoost :: Maybe Boost
1227 } deriving (Eq, Show, Generic, Typeable)
1229data MatchQuery =
1230 MatchQuery { matchQueryField :: FieldName
1231 , matchQueryQueryString :: QueryString
1232 , matchQueryOperator :: BooleanOperator
1233 , matchQueryZeroTerms :: ZeroTermsQuery
1234 , matchQueryCutoffFrequency :: Maybe CutoffFrequency
1235 , matchQueryMatchType :: Maybe MatchQueryType
1236 , matchQueryAnalyzer :: Maybe Analyzer
1237 , matchQueryMaxExpansions :: Maybe MaxExpansions
1238 , matchQueryLenient :: Maybe Lenient
1239 , matchQueryBoost :: Maybe Boost } deriving (Eq, Show, Generic, Typeable)
1241{-| 'mkMatchQuery' is a convenience function that defaults the less common parameters,
1242 enabling you to provide only the 'FieldName' and 'QueryString' to make a 'MatchQuery'
1244mkMatchQuery :: FieldName -> QueryString -> MatchQuery
1245mkMatchQuery field query = MatchQuery field query Or ZeroTermsNone Nothing Nothing Nothing Nothing Nothing Nothing
1247data MatchQueryType =
1248 MatchPhrase
1249 | MatchPhrasePrefix deriving (Eq, Show, Generic, Typeable)
1251data MultiMatchQuery =
1252 MultiMatchQuery { multiMatchQueryFields :: [FieldName]
1253 , multiMatchQueryString :: QueryString
1254 , multiMatchQueryOperator :: BooleanOperator
1255 , multiMatchQueryZeroTerms :: ZeroTermsQuery
1256 , multiMatchQueryTiebreaker :: Maybe Tiebreaker
1257 , multiMatchQueryType :: Maybe MultiMatchQueryType
1258 , multiMatchQueryCutoffFrequency :: Maybe CutoffFrequency
1259 , multiMatchQueryAnalyzer :: Maybe Analyzer
1260 , multiMatchQueryMaxExpansions :: Maybe MaxExpansions
1261 , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show, Generic, Typeable)
1263{-| 'mkMultiMatchQuery' is a convenience function that defaults the less common parameters,
1264 enabling you to provide only the list of 'FieldName's and 'QueryString' to
1265 make a 'MultiMatchQuery'.
1268mkMultiMatchQuery :: [FieldName] -> QueryString -> MultiMatchQuery
1269mkMultiMatchQuery matchFields query =
1270 MultiMatchQuery matchFields query
1271 Or ZeroTermsNone Nothing Nothing Nothing Nothing Nothing Nothing
1273data MultiMatchQueryType =
1274 MultiMatchBestFields
1275 | MultiMatchMostFields
1276 | MultiMatchCrossFields
1277 | MultiMatchPhrase
1278 | MultiMatchPhrasePrefix deriving (Eq, Show, Generic, Typeable)
1280data BoolQuery =
1281 BoolQuery { boolQueryMustMatch :: [Query]
1282 , boolQueryMustNotMatch :: [Query]
1283 , boolQueryShouldMatch :: [Query]
1284 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
1285 , boolQueryBoost :: Maybe Boost
1286 , boolQueryDisableCoord :: Maybe DisableCoord
1287 } deriving (Eq, Show, Generic, Typeable)
1289mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
1290mkBoolQuery must mustNot should =
1291 BoolQuery must mustNot should Nothing Nothing Nothing
1293data BoostingQuery =
1294 BoostingQuery { positiveQuery :: Query
1295 , negativeQuery :: Query
1296 , negativeBoost :: Boost } deriving (Eq, Show, Generic, Typeable)
1298data CommonTermsQuery =
1299 CommonTermsQuery { commonField :: FieldName
1300 , commonQuery :: QueryString
1301 , commonCutoffFrequency :: CutoffFrequency
1302 , commonLowFreqOperator :: BooleanOperator
1303 , commonHighFreqOperator :: BooleanOperator
1304 , commonMinimumShouldMatch :: Maybe CommonMinimumMatch
1305 , commonBoost :: Maybe Boost
1306 , commonAnalyzer :: Maybe Analyzer
1307 , commonDisableCoord :: Maybe DisableCoord
1308 } deriving (Eq, Show, Generic, Typeable)
1310data CommonMinimumMatch =
1311 CommonMinimumMatchHighLow MinimumMatchHighLow
1312 | CommonMinimumMatch MinimumMatch
1313 deriving (Eq, Show, Generic, Typeable)
1315data MinimumMatchHighLow =
1316 MinimumMatchHighLow { lowFreq :: MinimumMatch
1317 , highFreq :: MinimumMatch } deriving (Eq, Show, Generic, Typeable)
1319data Filter = AndFilter [Filter] Cache
1320 | OrFilter [Filter] Cache
1321 | NotFilter Filter Cache
1322 | IdentityFilter
1323 | BoolFilter BoolMatch
1324 | ExistsFilter FieldName -- always cached
1325 | GeoBoundingBoxFilter GeoBoundingBoxConstraint
1326 | GeoDistanceFilter GeoPoint Distance DistanceType OptimizeBbox Cache
1327 | GeoDistanceRangeFilter GeoPoint DistanceRange
1328 | GeoPolygonFilter FieldName [LatLon]
1329 | IdsFilter MappingName [DocId]
1330 | LimitFilter Int
1331 | MissingFilter FieldName Existence NullValue
1332 | PrefixFilter FieldName PrefixValue Cache
1333 | QueryFilter Query Cache
1334 | RangeFilter FieldName RangeValue RangeExecution Cache
1335 | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
1336 | TermFilter Term Cache
1337 deriving (Eq, Show, Generic, Typeable)
1339data ZeroTermsQuery = ZeroTermsNone
1340 | ZeroTermsAll deriving (Eq, Show, Generic, Typeable)
1342data RangeExecution = RangeExecutionIndex
1343 | RangeExecutionFielddata deriving (Eq, Show, Generic, Typeable)
1345newtype Regexp = Regexp Text deriving (Eq, Show, Generic, Typeable, FromJSON)
1347data RegexpFlags = AllRegexpFlags
1348 | NoRegexpFlags
1349 | SomeRegexpFlags (NonEmpty RegexpFlag) deriving (Eq, Show, Generic, Typeable)
1351data RegexpFlag = AnyString
1352 | Automaton
1353 | Complement
1354 | Empty
1355 | Intersection
1356 | Interval deriving (Eq, Show, Generic, Typeable)
1358newtype LessThan = LessThan Double deriving (Eq, Show, Generic, Typeable)
1359newtype LessThanEq = LessThanEq Double deriving (Eq, Show, Generic, Typeable)
1360newtype GreaterThan = GreaterThan Double deriving (Eq, Show, Generic, Typeable)
1361newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show, Generic, Typeable)
1363newtype LessThanD = LessThanD UTCTime deriving (Eq, Show, Generic, Typeable)
1364newtype LessThanEqD = LessThanEqD UTCTime deriving (Eq, Show, Generic, Typeable)
1365newtype GreaterThanD = GreaterThanD UTCTime deriving (Eq, Show, Generic, Typeable)
1366newtype GreaterThanEqD = GreaterThanEqD UTCTime deriving (Eq, Show, Generic, Typeable)
1368data RangeValue = RangeDateLte LessThanEqD
1369 | RangeDateLt LessThanD
1370 | RangeDateGte GreaterThanEqD
1371 | RangeDateGt GreaterThanD
1372 | RangeDateGtLt GreaterThanD LessThanD
1373 | RangeDateGteLte GreaterThanEqD LessThanEqD
1374 | RangeDateGteLt GreaterThanEqD LessThanD
1375 | RangeDateGtLte GreaterThanD LessThanEqD
1376 | RangeDoubleLte LessThanEq
1377 | RangeDoubleLt LessThan
1378 | RangeDoubleGte GreaterThanEq
1379 | RangeDoubleGt GreaterThan
1380 | RangeDoubleGtLt GreaterThan LessThan
1381 | RangeDoubleGteLte GreaterThanEq LessThanEq
1382 | RangeDoubleGteLt GreaterThanEq LessThan
1383 | RangeDoubleGtLte GreaterThan LessThanEq
1384 deriving (Eq, Show, Generic, Typeable)
1386rangeValueToPair :: RangeValue -> [Pair]
1387rangeValueToPair rv = case rv of
1388 RangeDateLte (LessThanEqD t) -> ["lte" .= t]
1389 RangeDateGte (GreaterThanEqD t) -> ["gte" .= t]
1390 RangeDateLt (LessThanD t) -> ["lt" .= t]
1391 RangeDateGt (GreaterThanD t) -> ["gt" .= t]
1392 RangeDateGteLte (GreaterThanEqD l) (LessThanEqD g) -> ["gte" .= l, "lte" .= g]
1393 RangeDateGtLte (GreaterThanD l) (LessThanEqD g) -> ["gt" .= l, "lte" .= g]
1394 RangeDateGteLt (GreaterThanEqD l) (LessThanD g) -> ["gte" .= l, "lt" .= g]
1395 RangeDateGtLt (GreaterThanD l) (LessThanD g) -> ["gt" .= l, "lt" .= g]
1396 RangeDoubleLte (LessThanEq t) -> ["lte" .= t]
1397 RangeDoubleGte (GreaterThanEq t) -> ["gte" .= t]
1398 RangeDoubleLt (LessThan t) -> ["lt" .= t]
1399 RangeDoubleGt (GreaterThan t) -> ["gt" .= t]
1400 RangeDoubleGteLte (GreaterThanEq l) (LessThanEq g) -> ["gte" .= l, "lte" .= g]
1401 RangeDoubleGtLte (GreaterThan l) (LessThanEq g) -> ["gt" .= l, "lte" .= g]
1402 RangeDoubleGteLt (GreaterThanEq l) (LessThan g) -> ["gte" .= l, "lt" .= g]
1403 RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
1405data Term = Term { termField :: Text
1406 , termValue :: Text } deriving (Eq, Show, Generic, Typeable)
1408data BoolMatch = MustMatch Term Cache
1409 | MustNotMatch Term Cache
1410 | ShouldMatch [Term] Cache deriving (Eq, Show, Generic, Typeable)
1412-- "memory" or "indexed"
1413data GeoFilterType = GeoFilterMemory
1414 | GeoFilterIndexed deriving (Eq, Show, Generic, Typeable)
1416data LatLon = LatLon { lat :: Double
1417 , lon :: Double } deriving (Eq, Show, Generic, Typeable)
1419data GeoBoundingBox =
1420 GeoBoundingBox { topLeft :: LatLon
1421 , bottomRight :: LatLon } deriving (Eq, Show, Generic, Typeable)
1423data GeoBoundingBoxConstraint =
1424 GeoBoundingBoxConstraint { geoBBField :: FieldName
1425 , constraintBox :: GeoBoundingBox
1426 , bbConstraintcache :: Cache
1427 , geoType :: GeoFilterType
1428 } deriving (Eq, Show, Generic, Typeable)
1430data GeoPoint =
1431 GeoPoint { geoField :: FieldName
1432 , latLon :: LatLon} deriving (Eq, Show, Generic, Typeable)
1434data DistanceUnit = Miles
1435 | Yards
1436 | Feet
1437 | Inches
1438 | Kilometers
1439 | Meters
1440 | Centimeters
1441 | Millimeters
1442 | NauticalMiles deriving (Eq, Show, Generic, Typeable)
1444data DistanceType = Arc
1445 | SloppyArc -- doesn't exist <1.0
1446 | Plane deriving (Eq, Show, Generic, Typeable)
1448data OptimizeBbox = OptimizeGeoFilterType GeoFilterType
1449 | NoOptimizeBbox deriving (Eq, Show, Generic, Typeable)
1451data Distance =
1452 Distance { coefficient :: Double
1453 , unit :: DistanceUnit } deriving (Eq, Show, Generic, Typeable)
1455data DistanceRange =
1456 DistanceRange { distanceFrom :: Distance
1457 , distanceTo :: Distance } deriving (Eq, Show, Generic, Typeable)
1459data SearchResult a =
1460 SearchResult { took :: Int
1461 , timedOut :: Bool
1462 , shards :: ShardResult
1463 , searchHits :: SearchHits a
1464 , aggregations :: Maybe AggregationResults
1465 , scrollId :: Maybe ScrollId } deriving (Eq, Show, Generic, Typeable)
1467newtype ScrollId = ScrollId Text deriving (Eq, Show, Generic, Ord, ToJSON, FromJSON)
1469type Score = Maybe Double
1471data SearchHits a =
1472 SearchHits { hitsTotal :: Int
1473 , maxScore :: Score
1474 , hits :: [Hit a] } deriving (Eq, Show, Generic, Typeable)
1477instance Monoid (SearchHits a) where
1478 mempty = SearchHits 0 Nothing mempty
1479 mappend (SearchHits ta ma ha) (SearchHits tb mb hb) =
1480 SearchHits (ta + tb) (max ma mb) (ha <> hb)
1483data Hit a =
1484 Hit { hitIndex :: IndexName
1485 , hitType :: MappingName
1486 , hitDocId :: DocId
1487 , hitScore :: Score
1488 , hitSource :: Maybe a
1489 , hitHighlight :: Maybe HitHighlight } deriving (Eq, Show, Generic, Typeable)
1491data ShardResult =
1492 ShardResult { shardTotal :: Int
1493 , shardsSuccessful :: Int
1494 , shardsFailed :: Int } deriving (Eq, Show, Generic, Typeable)
1496type HitHighlight = M.Map Text [Text]
1498showText :: Show a => a -> Text
1499showText = T.pack . show
1501readMay :: Read a => String -> Maybe a
1502readMay s = case reads s of
1503 (a, ""):_ -> Just a
1504 _ -> Nothing
1506parseReadText :: Read a => Text -> Parser a
1507parseReadText = maybe mzero return . readMay . T.unpack
1509type Aggregations = M.Map Text Aggregation
1511emptyAggregations :: Aggregations
1512emptyAggregations = M.empty
1514mkAggregations :: Text -> Aggregation -> Aggregations
1515mkAggregations name aggregation = M.insert name aggregation emptyAggregations
1517data TermOrder = TermOrder{ termSortField :: Text
1518 , termSortOrder :: SortOrder } deriving (Eq, Show, Generic, Typeable)
1520data TermInclusion = TermInclusion Text
1521 | TermPattern Text Text deriving (Eq, Show, Generic, Typeable)
1523data CollectionMode = BreadthFirst
1524 | DepthFirst deriving (Eq, Show, Generic, Typeable)
1526data ExecutionHint = Ordinals
1527 | GlobalOrdinals
1528 | GlobalOrdinalsHash
1529 | GlobalOrdinalsLowCardinality
1530 | Map deriving (Eq, Show, Generic, Typeable)
1532data TimeInterval = Weeks
1533 | Days
1534 | Hours
1535 | Minutes
1536 | Seconds deriving (Eq)
1538data Interval = Year
1539 | Quarter
1540 | Month
1541 | Week
1542 | Day
1543 | Hour
1544 | Minute
1545 | Second
1546 | FractionalInterval Float TimeInterval deriving (Eq, Show, Generic, Typeable)
1548data Aggregation = TermsAgg TermsAggregation
1549 | DateHistogramAgg DateHistogramAggregation
1550 | ValueCountAgg ValueCountAggregation
1551 | FilterAgg FilterAggregation
1552 | DateRangeAgg DateRangeAggregation deriving (Eq, Show, Generic, Typeable)
1555data TermsAggregation = TermsAggregation { term :: Either Text Text
1556 , termInclude :: Maybe TermInclusion
1557 , termExclude :: Maybe TermInclusion
1558 , termOrder :: Maybe TermOrder
1559 , termMinDocCount :: Maybe Int
1560 , termSize :: Maybe Int
1561 , termShardSize :: Maybe Int
1562 , termCollectMode :: Maybe CollectionMode
1563 , termExecutionHint :: Maybe ExecutionHint
1564 , termAggs :: Maybe Aggregations
1565 } deriving (Eq, Show, Generic, Typeable)
1567data DateHistogramAggregation = DateHistogramAggregation { dateField :: FieldName
1568 , dateInterval :: Interval
1569 , dateFormat :: Maybe Text
1570 -- pre and post deprecated in 1.5
1571 , datePreZone :: Maybe Text
1572 , datePostZone :: Maybe Text
1573 , datePreOffset :: Maybe Text
1574 , datePostOffset :: Maybe Text
1575 , dateAggs :: Maybe Aggregations
1576 } deriving (Eq, Show, Generic, Typeable)
1579data DateRangeAggregation = DateRangeAggregation { draField :: FieldName
1580 , draFormat :: Maybe Text
1581 , draRanges :: NonEmpty DateRangeAggRange
1582 } deriving (Eq, Show, Generic, Typeable)
1584data DateRangeAggRange = DateRangeFrom DateMathExpr
1585 | DateRangeTo DateMathExpr
1586 | DateRangeFromAndTo DateMathExpr DateMathExpr deriving (Eq, Show, Generic, Typeable)
1588-- | See <https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math> for more information.
1589data DateMathExpr = DateMathExpr DateMathAnchor [DateMathModifier] deriving (Eq, Show, Generic, Typeable)
1592-- | Starting point for a date range. This along with the 'DateMathModifiers' gets you the date ES will start from.
1593data DateMathAnchor = DMNow
1594 | DMDate Day deriving (Eq, Show, Generic, Typeable)
1596data DateMathModifier = AddTime Int DateMathUnit
1597 | SubtractTime Int DateMathUnit
1598 | RoundDownTo DateMathUnit deriving (Eq, Show, Generic, Typeable)
1600data DateMathUnit = DMYear
1601 | DMMonth
1602 | DMWeek
1603 | DMDay
1604 | DMHour
1605 | DMMinute
1606 | DMSecond deriving (Eq, Show, Generic, Typeable)
1608-- | See <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html> for more information.
1609data ValueCountAggregation = FieldValueCount FieldName
1610 | ScriptValueCount Script deriving (Eq, Show, Generic, Typeable)
1612-- | 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.
1613data FilterAggregation = FilterAggregation { faFilter :: Filter
1614 , faAggs :: Maybe Aggregations} deriving (Eq, Show, Generic, Typeable)
1616mkTermsAggregation :: Text -> TermsAggregation
1617mkTermsAggregation t = TermsAggregation (Left t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1619mkTermsScriptAggregation :: Text -> TermsAggregation
1620mkTermsScriptAggregation t = TermsAggregation (Right t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1622mkDateHistogram :: FieldName -> Interval -> DateHistogramAggregation
1623mkDateHistogram t i = DateHistogramAggregation t i Nothing Nothing Nothing Nothing Nothing Nothing
1625instance ToJSON Version where
1626 toJSON Version {..} = object ["number" .= number
1627 ,"build_hash" .= build_hash
1628 ,"build_timestamp" .= build_timestamp
1629 ,"build_snapshot" .= build_snapshot
1630 ,"lucene_version" .= lucene_version]
1632instance FromJSON Version where
1633 parseJSON = withObject "Version" parse
1634 where parse o = Version
1635 <$> o .: "number"
1636 <*> o .: "build_hash"
1637 <*> o .: "build_timestamp"
1638 <*> o .: "build_snapshot"
1639 <*> o .: "lucene_version"
1641instance ToJSON TermOrder where
1642 toJSON (TermOrder termSortField termSortOrder) = object [termSortField .= termSortOrder]
1644instance ToJSON TermInclusion where
1645 toJSON (TermInclusion x) = toJSON x
1646 toJSON (TermPattern pattern flags) = omitNulls [ "pattern" .= pattern,
1647 "flags" .= flags]
1649instance ToJSON CollectionMode where
1650 toJSON BreadthFirst = "breadth_first"
1651 toJSON DepthFirst = "depth_first"
1653instance ToJSON ExecutionHint where
1654 toJSON Ordinals = "ordinals"
1655 toJSON GlobalOrdinals = "global_ordinals"
1656 toJSON GlobalOrdinalsHash = "global_ordinals_hash"
1657 toJSON GlobalOrdinalsLowCardinality = "global_ordinals_low_cardinality"
1658 toJSON Map = "map"
1660instance ToJSON Interval where
1661 toJSON Year = "year"
1662 toJSON Quarter = "quarter"
1663 toJSON Month = "month"
1664 toJSON Week = "week"
1665 toJSON Day = "day"
1666 toJSON Hour = "hour"
1667 toJSON Minute = "minute"
1668 toJSON Second = "second"
1669 toJSON (FractionalInterval fraction interval) = toJSON $ show fraction ++ show interval
1671instance Show TimeInterval where
1672 show Weeks = "w"
1673 show Days = "d"
1674 show Hours = "h"
1675 show Minutes = "m"
1676 show Seconds = "s"
1678instance ToJSON Aggregation where
1679 toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint termAggs)) =
1680 omitNulls ["terms" .= omitNulls [ toJSON' term,
1681 "include" .= include,
1682 "exclude" .= exclude,
1683 "order" .= order,
1684 "min_doc_count" .= minDocCount,
1685 "size" .= size,
1686 "shard_size" .= shardSize,
1687 "collect_mode" .= collectMode,
1688 "execution_hint" .= executionHint
1689 ],
1690 "aggs" .= termAggs ]
1691 where
1692 toJSON' x = case x of { Left y -> "field" .= y; Right y -> "script" .= y }
1694 toJSON (DateHistogramAgg (DateHistogramAggregation field interval format preZone postZone preOffset postOffset dateHistoAggs)) =
1695 omitNulls ["date_histogram" .= omitNulls [ "field" .= field,
1696 "interval" .= interval,
1697 "format" .= format,
1698 "pre_zone" .= preZone,
1699 "post_zone" .= postZone,
1700 "pre_offset" .= preOffset,
1701 "post_offset" .= postOffset
1702 ],
1703 "aggs" .= dateHistoAggs ]
1704 toJSON (ValueCountAgg a) = object ["value_count" .= v]
1705 where v = case a of
1706 (FieldValueCount (FieldName n)) -> object ["field" .= n]
1707 (ScriptValueCount (Script s)) -> object ["script" .= s]
1708 toJSON (FilterAgg (FilterAggregation filt ags)) =
1709 omitNulls [ "filter" .= filt
1710 , "aggs" .= ags]
1711 toJSON (DateRangeAgg a) = object [ "date_range" .= a
1714instance ToJSON DateRangeAggregation where
1715 toJSON DateRangeAggregation {..} =
1716 omitNulls [ "field" .= draField
1717 , "format" .= draFormat
1718 , "ranges" .= toList draRanges
1721instance 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 ]
1726instance 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"
1745type AggregationResults = M.Map Text Value
1747class BucketAggregation a where
1748 key :: a -> Text
1749 docCount :: a -> Int
1750 aggs :: a -> Maybe AggregationResults
1753data Bucket a = Bucket { buckets :: [a]} deriving (Show)
1755data TermsResult = TermsResult { termKey :: Text
1756 , termsDocCount :: Int
1757 , termsAggs :: Maybe AggregationResults } deriving (Show)
1759data DateHistogramResult = DateHistogramResult { dateKey :: Int
1760 , dateKeyStr :: Maybe Text
1761 , dateDocCount :: Int
1762 , dateHistogramAggs :: Maybe AggregationResults } deriving (Show)
1764data 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)
1772toTerms :: Text -> AggregationResults -> Maybe (Bucket TermsResult)
1773toTerms t a = M.lookup t a >>= deserialize
1774 where deserialize = parseMaybe parseJSON
1776toDateHistogram :: Text -> AggregationResults -> Maybe (Bucket DateHistogramResult)
1777toDateHistogram t a = M.lookup t a >>= deserialize
1778 where deserialize = parseMaybe parseJSON
1780instance BucketAggregation TermsResult where
1781 key = termKey
1782 docCount = termsDocCount
1783 aggs = termsAggs
1785instance BucketAggregation DateHistogramResult where
1786 key = showText . dateKey
1787 docCount = dateDocCount
1788 aggs = dateHistogramAggs
1790instance BucketAggregation DateRangeResult where
1791 key = dateRangeKey
1792 docCount = dateRangeDocCount
1793 aggs = dateRangeAggs
1795instance (FromJSON a, BucketAggregation a) => FromJSON (Bucket a) where
1796 parseJSON (Object v) = Bucket <$>
1797 v .: "buckets"
1798 parseJSON _ = mempty
1800instance FromJSON TermsResult where
1801 parseJSON (Object v) = TermsResult <$>
1802 v .: "key" <*>
1803 v .: "doc_count" <*>
1804 v .:? "aggregations"
1805 parseJSON _ = mempty
1807instance FromJSON DateHistogramResult where
1808 parseJSON (Object v) = DateHistogramResult <$>
1809 v .: "key" <*>
1810 v .:? "key_as_string" <*>
1811 v .: "doc_count" <*>
1812 v .:? "aggregations"
1813 parseJSON _ = mempty
1815instance 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"
1826instance 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)))
1831instance Monoid Filter where
1832 mempty = IdentityFilter
1833 mappend a b = AndFilter [a, b] defaultCache
1835instance Seminearring Filter where
1836 a <||> b = OrFilter [a, b] defaultCache
1838instance ToJSON Filter where
1839 toJSON (AndFilter filters cache) =
1840 object ["and" .=
1841 object [ "filters" .= fmap toJSON filters
1842 , "_cache" .= cache]]
1844 toJSON (OrFilter filters cache) =
1845 object ["or" .=
1846 object [ "filters" .= fmap toJSON filters
1847 , "_cache" .= cache]]
1849 toJSON (NotFilter notFilter cache) =
1850 object ["not" .=
1851 object ["filter" .= notFilter
1852 , "_cache" .= cache]]
1854 toJSON (IdentityFilter) =
1855 object ["match_all" .= object []]
1857 toJSON (TermFilter (Term termFilterField termFilterValue) cache) =
1858 object ["term" .= object base]
1859 where base = [termFilterField .= termFilterValue,
1860 "_cache" .= cache]
1862 toJSON (ExistsFilter (FieldName fieldName)) =
1863 object ["exists" .= object
1864 ["field" .= fieldName]]
1866 toJSON (BoolFilter boolMatch) =
1867 object ["bool" .= boolMatch]
1869 toJSON (GeoBoundingBoxFilter bbConstraint) =
1870 object ["geo_bounding_box" .= bbConstraint]
1872 toJSON (GeoDistanceFilter (GeoPoint (FieldName distanceGeoField) geoDistLatLon)
1873 distance distanceType optimizeBbox cache) =
1874 object ["geo_distance" .=
1875 object ["distance" .= distance
1876 , "distance_type" .= distanceType
1877 , "optimize_bbox" .= optimizeBbox
1878 , distanceGeoField .= geoDistLatLon
1879 , "_cache" .= cache]]
1881 toJSON (GeoDistanceRangeFilter (GeoPoint (FieldName gddrField) drLatLon)
1882 (DistanceRange geoDistRangeDistFrom drDistanceTo)) =
1883 object ["geo_distance_range" .=
1884 object ["from" .= geoDistRangeDistFrom
1885 , "to" .= drDistanceTo
1886 , gddrField .= drLatLon]]
1888 toJSON (GeoPolygonFilter (FieldName geoPolygonFilterField) latLons) =
1889 object ["geo_polygon" .=
1890 object [geoPolygonFilterField .=
1891 object ["points" .= fmap toJSON latLons]]]
1893 toJSON (IdsFilter (MappingName mappingName) values) =
1894 object ["ids" .=
1895 object ["type" .= mappingName
1896 , "values" .= fmap unpackId values]]
1898 toJSON (LimitFilter limit) =
1899 object ["limit" .= object ["value" .= limit]]
1901 toJSON (MissingFilter (FieldName fieldName) (Existence existence) (NullValue nullValue)) =
1902 object ["missing" .=
1903 object ["field" .= fieldName
1904 , "existence" .= existence
1905 , "null_value" .= nullValue]]
1907 toJSON (PrefixFilter (FieldName fieldName) fieldValue cache) =
1908 object ["prefix" .=
1909 object [fieldName .= fieldValue
1910 , "_cache" .= cache]]
1912 toJSON (QueryFilter query False) =
1913 object ["query" .= toJSON query ]
1914 toJSON (QueryFilter query True) =
1915 object ["fquery" .=
1916 object [ "query" .= toJSON query
1917 , "_cache" .= True ]]
1919 toJSON (RangeFilter (FieldName fieldName) rangeValue rangeExecution cache) =
1920 object ["range" .=
1921 object [ fieldName .= object (rangeValueToPair rangeValue)
1922 , "execution" .= rangeExecution
1923 , "_cache" .= cache]]
1925 toJSON (RegexpFilter (FieldName fieldName)
1926 (Regexp regexText) flags (CacheName cacheName) cache (CacheKey cacheKey)) =
1927 object ["regexp" .=
1928 object [fieldName .=
1929 object ["value" .= regexText
1930 , "flags" .= flags]
1931 , "_name" .= cacheName
1932 , "_cache" .= cache
1933 , "_cache_key" .= cacheKey]]
1935instance FromJSON Filter where
1936 parseJSON = withObject "Filter" parse
1937 where parse o = andFilter `taggedWith` "and"
1938 <|> orFilter `taggedWith` "or"
1939 <|> notFilter `taggedWith` "not"
1940 <|> identityFilter `taggedWith` "match_all"
1941 <|> boolFilter `taggedWith` "bool"
1942 <|> existsFilter `taggedWith` "exists"
1943 <|> geoBoundingBoxFilter `taggedWith` "geo_bounding_box"
1944 <|> geoDistanceFilter `taggedWith` "geo_distance"
1945 <|> geoDistanceRangeFilter `taggedWith` "geo_distance_range"
1946 <|> geoPolygonFilter `taggedWith` "geo_polygon"
1947 <|> idsFilter `taggedWith` "ids"
1948 <|> limitFilter `taggedWith` "limit"
1949 <|> missingFilter `taggedWith` "missing"
1950 <|> prefixFilter `taggedWith` "prefix"
1951 <|> queryFilter `taggedWith` "query"
1952 <|> fqueryFilter `taggedWith` "fquery"
1953 <|> rangeFilter `taggedWith` "range"
1954 <|> regexpFilter `taggedWith` "regexp"
1955 <|> termFilter `taggedWith` "term"
1956 where taggedWith parser k = parser =<< o .: k
1957 andFilter o = AndFilter <$> o .: "filters"
1958 <*> o .:? "_cache" .!= defaultCache
1959 orFilter o = OrFilter <$> o .: "filters"
1960 <*> o .:? "_cache" .!= defaultCache
1961 notFilter o = NotFilter <$> o .: "filter"
1962 <*> o .: "_cache" .!= defaultCache
1963 identityFilter :: Object -> Parser Filter
1964 identityFilter m
1965 | HM.null m = pure IdentityFilter
1966 | otherwise = fail ("Identityfilter expected empty object but got " <> show m)
1967 boolFilter = pure . BoolFilter
1968 existsFilter o = ExistsFilter <$> o .: "field"
1969 geoBoundingBoxFilter = pure . GeoBoundingBoxFilter
1970 geoDistanceFilter o = do
1971 case HM.toList (deleteSeveral ["distance", "distance_type", "optimize_bbox", "_cache"] o) of
1972 [(fn, v)] -> do
1973 gp <- GeoPoint (FieldName fn) <$> parseJSON v
1974 GeoDistanceFilter gp <$> o .: "distance"
1975 <*> o .: "distance_type"
1976 <*> o .: "optimize_bbox"
1977 <*> o .:? "_cache" .!= defaultCache
1978 _ -> fail "Could not find GeoDistanceFilter field name"
1979 geoDistanceRangeFilter o = do
1980 case HM.toList (deleteSeveral ["from", "to"] o) of
1981 [(fn, v)] -> do
1982 gp <- GeoPoint (FieldName fn) <$> parseJSON v
1983 rng <- DistanceRange <$> o .: "from" <*> o .: "to"
1984 return (GeoDistanceRangeFilter gp rng)
1985 _ -> fail "Could not find GeoDistanceRangeFilter field name"
1986 geoPolygonFilter = fieldTagged $ \fn o -> GeoPolygonFilter fn <$> o .: "points"
1987 idsFilter o = IdsFilter <$> o .: "type"
1988 <*> o .: "values"
1989 limitFilter o = LimitFilter <$> o .: "value"
1990 missingFilter o = MissingFilter <$> o .: "field"
1991 <*> o .: "existence"
1992 <*> o .: "null_value"
1993 prefixFilter o = case HM.toList (HM.delete "_cache" o) of
1994 [(fn, String v)] -> PrefixFilter (FieldName fn) v <$> o .:? "_cache" .!= defaultCache
1995 _ -> fail "Could not parse PrefixFilter"
1997 queryFilter q = pure (QueryFilter q False)
1998 fqueryFilter o = QueryFilter <$> o .: "query" <*> pure True
1999 rangeFilter o = case HM.toList (deleteSeveral ["execution", "_cache"] o) of
2000 [(fn, v)] -> RangeFilter (FieldName fn)
2001 <$> parseJSON v
2002 <*> o .: "execution"
2003 <*> o .:? "_cache" .!= defaultCache
2004 _ -> fail "Could not find field name for RangeFilter"
2005 regexpFilter o = case HM.toList (deleteSeveral ["_name", "_cache", "_cache_key"] o) of
2006 [(fn, Object o')] -> RegexpFilter (FieldName fn)
2007 <$> o' .: "value"
2008 <*> o' .: "flags"
2009 <*> o .: "_name"
2010 <*> o .:? "_cache" .!= defaultCache
2011 <*> o .: "_cache_key"
2012 _ -> fail "Could not find field name for RegexpFilter"
2013 termFilter o = case HM.toList (HM.delete "_cache" o) of
2014 [(termField, String termVal)] -> TermFilter (Term termField termVal)
2015 <$> o .:? "_cache" .!= defaultCache
2016 _ -> fail "Could not find term field for TermFilter"
2018fieldTagged :: Monad m => (FieldName -> Object -> m a) -> Object -> m a
2019fieldTagged f o = case HM.toList o of
2020 [(k, Object o')] -> f (FieldName k) o'
2021 _ -> fail "Expected object with 1 field-named key"
2023instance ToJSON GeoPoint where
2024 toJSON (GeoPoint (FieldName geoPointField) geoPointLatLon) =
2025 object [ geoPointField .= geoPointLatLon ]
2028instance ToJSON Query where
2029 toJSON (TermQuery (Term termQueryField termQueryValue) boost) =
2030 object [ "term" .=
2031 object [termQueryField .= object merged]]
2032 where
2033 base = [ "value" .= termQueryValue ]
2034 boosted = maybe [] (return . ("boost" .=)) boost
2035 merged = mappend base boosted
2037 toJSON (TermsQuery fieldName terms) =
2038 object [ "terms" .= object conjoined ]
2039 where conjoined = [fieldName .= terms]
2040 toJSON (IdsQuery idsQueryMappingName docIds) =
2041 object [ "ids" .= object conjoined ]
2042 where conjoined = [ "type" .= idsQueryMappingName
2043 , "values" .= fmap toJSON docIds ]
2045 toJSON (QueryQueryStringQuery qQueryStringQuery) =
2046 object [ "query_string" .= qQueryStringQuery ]
2048 toJSON (QueryMatchQuery matchQuery) =
2049 object [ "match" .= matchQuery ]
2051 toJSON (QueryMultiMatchQuery multiMatchQuery) =
2052 toJSON multiMatchQuery
2054 toJSON (QueryBoolQuery boolQuery) =
2055 object [ "bool" .= boolQuery ]
2057 toJSON (QueryBoostingQuery boostingQuery) =
2058 object [ "boosting" .= boostingQuery ]
2060 toJSON (QueryCommonTermsQuery commonTermsQuery) =
2061 object [ "common" .= commonTermsQuery ]
2063 toJSON (ConstantScoreFilter csFilter boost) =
2064 object ["constant_score" .= object ["filter" .= csFilter
2065 , "boost" .= boost]]
2067 toJSON (ConstantScoreQuery query boost) =
2068 object ["constant_score" .= object ["query" .= query
2069 , "boost" .= boost]]
2071 toJSON (QueryDisMaxQuery disMaxQuery) =
2072 object [ "dis_max" .= disMaxQuery ]
2074 toJSON (QueryFilteredQuery qFilteredQuery) =
2075 object [ "filtered" .= qFilteredQuery ]
2077 toJSON (QueryFuzzyLikeThisQuery fuzzyQuery) =
2078 object [ "fuzzy_like_this" .= fuzzyQuery ]
2080 toJSON (QueryFuzzyLikeFieldQuery fuzzyFieldQuery) =
2081 object [ "fuzzy_like_this_field" .= fuzzyFieldQuery ]
2083 toJSON (QueryFuzzyQuery fuzzyQuery) =
2084 object [ "fuzzy" .= fuzzyQuery ]
2086 toJSON (QueryHasChildQuery childQuery) =
2087 object [ "has_child" .= childQuery ]
2089 toJSON (QueryHasParentQuery parentQuery) =
2090 object [ "has_parent" .= parentQuery ]
2092 toJSON (QueryIndicesQuery qIndicesQuery) =
2093 object [ "indices" .= qIndicesQuery ]
2095 toJSON (MatchAllQuery boost) =
2096 object [ "match_all" .= omitNulls [ "boost" .= boost ] ]
2098 toJSON (QueryMoreLikeThisQuery query) =
2099 object [ "more_like_this" .= query ]
2101 toJSON (QueryMoreLikeThisFieldQuery query) =
2102 object [ "more_like_this_field" .= query ]
2104 toJSON (QueryNestedQuery query) =
2105 object [ "nested" .= query ]
2107 toJSON (QueryPrefixQuery query) =
2108 object [ "prefix" .= query ]
2110 toJSON (QueryRangeQuery query) =
2111 object [ "range" .= query ]
2113 toJSON (QueryRegexpQuery query) =
2114 object [ "regexp" .= query ]
2116 toJSON (QuerySimpleQueryStringQuery query) =
2117 object [ "simple_query_string" .= query ]
2119instance FromJSON Query where
2120 parseJSON v = withObject "Query" parse v
2121 where parse o = termQuery `taggedWith` "term"
2122 <|> termsQuery `taggedWith` "terms"
2123 <|> idsQuery `taggedWith` "ids"
2124 <|> queryQueryStringQuery `taggedWith` "query_string"
2125 <|> queryMatchQuery `taggedWith` "match"
2126 <|> queryMultiMatchQuery
2127 <|> queryBoolQuery `taggedWith` "bool"
2128 <|> queryBoostingQuery `taggedWith` "boosting"
2129 <|> queryCommonTermsQuery `taggedWith` "common"
2130 <|> constantScoreFilter `taggedWith` "constant_score"
2131 <|> constantScoreQuery `taggedWith` "constant_score"
2132 <|> queryDisMaxQuery `taggedWith` "dis_max"
2133 <|> queryFilteredQuery `taggedWith` "filtered"
2134 <|> queryFuzzyLikeThisQuery `taggedWith` "fuzzy_like_this"
2135 <|> queryFuzzyLikeFieldQuery `taggedWith` "fuzzy_like_this_field"
2136 <|> queryFuzzyQuery `taggedWith` "fuzzy"
2137 <|> queryHasChildQuery `taggedWith` "has_child"
2138 <|> queryHasParentQuery `taggedWith` "has_parent"
2139 <|> queryIndicesQuery `taggedWith` "indices"
2140 <|> matchAllQuery `taggedWith` "match_all"
2141 <|> queryMoreLikeThisQuery `taggedWith` "more_like_this"
2142 <|> queryMoreLikeThisFieldQuery `taggedWith` "more_like_this_field"
2143 <|> queryNestedQuery `taggedWith` "nested"
2144 <|> queryPrefixQuery `taggedWith` "prefix"
2145 <|> queryRangeQuery `taggedWith` "range"
2146 <|> queryRegexpQuery `taggedWith` "regexp"
2147 <|> querySimpleQueryStringQuery `taggedWith` "simple_query_string"
2148 where taggedWith parser k = parser =<< o .: k
2149 termQuery = fieldTagged $ \(FieldName fn) o ->
2150 TermQuery <$> (Term fn <$> o .: "value") <*> o .:? "boost"
2151 termsQuery o = case HM.toList o of
2152 [(fn, vs)] -> do vals <- parseJSON vs
2153 case vals of
2154 x:xs -> return (TermsQuery fn (x :| xs))
2155 _ -> fail "Expected non empty list of values"
2156 _ -> fail "Expected object with 1 field-named key"
2157 idsQuery o = IdsQuery <$> o .: "type"
2158 <*> o .: "values"
2159 queryQueryStringQuery = pure . QueryQueryStringQuery
2160 queryMatchQuery = pure . QueryMatchQuery
2161 queryMultiMatchQuery = QueryMultiMatchQuery <$> parseJSON v
2162 queryBoolQuery = pure . QueryBoolQuery
2163 queryBoostingQuery = pure . QueryBoostingQuery
2164 queryCommonTermsQuery = pure . QueryCommonTermsQuery
2165 constantScoreFilter o = case HM.lookup "filter" o of
2166 Just x -> ConstantScoreFilter <$> parseJSON x
2167 <*> o .: "boost"
2168 _ -> fail "Does not appear to be a ConstantScoreFilter"
2169 constantScoreQuery o = case HM.lookup "query" o of
2170 Just x -> ConstantScoreQuery <$> parseJSON x
2171 <*> o .: "boost"
2172 _ -> fail "Does not appear to be a ConstantScoreQuery"
2173 queryDisMaxQuery = pure . QueryDisMaxQuery
2174 queryFilteredQuery = pure . QueryFilteredQuery
2175 queryFuzzyLikeThisQuery = pure . QueryFuzzyLikeThisQuery
2176 queryFuzzyLikeFieldQuery = pure . QueryFuzzyLikeFieldQuery
2177 queryFuzzyQuery = pure . QueryFuzzyQuery
2178 queryHasChildQuery = pure . QueryHasChildQuery
2179 queryHasParentQuery = pure . QueryHasParentQuery
2180 queryIndicesQuery = pure . QueryIndicesQuery
2181 matchAllQuery o = MatchAllQuery <$> o .:? "boost"
2182 queryMoreLikeThisQuery = pure . QueryMoreLikeThisQuery
2183 queryMoreLikeThisFieldQuery = pure . QueryMoreLikeThisFieldQuery
2184 queryNestedQuery = pure . QueryNestedQuery
2185 queryPrefixQuery = pure . QueryPrefixQuery
2186 queryRangeQuery = pure . QueryRangeQuery
2187 queryRegexpQuery = pure . QueryRegexpQuery
2188 querySimpleQueryStringQuery = pure . QuerySimpleQueryStringQuery
2191omitNulls :: [(Text, Value)] -> Value
2192omitNulls = object . filter notNull where
2193 notNull (_, Null) = False
2194 notNull (_, Array a) = (not . V.null) a
2195 notNull _ = True
2198instance ToJSON SimpleQueryStringQuery where
2199 toJSON SimpleQueryStringQuery {..} =
2200 omitNulls (base ++ maybeAdd)
2201 where base = [ "query" .= simpleQueryStringQuery ]
2202 maybeAdd = [ "fields" .= simpleQueryStringField
2203 , "default_operator" .= simpleQueryStringOperator
2204 , "analyzer" .= simpleQueryStringAnalyzer
2205 , "flags" .= simpleQueryStringFlags
2206 , "lowercase_expanded_terms" .= simpleQueryStringLowercaseExpanded
2207 , "locale" .= simpleQueryStringLocale ]
2209instance FromJSON SimpleQueryStringQuery where
2210 parseJSON = withObject "SimpleQueryStringQuery" parse
2211 where parse o = SimpleQueryStringQuery <$> o .: "query"
2212 <*> o .:? "fields"
2213 <*> o .:? "default_operator"
2214 <*> o .:? "analyzer"
2215 <*> (parseFlags <$> o .:? "flags")
2216 <*> o .:? "lowercase_expanded_terms"
2217 <*> o .:? "locale"
2218 parseFlags (Just (x:xs)) = Just (x :| xs)
2219 parseFlags _ = Nothing
2221instance ToJSON FieldOrFields where
2222 toJSON (FofField fieldName) =
2223 toJSON fieldName
2224 toJSON (FofFields fieldNames) =
2225 toJSON fieldNames
2227instance FromJSON FieldOrFields where
2228 parseJSON v = FofField <$> parseJSON v
2229 <|> FofFields <$> (parseNEJSON =<< parseJSON v)
2231instance ToJSON SimpleQueryFlag where
2232 toJSON SimpleQueryAll = "ALL"
2233 toJSON SimpleQueryNone = "NONE"
2234 toJSON SimpleQueryAnd = "AND"
2235 toJSON SimpleQueryOr = "OR"
2236 toJSON SimpleQueryPrefix = "PREFIX"
2237 toJSON SimpleQueryPhrase = "PHRASE"
2238 toJSON SimpleQueryPrecedence = "PRECEDENCE"
2239 toJSON SimpleQueryEscape = "ESCAPE"
2240 toJSON SimpleQueryWhitespace = "WHITESPACE"
2241 toJSON SimpleQueryFuzzy = "FUZZY"
2242 toJSON SimpleQueryNear = "NEAR"
2243 toJSON SimpleQuerySlop = "SLOP"
2245instance FromJSON SimpleQueryFlag where
2246 parseJSON = withText "SimpleQueryFlag" parse
2247 where parse "ALL" = pure SimpleQueryAll
2248 parse "NONE" = pure SimpleQueryNone
2249 parse "AND" = pure SimpleQueryAnd
2250 parse "OR" = pure SimpleQueryOr
2251 parse "PREFIX" = pure SimpleQueryPrefix
2252 parse "PHRASE" = pure SimpleQueryPhrase
2253 parse "PRECEDENCE" = pure SimpleQueryPrecedence
2254 parse "ESCAPE" = pure SimpleQueryEscape
2255 parse "WHITESPACE" = pure SimpleQueryWhitespace
2256 parse "FUZZY" = pure SimpleQueryFuzzy
2257 parse "NEAR" = pure SimpleQueryNear
2258 parse "SLOP" = pure SimpleQuerySlop
2259 parse f = fail ("Unexpected SimpleQueryFlag: " <> show f)
2261instance ToJSON RegexpQuery where
2262 toJSON (RegexpQuery (FieldName rqQueryField)
2263 (Regexp regexpQueryQuery) rqQueryFlags
2264 rqQueryBoost) =
2265 object [ rqQueryField .= omitNulls base ]
2266 where base = [ "value" .= regexpQueryQuery
2267 , "flags" .= rqQueryFlags
2268 , "boost" .= rqQueryBoost ]
2270instance FromJSON RegexpQuery where
2271 parseJSON = withObject "RegexpQuery" parse
2272 where parse = fieldTagged $ \fn o ->
2273 RegexpQuery fn
2274 <$> o .: "value"
2275 <*> o .: "flags"
2276 <*> o .:? "boost"
2278instance ToJSON QueryStringQuery where
2279 toJSON (QueryStringQuery qsQueryString
2280 qsDefaultField qsOperator
2281 qsAnalyzer qsAllowWildcard
2282 qsLowercaseExpanded qsEnablePositionIncrements
2283 qsFuzzyMaxExpansions qsFuzziness
2284 qsFuzzyPrefixLength qsPhraseSlop
2285 qsBoost qsAnalyzeWildcard
2286 qsGeneratePhraseQueries qsMinimumShouldMatch
2287 qsLenient qsLocale) =
2288 omitNulls base
2289 where
2290 base = [ "query" .= qsQueryString
2291 , "default_field" .= qsDefaultField
2292 , "default_operator" .= qsOperator
2293 , "analyzer" .= qsAnalyzer
2294 , "allow_leading_wildcard" .= qsAllowWildcard
2295 , "lowercase_expanded_terms" .= qsLowercaseExpanded
2296 , "enable_position_increments" .= qsEnablePositionIncrements
2297 , "fuzzy_max_expansions" .= qsFuzzyMaxExpansions
2298 , "fuzziness" .= qsFuzziness
2299 , "fuzzy_prefix_length" .= qsFuzzyPrefixLength
2300 , "phrase_slop" .= qsPhraseSlop
2301 , "boost" .= qsBoost
2302 , "analyze_wildcard" .= qsAnalyzeWildcard
2303 , "auto_generate_phrase_queries" .= qsGeneratePhraseQueries
2304 , "minimum_should_match" .= qsMinimumShouldMatch
2305 , "lenient" .= qsLenient
2306 , "locale" .= qsLocale ]
2308instance FromJSON QueryStringQuery where
2309 parseJSON = withObject "QueryStringQuery" parse
2310 where parse o = QueryStringQuery
2311 <$> o .: "query"
2312 <*> o .:? "default_field"
2313 <*> o .:? "default_operator"
2314 <*> o .:? "analyzer"
2315 <*> o .:? "allow_leading_wildcard"
2316 <*> o .:? "lowercase_expanded_terms"
2317 <*> o .:? "enable_position_increments"
2318 <*> o .:? "fuzzy_max_expansions"
2319 <*> o .:? "fuzziness"
2320 <*> o .:? "fuzzy_prefix_length"
2321 <*> o .:? "phrase_slop"
2322 <*> o .:? "boost"
2323 <*> o .:? "analyze_wildcard"
2324 <*> o .:? "auto_generate_phrase_queries"
2325 <*> o .:? "minimum_should_match"
2326 <*> o .:? "lenient"
2327 <*> o .:? "locale"
2329instance ToJSON RangeQuery where
2330 toJSON (RangeQuery (FieldName fieldName) range boost) =
2331 object [ fieldName .= object conjoined ]
2332 where conjoined = [ "boost" .= boost ] ++ (rangeValueToPair range)
2334instance FromJSON RangeQuery where
2335 parseJSON = withObject "RangeQuery" parse
2336 where parse = fieldTagged $ \fn o ->
2337 RangeQuery fn
2338 <$> parseJSON (Object o)
2339 <*> o .: "boost"
2341instance FromJSON RangeValue where
2342 parseJSON = withObject "RangeValue" parse
2343 where parse o = parseDate o
2344 <|> parseDouble o
2345 parseDate o = do lt <- o .:? "lt"
2346 lte <- o .:? "lte"
2347 gt <- o .:? "gt"
2348 gte <- o .:? "gte"
2349 case (lt, lte, gt, gte) of
2350 (Just a, _, Just b, _) -> return (RangeDateGtLt (GreaterThanD b) (LessThanD a))
2351 (Just a, _, _, Just b)-> return (RangeDateGteLt (GreaterThanEqD b) (LessThanD a))
2352 (_, Just a, Just b, _)-> return (RangeDateGtLte (GreaterThanD b) (LessThanEqD a))
2353 (_, Just a, _, Just b)-> return (RangeDateGteLte (GreaterThanEqD b) (LessThanEqD a))
2354 (_, _, Just a, _)-> return (RangeDateGt (GreaterThanD a))
2355 (Just a, _, _, _)-> return (RangeDateLt (LessThanD a))
2356 (_, _, _, Just a)-> return (RangeDateGte (GreaterThanEqD a))
2357 (_, Just a, _, _)-> return (RangeDateLte (LessThanEqD a))
2358 (Nothing, Nothing, Nothing, Nothing) -> mzero
2359 parseDouble o = do lt <- o .:? "lt"
2360 lte <- o .:? "lte"
2361 gt <- o .:? "gt"
2362 gte <- o .:? "gte"
2363 case (lt, lte, gt, gte) of
2364 (Just a, _, Just b, _) -> return (RangeDoubleGtLt (GreaterThan b) (LessThan a))
2365 (Just a, _, _, Just b)-> return (RangeDoubleGteLt (GreaterThanEq b) (LessThan a))
2366 (_, Just a, Just b, _)-> return (RangeDoubleGtLte (GreaterThan b) (LessThanEq a))
2367 (_, Just a, _, Just b)-> return (RangeDoubleGteLte (GreaterThanEq b) (LessThanEq a))
2368 (_, _, Just a, _)-> return (RangeDoubleGt (GreaterThan a))
2369 (Just a, _, _, _)-> return (RangeDoubleLt (LessThan a))
2370 (_, _, _, Just a)-> return (RangeDoubleGte (GreaterThanEq a))
2371 (_, Just a, _, _)-> return (RangeDoubleLte (LessThanEq a))
2372 (Nothing, Nothing, Nothing, Nothing) -> mzero
2374instance ToJSON PrefixQuery where
2375 toJSON (PrefixQuery (FieldName fieldName) queryValue boost) =
2376 object [ fieldName .= omitNulls base ]
2377 where base = [ "value" .= queryValue
2378 , "boost" .= boost ]
2380instance FromJSON PrefixQuery where
2381 parseJSON = withObject "PrefixQuery" parse
2382 where parse = fieldTagged $ \fn o ->
2383 PrefixQuery fn
2384 <$> o .: "value"
2385 <*> o .:? "boost"
2387instance ToJSON NestedQuery where
2388 toJSON (NestedQuery nqPath nqScoreType nqQuery) =
2389 object [ "path" .= nqPath
2390 , "score_mode" .= nqScoreType
2391 , "query" .= nqQuery ]
2393instance FromJSON NestedQuery where
2394 parseJSON = withObject "NestedQuery" parse
2395 where parse o = NestedQuery
2396 <$> o .: "path"
2397 <*> o .: "score_mode"
2398 <*> o .: "query"
2400instance ToJSON MoreLikeThisFieldQuery where
2401 toJSON (MoreLikeThisFieldQuery text (FieldName fieldName)
2402 percent mtf mqt stopwords mindf maxdf
2403 minwl maxwl boostTerms boost analyzer) =
2404 object [ fieldName .= omitNulls base ]
2405 where base = [ "like_text" .= text
2406 , "percent_terms_to_match" .= percent
2407 , "min_term_freq" .= mtf
2408 , "max_query_terms" .= mqt
2409 , "stop_words" .= stopwords
2410 , "min_doc_freq" .= mindf
2411 , "max_doc_freq" .= maxdf
2412 , "min_word_length" .= minwl
2413 , "max_word_length" .= maxwl
2414 , "boost_terms" .= boostTerms
2415 , "boost" .= boost
2416 , "analyzer" .= analyzer ]
2418instance FromJSON MoreLikeThisFieldQuery where
2419 parseJSON = withObject "MoreLikeThisFieldQuery" parse
2420 where parse = fieldTagged $ \fn o ->
2421 MoreLikeThisFieldQuery
2422 <$> o .: "like_text"
2423 <*> pure fn
2424 <*> o .:? "percent_terms_to_match"
2425 <*> o .:? "min_term_freq"
2426 <*> o .:? "max_query_terms"
2427 <*> (optionalNE =<< o .:? "stop_words")
2428 <*> o .:? "min_doc_freq"
2429 <*> o .:? "max_doc_freq"
2430 <*> o .:? "min_word_length"
2431 <*> o .:? "max_word_length"
2432 <*> o .:? "boost_terms"
2433 <*> o .:? "boost"
2434 <*> o .:? "analyzer"
2435 optionalNE = maybe (pure Nothing) (fmap Just . parseNEJSON)
2437instance ToJSON MoreLikeThisQuery where
2438 toJSON (MoreLikeThisQuery text fields percent
2439 mtf mqt stopwords mindf maxdf
2440 minwl maxwl boostTerms boost analyzer) =
2441 omitNulls base
2442 where base = [ "like_text" .= text
2443 , "fields" .= fields
2444 , "percent_terms_to_match" .= percent
2445 , "min_term_freq" .= mtf
2446 , "max_query_terms" .= mqt
2447 , "stop_words" .= stopwords
2448 , "min_doc_freq" .= mindf
2449 , "max_doc_freq" .= maxdf
2450 , "min_word_length" .= minwl
2451 , "max_word_length" .= maxwl
2452 , "boost_terms" .= boostTerms
2453 , "boost" .= boost
2454 , "analyzer" .= analyzer ]
2456instance FromJSON MoreLikeThisQuery where
2457 parseJSON = withObject "MoreLikeThisQuery" parse
2458 where parse o = MoreLikeThisQuery
2459 <$> o .: "like_text"
2460 <*> (optionalNE =<< o .:? "fields")
2461 <*> o .:? "percent_terms_to_match"
2462 <*> o .:? "min_term_freq"
2463 <*> o .:? "max_query_terms"
2464 <*> (optionalNE =<< o .:? "stop_words")
2465 <*> o .:? "min_doc_freq"
2466 <*> o .:? "max_doc_freq"
2467 <*> o .:? "min_word_length"
2468 <*> o .:? "max_word_length"
2469 <*> o .:? "boost_terms"
2470 <*> o .:? "boost"
2471 <*> o .:? "analyzer"
2472 optionalNE = maybe (pure Nothing) (fmap Just . parseNEJSON)
2474instance ToJSON IndicesQuery where
2475 toJSON (IndicesQuery indices query noMatch) =
2476 omitNulls [ "indices" .= indices
2477 , "no_match_query" .= noMatch
2478 , "query" .= query ]
2480instance FromJSON IndicesQuery where
2481 parseJSON = withObject "IndicesQuery" parse
2482 where parse o = IndicesQuery
2483 <$> o .:? "indices" .!= []
2484 <*> o .: "query"
2485 <*> o .:? "no_match_query"
2487instance ToJSON HasParentQuery where
2488 toJSON (HasParentQuery queryType query scoreType) =
2489 omitNulls [ "parent_type" .= queryType
2490 , "score_type" .= scoreType
2491 , "query" .= query ]
2493instance FromJSON HasParentQuery where
2494 parseJSON = withObject "HasParentQuery" parse
2495 where parse o = HasParentQuery
2496 <$> o .: "parent_type"
2497 <*> o .: "query"
2498 <*> o .:? "score_type"
2500instance ToJSON HasChildQuery where
2501 toJSON (HasChildQuery queryType query scoreType) =
2502 omitNulls [ "query" .= query
2503 , "score_type" .= scoreType
2504 , "type" .= queryType ]
2506instance FromJSON HasChildQuery where
2507 parseJSON = withObject "HasChildQuery" parse
2508 where parse o = HasChildQuery
2509 <$> o .: "type"
2510 <*> o .: "query"
2511 <*> o .:? "score_type"
2513instance ToJSON FuzzyQuery where
2514 toJSON (FuzzyQuery (FieldName fieldName) queryText
2515 prefixLength maxEx fuzziness boost) =
2516 object [ fieldName .= omitNulls base ]
2517 where base = [ "value" .= queryText
2518 , "fuzziness" .= fuzziness
2519 , "prefix_length" .= prefixLength
2520 , "boost" .= boost
2521 , "max_expansions" .= maxEx ]
2523instance FromJSON FuzzyQuery where
2524 parseJSON = withObject "FuzzyQuery" parse
2525 where parse = fieldTagged $ \fn o ->
2526 FuzzyQuery fn
2527 <$> o .: "value"
2528 <*> o .: "prefix_length"
2529 <*> o .: "max_expansions"
2530 <*> o .: "fuzziness"
2531 <*> o .:? "boost"
2533instance ToJSON FuzzyLikeFieldQuery where
2534 toJSON (FuzzyLikeFieldQuery (FieldName fieldName)
2535 fieldText maxTerms ignoreFreq fuzziness prefixLength
2536 boost analyzer) =
2537 object [ fieldName .=
2538 omitNulls [ "like_text" .= fieldText
2539 , "max_query_terms" .= maxTerms
2540 , "ignore_tf" .= ignoreFreq
2541 , "fuzziness" .= fuzziness
2542 , "prefix_length" .= prefixLength
2543 , "analyzer" .= analyzer
2544 , "boost" .= boost ]]
2546instance FromJSON FuzzyLikeFieldQuery where
2547 parseJSON = withObject "FuzzyLikeFieldQuery" parse
2548 where parse = fieldTagged $ \fn o ->
2549 FuzzyLikeFieldQuery fn
2550 <$> o .: "like_text"
2551 <*> o .: "max_query_terms"
2552 <*> o .: "ignore_tf"
2553 <*> o .: "fuzziness"
2554 <*> o .: "prefix_length"
2555 <*> o .: "boost"
2556 <*> o .:? "analyzer"
2558instance ToJSON FuzzyLikeThisQuery where
2559 toJSON (FuzzyLikeThisQuery fields text maxTerms
2560 ignoreFreq fuzziness prefixLength boost analyzer) =
2561 omitNulls base
2562 where base = [ "fields" .= fields
2563 , "like_text" .= text
2564 , "max_query_terms" .= maxTerms
2565 , "ignore_tf" .= ignoreFreq
2566 , "fuzziness" .= fuzziness
2567 , "prefix_length" .= prefixLength
2568 , "analyzer" .= analyzer
2569 , "boost" .= boost ]
2571instance FromJSON FuzzyLikeThisQuery where
2572 parseJSON = withObject "FuzzyLikeThisQuery" parse
2573 where parse o = FuzzyLikeThisQuery
2574 <$> o .:? "fields" .!= []
2575 <*> o .: "like_text"
2576 <*> o .: "max_query_terms"
2577 <*> o .: "ignore_tf"
2578 <*> o .: "fuzziness"
2579 <*> o .: "prefix_length"
2580 <*> o .: "boost"
2581 <*> o .:? "analyzer"
2583instance ToJSON FilteredQuery where
2584 toJSON (FilteredQuery query fFilter) =
2585 object [ "query" .= query
2586 , "filter" .= fFilter ]
2588instance FromJSON FilteredQuery where
2589 parseJSON = withObject "FilteredQuery" parse
2590 where parse o = FilteredQuery
2591 <$> o .: "query"
2592 <*> o .: "filter"
2594instance ToJSON DisMaxQuery where
2595 toJSON (DisMaxQuery queries tiebreaker boost) =
2596 omitNulls base
2597 where base = [ "queries" .= queries
2598 , "boost" .= boost
2599 , "tie_breaker" .= tiebreaker ]
2601instance FromJSON DisMaxQuery where
2602 parseJSON = withObject "DisMaxQuery" parse
2603 where parse o = DisMaxQuery
2604 <$> o .:? "queries" .!= []
2605 <*> o .: "tie_breaker"
2606 <*> o .:? "boost"
2608instance ToJSON CommonTermsQuery where
2609 toJSON (CommonTermsQuery (FieldName fieldName)
2610 (QueryString query) cf lfo hfo msm
2611 boost analyzer disableCoord) =
2612 object [fieldName .= omitNulls base ]
2613 where base = [ "query" .= query
2614 , "cutoff_frequency" .= cf
2615 , "low_freq_operator" .= lfo
2616 , "minimum_should_match" .= msm
2617 , "boost" .= boost
2618 , "analyzer" .= analyzer
2619 , "disable_coord" .= disableCoord
2620 , "high_freq_operator" .= hfo ]
2622instance FromJSON CommonTermsQuery where
2623 parseJSON = withObject "CommonTermsQuery" parse
2624 where parse = fieldTagged $ \fn o ->
2625 CommonTermsQuery fn
2626 <$> o .: "query"
2627 <*> o .: "cutoff_frequency"
2628 <*> o .: "low_freq_operator"
2629 <*> o .: "high_freq_operator"
2630 <*> o .:? "minimum_should_match"
2631 <*> o .:? "boost"
2632 <*> o .:? "analyzer"
2633 <*> o .:? "disable_coord"
2635instance ToJSON CommonMinimumMatch where
2636 toJSON (CommonMinimumMatch mm) = toJSON mm
2637 toJSON (CommonMinimumMatchHighLow (MinimumMatchHighLow lowF highF)) =
2638 object [ "low_freq" .= lowF
2639 , "high_freq" .= highF ]
2641instance FromJSON CommonMinimumMatch where
2642 parseJSON v = parseMinimum v
2643 <|> parseMinimumHighLow v
2644 where parseMinimum = fmap CommonMinimumMatch . parseJSON
2645 parseMinimumHighLow = fmap CommonMinimumMatchHighLow . withObject "CommonMinimumMatchHighLow" (\o ->
2646 MinimumMatchHighLow
2647 <$> o .: "low_freq"
2648 <*> o .: "high_freq")
2651instance ToJSON BoostingQuery where
2652 toJSON (BoostingQuery bqPositiveQuery bqNegativeQuery bqNegativeBoost) =
2653 object [ "positive" .= bqPositiveQuery
2654 , "negative" .= bqNegativeQuery
2655 , "negative_boost" .= bqNegativeBoost ]
2657instance FromJSON BoostingQuery where
2658 parseJSON = withObject "BoostingQuery" parse
2659 where parse o = BoostingQuery
2660 <$> o .: "positive"
2661 <*> o .: "negative"
2662 <*> o .: "negative_boost"
2664instance ToJSON BoolQuery where
2665 toJSON (BoolQuery mustM notM shouldM bqMin boost disableCoord) =
2666 omitNulls base
2667 where base = [ "must" .= mustM
2668 , "must_not" .= notM
2669 , "should" .= shouldM
2670 , "minimum_should_match" .= bqMin
2671 , "boost" .= boost
2672 , "disable_coord" .= disableCoord ]
2674instance FromJSON BoolQuery where
2675 parseJSON = withObject "BoolQuery" parse
2676 where parse o = BoolQuery
2677 <$> o .:? "must" .!= []
2678 <*> o .:? "must_not" .!= []
2679 <*> o .:? "should" .!= []
2680 <*> o .:? "minimum_should_match"
2681 <*> o .:? "boost"
2682 <*> o .:? "disable_coord"
2684instance ToJSON MatchQuery where
2685 toJSON (MatchQuery (FieldName fieldName)
2686 (QueryString mqQueryString) booleanOperator
2687 zeroTermsQuery cutoffFrequency matchQueryType
2688 analyzer maxExpansions lenient boost) =
2689 object [ fieldName .= omitNulls base ]
2690 where base = [ "query" .= mqQueryString
2691 , "operator" .= booleanOperator
2692 , "zero_terms_query" .= zeroTermsQuery
2693 , "cutoff_frequency" .= cutoffFrequency
2694 , "type" .= matchQueryType
2695 , "analyzer" .= analyzer
2696 , "max_expansions" .= maxExpansions
2697 , "lenient" .= lenient
2698 , "boost" .= boost ]
2700instance FromJSON MatchQuery where
2701 parseJSON = withObject "MatchQuery" parse
2702 where parse = fieldTagged $ \fn o ->
2703 MatchQuery fn
2704 <$> o .: "query"
2705 <*> o .: "operator"
2706 <*> o .: "zero_terms_query"
2707 <*> o .:? "cutoff_frequency"
2708 <*> o .:? "type"
2709 <*> o .:? "analyzer"
2710 <*> o .:? "max_expansions"
2711 <*> o .:? "lenient"
2712 <*> o .:? "boost"
2714instance ToJSON MultiMatchQuery where
2715 toJSON (MultiMatchQuery fields (QueryString query) boolOp
2716 ztQ tb mmqt cf analyzer maxEx lenient) =
2717 object ["multi_match" .= omitNulls base]
2718 where base = [ "fields" .= fmap toJSON fields
2719 , "query" .= query
2720 , "operator" .= boolOp
2721 , "zero_terms_query" .= ztQ
2722 , "tiebreaker" .= tb
2723 , "type" .= mmqt
2724 , "cutoff_frequency" .= cf
2725 , "analyzer" .= analyzer
2726 , "max_expansions" .= maxEx
2727 , "lenient" .= lenient ]
2729instance FromJSON MultiMatchQuery where
2730 parseJSON = withObject "MultiMatchQuery" parse
2731 where parse raw = do o <- raw .: "multi_match"
2732 MultiMatchQuery
2733 <$> o .:? "fields" .!= []
2734 <*> o .: "query"
2735 <*> o .: "operator"
2736 <*> o .: "zero_terms_query"
2737 <*> o .:? "tiebreaker"
2738 <*> o .:? "type"
2739 <*> o .:? "cutoff_frequency"
2740 <*> o .:? "analyzer"
2741 <*> o .:? "max_expansions"
2742 <*> o .:? "lenient"
2744instance ToJSON MultiMatchQueryType where
2745 toJSON MultiMatchBestFields = "best_fields"
2746 toJSON MultiMatchMostFields = "most_fields"
2747 toJSON MultiMatchCrossFields = "cross_fields"
2748 toJSON MultiMatchPhrase = "phrase"
2749 toJSON MultiMatchPhrasePrefix = "phrase_prefix"
2751instance FromJSON MultiMatchQueryType where
2752 parseJSON = withText "MultiMatchPhrasePrefix" parse
2753 where parse "best_fields" = pure MultiMatchBestFields
2754 parse "most_fields" = pure MultiMatchMostFields
2755 parse "cross_fields" = pure MultiMatchCrossFields
2756 parse "phrase" = pure MultiMatchPhrase
2757 parse "phrase_prefix" = pure MultiMatchPhrasePrefix
2758 parse t = fail ("Unexpected MultiMatchPhrasePrefix: " <> show t)
2760instance ToJSON BooleanOperator where
2761 toJSON And = String "and"
2762 toJSON Or = String "or"
2764instance FromJSON BooleanOperator where
2765 parseJSON = withText "BooleanOperator" parse
2766 where parse "and" = pure And
2767 parse "or" = pure Or
2768 parse o = fail ("Unexpected BooleanOperator: " <> show o)
2770instance ToJSON ZeroTermsQuery where
2771 toJSON ZeroTermsNone = String "none"
2772 toJSON ZeroTermsAll = String "all"
2774instance FromJSON ZeroTermsQuery where
2775 parseJSON = withText "ZeroTermsQuery" parse
2776 where parse "none" = pure ZeroTermsNone
2777 parse "all" = pure ZeroTermsAll
2778 parse q = fail ("Unexpected ZeroTermsQuery: " <> show q)
2780instance ToJSON MatchQueryType where
2781 toJSON MatchPhrase = "phrase"
2782 toJSON MatchPhrasePrefix = "phrase_prefix"
2784instance FromJSON MatchQueryType where
2785 parseJSON = withText "MatchQueryType" parse
2786 where parse "phrase" = pure MatchPhrase
2787 parse "phrase_prefix" = pure MatchPhrasePrefix
2788 parse t = fail ("Unexpected MatchQueryType: " <> show t)
2790instance FromJSON Status where
2791 parseJSON (Object v) = Status <$>
2792 v .:? "ok" <*>
2793 v .: "status" <*>
2794 v .: "name" <*>
2795 v .: "version" <*>
2796 v .: "tagline"
2797 parseJSON _ = empty
2800instance ToJSON IndexSettings where
2801 toJSON (IndexSettings s r) = object ["settings" .=
2802 object ["index" .=
2803 object ["number_of_shards" .= s, "number_of_replicas" .= r]
2807instance 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"
2814instance 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
2844instance 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
2907instance 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
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'
2921unStringlyTypeJSON :: MonadPlus m => Value -> m Value
2922unStringlyTypeJSON (String "true") = return (Bool True)
2923unStringlyTypeJSON (String "false") = return (Bool False)
2924unStringlyTypeJSON (String "null") = return Null
2925unStringlyTypeJSON (String t) = case readMay (T.unpack t) of
2926 Just n -> return (Number n)
2927 Nothing -> mzero
2928unStringlyTypeJSON _ = mzero
2931parseSettings :: Object -> Parser [UpdatableIndexSetting]
2932parseSettings 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)
2942oPath :: ToJSON a => NonEmpty Text -> a -> Value
2943oPath (k :| []) v = object [k .= v]
2944oPath (k:| (h:t)) v = object [k .= oPath (h :| t) v]
2946attrFilterJSON :: NonEmpty NodeAttrFilter -> Value
2947attrFilterJSON fs = object [ n .= T.intercalate "," (toList vs)
2948 | NodeAttrFilter (NodeAttrName n) vs <- toList fs]
2950parseAttrFilter :: Value -> Parser (NonEmpty NodeAttrFilter)
2951parseAttrFilter = 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"
2960instance 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
2965instance 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"
2976instance ToJSON AllocationPolicy where
2977 toJSON AllocAll = String "all"
2978 toJSON AllocPrimaries = String "primaries"
2979 toJSON AllocNewPrimaries = String "new_primaries"
2980 toJSON AllocNone = String "none"
2982instance 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)
2990instance 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
2997instance 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
3006instance ToJSON FSType where
3007 toJSON FSSimple = "simple"
3008 toJSON FSBuffered = "buffered"
3010instance 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)
3016instance ToJSON CompoundFormat where
3017 toJSON (CompoundFileFormat x) = Bool x
3018 toJSON (MergeSegmentVsTotalIndex x) = toJSON x
3020instance FromJSON CompoundFormat where
3021 parseJSON v = CompoundFileFormat <$> parseJSON v
3022 <|> MergeSegmentVsTotalIndex <$> parseJSON v
3024instance ToJSON NominalDiffTimeJSON where
3025 toJSON (NominalDiffTimeJSON t) = String (showText (round t :: Integer) <> "s")
3027instance 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)"
3033instance ToJSON IndexTemplate where
3034 toJSON (IndexTemplate p s m) = merge
3035 (object [ "template" .= p
3036 , "mappings" .= foldl' merge (object []) m
3037 ])
3038 (toJSON s)
3039 where
3040 merge (Object o1) (Object o2) = toJSON $ HM.union o1 o2
3041 merge o Null = o
3042 merge _ _ = undefined
3044instance (FromJSON a) => FromJSON (EsResult a) where
3045 parseJSON jsonVal@(Object v) = do
3046 found <- v .:? "found" .!= False
3047 fr <- if found
3048 then parseJSON jsonVal
3049 else return Nothing
3050 EsResult <$> v .: "_index" <*>
3051 v .: "_type" <*>
3052 v .: "_id" <*>
3053 pure fr
3054 parseJSON _ = empty
3056instance (FromJSON a) => FromJSON (EsResultFound a) where
3057 parseJSON (Object v) = EsResultFound <$>
3058 v .: "_version" <*>
3059 v .: "_source"
3060 parseJSON _ = empty
3062instance FromJSON EsError where
3063 parseJSON (Object v) = EsError <$>
3064 v .: "status" <*>
3065 v .: "error"
3066 parseJSON _ = empty
3068instance FromJSON IndexAliasesSummary where
3069 parseJSON = withObject "IndexAliasesSummary" parse
3070 where parse o = IndexAliasesSummary . mconcat <$> mapM (uncurry go) (HM.toList o)
3071 go ixn = withObject "index aliases" $ \ia -> do
3072 aliases <- ia .:? "aliases" .!= mempty
3073 forM (HM.toList aliases) $ \(aName, v) -> do
3074 let indexAlias = IndexAlias (IndexName ixn) (IndexAliasName (IndexName aName))
3075 IndexAliasSummary indexAlias <$> parseJSON v
3078instance ToJSON IndexAliasAction where
3079 toJSON (AddAlias ia opts) = object ["add" .= (iaObj <> optsObj)]
3080 where Object iaObj = toJSON ia
3081 Object optsObj = toJSON opts
3082 toJSON (RemoveAlias ia) = object ["remove" .= iaObj]
3083 where Object iaObj = toJSON ia
3085instance ToJSON IndexAlias where
3086 toJSON IndexAlias {..} = object ["index" .= srcIndex
3087 , "alias" .= indexAlias
3090instance ToJSON IndexAliasCreate where
3091 toJSON IndexAliasCreate {..} = Object (filterObj <> routingObj)
3092 where filterObj = maybe mempty (HM.singleton "filter" . toJSON) aliasCreateFilter
3093 Object routingObj = maybe (Object mempty) toJSON aliasCreateRouting
3095instance ToJSON AliasRouting where
3096 toJSON (AllAliasRouting v) = object ["routing" .= v]
3097 toJSON (GranularAliasRouting srch idx) = object (catMaybes prs)
3098 where prs = [("search_routing" .=) <$> srch
3099 ,("index_routing" .=) <$> idx]
3101instance FromJSON AliasRouting where
3102 parseJSON = withObject "AliasRouting" parse
3103 where parse o = parseAll o <|> parseGranular o
3104 parseAll o = AllAliasRouting <$> o .: "routing"
3105 parseGranular o = do
3106 sr <- o .:? "search_routing"
3107 ir <- o .:? "index_routing"
3108 if isNothing sr && isNothing ir
3109 then fail "Both search_routing and index_routing can't be blank"
3110 else return (GranularAliasRouting sr ir)
3112instance FromJSON IndexAliasCreate where
3113 parseJSON v = withObject "IndexAliasCreate" parse v
3114 where parse o = IndexAliasCreate <$> optional (parseJSON v)
3115 <*> o .:? "filter"
3117instance ToJSON SearchAliasRouting where
3118 toJSON (SearchAliasRouting rvs) = toJSON (T.intercalate "," (routingValue <$> toList rvs))
3120instance FromJSON SearchAliasRouting where
3121 parseJSON = withText "SearchAliasRouting" parse
3122 where parse t = SearchAliasRouting <$> parseNEJSON (String <$> T.splitOn "," t)
3124instance ToJSON Search where
3125 toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
3126 omitNulls [ "query" .= query
3127 , "filter" .= sFilter
3128 , "sort" .= sort
3129 , "aggregations" .= searchAggs
3130 , "highlight" .= highlight
3131 , "from" .= sFrom
3132 , "size" .= sSize
3133 , "track_scores" .= sTrackSortScores
3134 , "fields" .= sFields
3135 , "_source" .= sSource]
3138instance ToJSON Source where
3139 toJSON NoSource = toJSON False
3140 toJSON (SourcePatterns patterns) = toJSON patterns
3141 toJSON (SourceIncludeExclude incl excl) = object [ "include" .= incl, "exclude" .= excl ]
3143instance ToJSON PatternOrPatterns where
3144 toJSON (PopPattern pattern) = toJSON pattern
3145 toJSON (PopPatterns patterns) = toJSON patterns
3147instance ToJSON Include where
3148 toJSON (Include patterns) = toJSON patterns
3150instance ToJSON Exclude where
3151 toJSON (Exclude patterns) = toJSON patterns
3153instance ToJSON Pattern where
3154 toJSON (Pattern pattern) = toJSON pattern
3157instance ToJSON FieldHighlight where
3158 toJSON (FieldHighlight (FieldName fName) (Just fSettings)) =
3159 object [ fName .= fSettings ]
3160 toJSON (FieldHighlight (FieldName fName) Nothing) =
3161 object [ fName .= emptyObject ]
3163instance ToJSON Highlights where
3164 toJSON (Highlights global fields) =
3165 omitNulls (("fields" .= fields)
3166 : highlightSettingsPairs global)
3168instance ToJSON HighlightSettings where
3169 toJSON hs = omitNulls (highlightSettingsPairs (Just hs))
3171highlightSettingsPairs :: Maybe HighlightSettings -> [Pair]
3172highlightSettingsPairs Nothing = []
3173highlightSettingsPairs (Just (Plain plh)) = plainHighPairs (Just plh)
3174highlightSettingsPairs (Just (Postings ph)) = postHighPairs (Just ph)
3175highlightSettingsPairs (Just (FastVector fvh)) = fastVectorHighPairs (Just fvh)
3178plainHighPairs :: Maybe PlainHighlight -> [Pair]
3179plainHighPairs Nothing = []
3180plainHighPairs (Just (PlainHighlight plCom plNonPost)) =
3181 [ "type" .= String "plain"]
3182 ++ commonHighlightPairs plCom
3183 ++ nonPostingsToPairs plNonPost
3185postHighPairs :: Maybe PostingsHighlight -> [Pair]
3186postHighPairs Nothing = []
3187postHighPairs (Just (PostingsHighlight pCom)) =
3188 ("type" .= String "postings")
3189 : commonHighlightPairs pCom
3191fastVectorHighPairs :: Maybe FastVectorHighlight -> [Pair]
3192fastVectorHighPairs Nothing = []
3193fastVectorHighPairs (Just
3194 (FastVectorHighlight fvCom fvNonPostSettings fvBoundChars
3195 fvBoundMaxScan fvFragOff fvMatchedFields
3196 fvPhraseLim)) =
3197 [ "type" .= String "fvh"
3198 , "boundary_chars" .= fvBoundChars
3199 , "boundary_max_scan" .= fvBoundMaxScan
3200 , "fragment_offset" .= fvFragOff
3201 , "matched_fields" .= fvMatchedFields
3202 , "phraseLimit" .= fvPhraseLim]
3203 ++ commonHighlightPairs fvCom
3204 ++ nonPostingsToPairs fvNonPostSettings
3206deleteSeveral :: (Eq k, Hashable k) => [k] -> HM.HashMap k v -> HM.HashMap k v
3207deleteSeveral ks hm = foldr HM.delete hm ks
3209commonHighlightPairs :: Maybe CommonHighlight -> [Pair]
3210commonHighlightPairs Nothing = []
3211commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder
3212 chNoMatchSize chHighlightQuery
3213 chRequireFieldMatch)) =
3214 [ "order" .= chScore
3215 , "force_source" .= chForceSource
3216 , "encoder" .= chEncoder
3217 , "no_match_size" .= chNoMatchSize
3218 , "highlight_query" .= chHighlightQuery
3219 , "require_fieldMatch" .= chRequireFieldMatch]
3220 ++ highlightTagToPairs chTag
3223nonPostingsToPairs :: Maybe NonPostings -> [Pair]
3224nonPostingsToPairs Nothing = []
3225nonPostingsToPairs (Just (NonPostings npFragSize npNumOfFrags)) =
3226 [ "fragment_size" .= npFragSize
3227 , "number_of_fragments" .= npNumOfFrags]
3229parseNEJSON :: (FromJSON a) => [Value] -> Parser (NonEmpty a)
3230parseNEJSON [] = fail "Expected non-empty list"
3231parseNEJSON (x:xs) = DT.mapM parseJSON (x :| xs)
3234instance ToJSON HighlightEncoder where
3235 toJSON DefaultEncoder = String "default"
3236 toJSON HTMLEncoder = String "html"
3238highlightTagToPairs :: Maybe HighlightTag -> [Pair]
3239highlightTagToPairs (Just (TagSchema _)) = [ "scheme" .= String "default"]
3240highlightTagToPairs (Just (CustomTags (pre, post))) = [ "pre_tags" .= pre
3241 , "post_tags" .= post]
3242highlightTagToPairs Nothing = []
3244instance ToJSON SortSpec where
3245 toJSON (DefaultSortSpec
3246 (DefaultSort (FieldName dsSortFieldName) dsSortOrder dsIgnoreUnmapped
3247 dsSortMode dsMissingSort dsNestedFilter)) =
3248 object [dsSortFieldName .= omitNulls base] where
3249 base = [ "order" .= dsSortOrder
3250 , "ignore_unmapped" .= dsIgnoreUnmapped
3251 , "mode" .= dsSortMode
3252 , "missing" .= dsMissingSort
3253 , "nested_filter" .= dsNestedFilter ]
3255 toJSON (GeoDistanceSortSpec gdsSortOrder (GeoPoint (FieldName field) gdsLatLon) units) =
3256 object [ "unit" .= units
3257 , field .= gdsLatLon
3258 , "order" .= gdsSortOrder ]
3261instance ToJSON SortOrder where
3262 toJSON Ascending = String "asc"
3263 toJSON Descending = String "desc"
3266instance ToJSON SortMode where
3267 toJSON SortMin = String "min"
3268 toJSON SortMax = String "max"
3269 toJSON SortSum = String "sum"
3270 toJSON SortAvg = String "avg"
3273instance ToJSON Missing where
3274 toJSON LastMissing = String "_last"
3275 toJSON FirstMissing = String "_first"
3276 toJSON (CustomMissing txt) = String txt
3279instance ToJSON ScoreType where
3280 toJSON ScoreTypeMax = "max"
3281 toJSON ScoreTypeAvg = "avg"
3282 toJSON ScoreTypeSum = "sum"
3283 toJSON ScoreTypeNone = "none"
3285instance FromJSON ScoreType where
3286 parseJSON = withText "ScoreType" parse
3287 where parse "max" = pure ScoreTypeMax
3288 parse "avg" = pure ScoreTypeAvg
3289 parse "sum" = pure ScoreTypeSum
3290 parse "none" = pure ScoreTypeNone
3291 parse t = fail ("Unexpected ScoreType: " <> show t)
3293instance ToJSON Distance where
3294 toJSON (Distance dCoefficient dUnit) =
3295 String boltedTogether where
3296 coefText = showText dCoefficient
3297 (String unitText) = toJSON dUnit
3298 boltedTogether = mappend coefText unitText
3300instance FromJSON Distance where
3301 parseJSON = withText "Distance" parse
3302 where parse t = Distance <$> parseCoeff nT
3303 <*> parseJSON (String unitT)
3304 where (nT, unitT) = T.span validForNumber t
3305 -- may be a better way to do this
3306 validForNumber '-' = True
3307 validForNumber '.' = True
3308 validForNumber 'e' = True
3309 validForNumber c = isNumber c
3310 parseCoeff "" = fail "Empty string cannot be parsed as number"
3311 parseCoeff s = return (read (T.unpack s))
3313instance ToJSON DistanceUnit where
3314 toJSON Miles = String "mi"
3315 toJSON Yards = String "yd"
3316 toJSON Feet = String "ft"
3317 toJSON Inches = String "in"
3318 toJSON Kilometers = String "km"
3319 toJSON Meters = String "m"
3320 toJSON Centimeters = String "cm"
3321 toJSON Millimeters = String "mm"
3322 toJSON NauticalMiles = String "nmi"
3325instance FromJSON DistanceUnit where
3326 parseJSON = withText "DistanceUnit" parse
3327 where parse "mi" = pure Miles
3328 parse "yd" = pure Yards
3329 parse "ft" = pure Feet
3330 parse "in" = pure Inches
3331 parse "km" = pure Kilometers
3332 parse "m" = pure Meters
3333 parse "cm" = pure Centimeters
3334 parse "mm" = pure Millimeters
3335 parse "nmi" = pure NauticalMiles
3336 parse u = fail ("Unrecognized DistanceUnit: " <> show u)
3338instance ToJSON DistanceType where
3339 toJSON Arc = String "arc"
3340 toJSON SloppyArc = String "sloppy_arc"
3341 toJSON Plane = String "plane"
3343instance FromJSON DistanceType where
3344 parseJSON = withText "DistanceType" parse
3345 where parse "arc" = pure Arc
3346 parse "sloppy_arc" = pure SloppyArc
3347 parse "plane" = pure Plane
3348 parse t = fail ("Unrecognized DistanceType: " <> show t)
3351instance ToJSON OptimizeBbox where
3352 toJSON NoOptimizeBbox = String "none"
3353 toJSON (OptimizeGeoFilterType gft) = toJSON gft
3355instance FromJSON OptimizeBbox where
3356 parseJSON v = withText "NoOptimizeBbox" parseNoOptimize v
3357 <|> parseOptimize v
3358 where parseNoOptimize "none" = pure NoOptimizeBbox
3359 parseNoOptimize _ = mzero
3360 parseOptimize = fmap OptimizeGeoFilterType . parseJSON
3362instance ToJSON GeoBoundingBoxConstraint where
3363 toJSON (GeoBoundingBoxConstraint
3364 (FieldName gbbcGeoBBField) gbbcConstraintBox cache type') =
3365 object [gbbcGeoBBField .= gbbcConstraintBox
3366 , "_cache" .= cache
3367 , "type" .= type']
3369instance FromJSON GeoBoundingBoxConstraint where
3370 parseJSON = withObject "GeoBoundingBoxConstraint" parse
3371 where parse o = case HM.toList (deleteSeveral ["type", "_cache"] o) of
3372 [(fn, v)] -> GeoBoundingBoxConstraint (FieldName fn)
3373 <$> parseJSON v
3374 <*> o .:? "_cache" .!= defaultCache
3375 <*> o .: "type"
3376 _ -> fail "Could not find field name for GeoBoundingBoxConstraint"
3378instance ToJSON GeoFilterType where
3379 toJSON GeoFilterMemory = String "memory"
3380 toJSON GeoFilterIndexed = String "indexed"
3382instance FromJSON GeoFilterType where
3383 parseJSON = withText "GeoFilterType" parse
3384 where parse "memory" = pure GeoFilterMemory
3385 parse "indexed" = pure GeoFilterIndexed
3386 parse t = fail ("Unrecognized GeoFilterType: " <> show t)
3388instance ToJSON GeoBoundingBox where
3389 toJSON (GeoBoundingBox gbbTopLeft gbbBottomRight) =
3390 object ["top_left" .= gbbTopLeft
3391 , "bottom_right" .= gbbBottomRight]
3393instance FromJSON GeoBoundingBox where
3394 parseJSON = withObject "GeoBoundingBox" parse
3395 where parse o = GeoBoundingBox
3396 <$> o .: "top_left"
3397 <*> o .: "bottom_right"
3399instance ToJSON LatLon where
3400 toJSON (LatLon lLat lLon) =
3401 object ["lat" .= lLat
3402 , "lon" .= lLon]
3404instance FromJSON LatLon where
3405 parseJSON = withObject "LatLon" parse
3406 where parse o = LatLon <$> o .: "lat"
3407 <*> o .: "lon"
3409-- index for smaller ranges, fielddata for longer ranges
3410instance ToJSON RangeExecution where
3411 toJSON RangeExecutionIndex = "index"
3412 toJSON RangeExecutionFielddata = "fielddata"
3415instance FromJSON RangeExecution where
3416 parseJSON = withText "RangeExecution" parse
3417 where parse "index" = pure RangeExecutionIndex
3418 parse "fielddata" = pure RangeExecutionFielddata
3419 parse t = error ("Unrecognized RangeExecution " <> show t)
3421instance ToJSON RegexpFlags where
3422 toJSON AllRegexpFlags = String "ALL"
3423 toJSON NoRegexpFlags = String "NONE"
3424 toJSON (SomeRegexpFlags (h :| fs)) = String $ T.intercalate "|" flagStrs
3425 where flagStrs = map flagStr . nub $ h:fs
3426 flagStr AnyString = "ANYSTRING"
3427 flagStr Automaton = "AUTOMATON"
3428 flagStr Complement = "COMPLEMENT"
3429 flagStr Empty = "EMPTY"
3430 flagStr Intersection = "INTERSECTION"
3431 flagStr Interval = "INTERVAL"
3433instance FromJSON RegexpFlags where
3434 parseJSON = withText "RegexpFlags" parse
3435 where parse "ALL" = pure AllRegexpFlags
3436 parse "NONE" = pure NoRegexpFlags
3437 parse t = SomeRegexpFlags <$> parseNEJSON (String <$> T.splitOn "|" t)
3439instance FromJSON RegexpFlag where
3440 parseJSON = withText "RegexpFlag" parse
3441 where parse "ANYSTRING" = pure AnyString
3442 parse "AUTOMATON" = pure Automaton
3443 parse "COMPLEMENT" = pure Complement
3444 parse "EMPTY" = pure Empty
3445 parse "INTERSECTION" = pure Intersection
3446 parse "INTERVAL" = pure Interval
3447 parse f = fail ("Unknown RegexpFlag: " <> show f)
3449instance ToJSON Term where
3450 toJSON (Term field value) = object ["term" .= object
3451 [field .= value]]
3453instance FromJSON Term where
3454 parseJSON = withObject "Term" parse
3455 where parse o = do termObj <- o .: "term"
3456 case HM.toList termObj of
3457 [(fn, v)] -> Term fn <$> parseJSON v
3458 _ -> fail "Expected object with 1 field-named key"
3460instance ToJSON BoolMatch where
3461 toJSON (MustMatch term cache) = object ["must" .= term,
3462 "_cache" .= cache]
3463 toJSON (MustNotMatch term cache) = object ["must_not" .= term,
3464 "_cache" .= cache]
3465 toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
3466 "_cache" .= cache]
3468instance FromJSON BoolMatch where
3469 parseJSON = withObject "BoolMatch" parse
3470 where parse o = mustMatch `taggedWith` "must"
3471 <|> mustNotMatch `taggedWith` "must_not"
3472 <|> shouldMatch `taggedWith` "should"
3473 where taggedWith parser k = parser =<< o .: k
3474 mustMatch t = MustMatch t <$> o .:? "_cache" .!= defaultCache
3475 mustNotMatch t = MustNotMatch t <$> o .:? "_cache" .!= defaultCache
3476 shouldMatch t = ShouldMatch t <$> o .:? "_cache" .!= defaultCache
3478instance (FromJSON a) => FromJSON (SearchResult a) where
3479 parseJSON (Object v) = SearchResult <$>
3480 v .: "took" <*>
3481 v .: "timed_out" <*>
3482 v .: "_shards" <*>
3483 v .: "hits" <*>
3484 v .:? "aggregations" <*>
3485 v .:? "_scroll_id"
3486 parseJSON _ = empty
3488instance (FromJSON a) => FromJSON (SearchHits a) where
3489 parseJSON (Object v) = SearchHits <$>
3490 v .: "total" <*>
3491 v .: "max_score" <*>
3492 v .: "hits"
3493 parseJSON _ = empty
3495instance (FromJSON a) => FromJSON (Hit a) where
3496 parseJSON (Object v) = Hit <$>
3497 v .: "_index" <*>
3498 v .: "_type" <*>
3499 v .: "_id" <*>
3500 v .: "_score" <*>
3501 v .:? "_source" <*>
3502 v .:? "highlight"
3503 parseJSON _ = empty
3505instance FromJSON ShardResult where
3506 parseJSON (Object v) = ShardResult <$>
3507 v .: "total" <*>
3508 v .: "successful" <*>
3509 v .: "failed"
3510 parseJSON _ = empty
3513instance FromJSON DocVersion where
3514 parseJSON v = do
3515 i <- parseJSON v
3516 maybe (fail "DocVersion out of range") return $ mkDocVersion i
3518-- This insanity is because ES *sometimes* returns Replica/Shard counts as strings
3519instance FromJSON ReplicaCount where
3520 parseJSON v = parseAsInt v
3521 <|> parseAsString v
3522 where parseAsInt = fmap ReplicaCount . parseJSON
3523 parseAsString = withText "ReplicaCount" (fmap ReplicaCount . parseReadText)
3525instance FromJSON ShardCount where
3526 parseJSON v = parseAsInt v
3527 <|> parseAsString v
3528 where parseAsInt = fmap ShardCount . parseJSON
3529 parseAsString = withText "ShardCount" (fmap ShardCount . parseReadText)
3531instance Bounded DocVersion where
3532 minBound = DocVersion 1
3533 maxBound = DocVersion 9200000000000000000 -- 9.2e+18
3535instance Enum DocVersion where
3536 succ x
3537 | x /= maxBound = DocVersion (succ $ docVersionNumber x)
3538 | otherwise = succError "DocVersion"
3539 pred x
3540 | x /= minBound = DocVersion (pred $ docVersionNumber x)
3541 | otherwise = predError "DocVersion"
3542 toEnum i =
3543 fromMaybe (error $ show i ++ " out of DocVersion range") $ mkDocVersion i
3544 fromEnum = docVersionNumber
3545 enumFrom = boundedEnumFrom
3546 enumFromThen = boundedEnumFromThen