@@ -1,8 +1,8 @@
1+{-# LANGUAGE DeriveGeneric #-}
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
5−{-# LANGUAGE NamedFieldPuns #-}
6{-# LANGUAGE OverloadedStrings #-}
6{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE RecordWildCards #-}
7{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE UndecidableInstances #-}
8{-# LANGUAGE UndecidableInstances #-}
@@ -10,11 +10,11 @@
10-------------------------------------------------------------------------------
10-------------------------------------------------------------------------------
12-- Module : Database.Bloodhound.Types
12-- Module : Database.Bloodhound.Types
13−-- Copyright : (C) 2014, 2018 Chris Allen
13+-- Copyright : (C) 2014 Chris Allen
14-- License : BSD-style (see the file LICENSE)
14-- License : BSD-style (see the file LICENSE)
15-- Maintainer : Chris Allen <cma@bitemyapp.com
15-- Maintainer : Chris Allen <cma@bitemyapp.com
16-- Stability : provisional
16-- Stability : provisional
17−-- Portability : RecordWildCards
17+-- Portability : DeriveGeneric, RecordWildCards
19-- Data types for describing actions and data structures performed to interact
19-- Data types for describing actions and data structures performed to interact
20-- with Elasticsearch. The two main buckets your queries against Elasticsearch
20-- with Elasticsearch. The two main buckets your queries against Elasticsearch
@@ -42,63 +42,25 @@ module Database.Bloodhound.Types
42 , mkTermsAggregation
42 , mkTermsAggregation
43 , mkTermsScriptAggregation
43 , mkTermsScriptAggregation
44 , mkDateHistogram
44 , mkDateHistogram
45− , mkCardinalityAggregation
46 , mkDocVersion
45 , mkDocVersion
48− , mkExtendedStatsAggregation
49 , docVersionNumber
46 , docVersionNumber
52 , toDateHistogram
48 , toDateHistogram
54 , omitNulls
49 , omitNulls
57− , BHEnv
52+ , BHEnv(..)
62 , MonadBH(..)
53 , MonadBH(..)
63 , Version(..)
54 , Version(..)
67 , Status(..)
55 , Status(..)
68 , Existence(..)
56 , Existence(..)
69 , NullValue(..)
57 , NullValue(..)
70 , IndexSettings(..)
58 , IndexSettings(..)
71− , UpdatableIndexSetting(..)
72− , IndexSettingsSummary(..)
73− , AllocationPolicy(..)
81− , InitialShardCount(..)
85 , IndexTemplate(..)
59 , IndexTemplate(..)
86 , Server(..)
60 , Server(..)
88 , EsResult(..)
62 , EsResult(..)
89 , EsResultFound(..)
63 , EsResultFound(..)
91− , EsProtocolException(..)
94− , IndexAliasAction(..)
95− , IndexAliasCreate(..)
96− , IndexAliasSummary(..)
97− , IndexAliasesSummary(..)
99− , SearchAliasRouting(..)
100− , IndexAliasRouting(..)
102 , DocVersion
64 , DocVersion
103 , ExternalDocVersion(..)
65 , ExternalDocVersion(..)
104 , VersionControl(..)
66 , VersionControl(..)
@@ -108,7 +70,7 @@ module Database.Bloodhound.Types
108 , Search(..)
70 , Search(..)
109 , SearchType(..)
71 , SearchType(..)
110 , SearchResult(..)
72 , SearchResult(..)
111− , ScrollId(..)
73+ , ScrollId
112 , SearchHits(..)
74 , SearchHits(..)
113 , TrackSortScores
75 , TrackSortScores
114 , From(..)
76 , From(..)
@@ -120,8 +82,8 @@ module Database.Bloodhound.Types
120 , Pattern(..)
82 , Pattern(..)
121 , ShardResult(..)
83 , ShardResult(..)
122 , Hit(..)
84 , Hit(..)
124 , Filter(..)
85 , Filter(..)
125 , BoolMatch(..)
87 , BoolMatch(..)
126 , Term(..)
88 , Term(..)
127 , GeoPoint(..)
89 , GeoPoint(..)
@@ -148,22 +110,8 @@ module Database.Bloodhound.Types
148 , RegexpFlags(..)
110 , RegexpFlags(..)
149 , RegexpFlag(..)
111 , RegexpFlag(..)
150 , FieldName(..)
112 , FieldName(..)
154 , Script(..)
113 , Script(..)
155− , ScriptLanguage(..)
161 , IndexName(..)
114 , IndexName(..)
162− , IndexSelection(..)
165− , ForceMergeIndexSettings(..)
166− , defaultForceMergeIndexSettings
167 , TemplateName(..)
115 , TemplateName(..)
168 , TemplatePattern(..)
116 , TemplatePattern(..)
169 , MappingName(..)
117 , MappingName(..)
@@ -187,19 +135,8 @@ module Database.Bloodhound.Types
187 , BoolQuery(..)
135 , BoolQuery(..)
188 , BoostingQuery(..)
136 , BoostingQuery(..)
189 , CommonTermsQuery(..)
137 , CommonTermsQuery(..)
190− , FunctionScoreQuery(..)
193− , FunctionScoreFunctions(..)
194− , ComponentFunctionScoreFunction(..)
195− , FunctionScoreFunction(..)
198− , FieldValueFactor(..)
200− , FactorModifier(..)
201− , FactorMissingFieldValue(..)
202 , DisMaxQuery(..)
138 , DisMaxQuery(..)
203 , FuzzyLikeThisQuery(..)
140 , FuzzyLikeThisQuery(..)
204 , FuzzyLikeFieldQuery(..)
141 , FuzzyLikeFieldQuery(..)
205 , FuzzyQuery(..)
142 , FuzzyQuery(..)
@@ -215,16 +152,10 @@ module Database.Bloodhound.Types
215 , RangeQuery(..)
152 , RangeQuery(..)
216 , RegexpQuery(..)
153 , RegexpQuery(..)
217 , QueryString(..)
154 , QueryString(..)
218− , TemplateQueryInline(..)
219− , TemplateQueryKeyValuePairs(..)
221 , BooleanOperator(..)
155 , BooleanOperator(..)
222 , ZeroTermsQuery(..)
156 , ZeroTermsQuery(..)
223 , CutoffFrequency(..)
157 , CutoffFrequency(..)
224 , Analyzer(..)
158 , Analyzer(..)
228 , MaxExpansions(..)
159 , MaxExpansions(..)
229 , Lenient(..)
160 , Lenient(..)
230 , MatchQueryType(..)
161 , MatchQueryType(..)
@@ -271,118 +202,16 @@ module Database.Bloodhound.Types
271 , CollectionMode(..)
202 , CollectionMode(..)
272 , TermOrder(..)
203 , TermOrder(..)
273 , TermInclusion(..)
204 , TermInclusion(..)
274− , SnapshotRepoSelection(..)
275− , GenericSnapshotRepo(..)
277− , SnapshotRepoConversionError(..)
278− , SnapshotRepoType(..)
279− , GenericSnapshotRepoSettings(..)
280− , SnapshotRepoUpdateSettings(..)
281− , defaultSnapshotRepoUpdateSettings
282− , SnapshotRepoName(..)
283− , SnapshotRepoPattern(..)
284− , SnapshotVerification(..)
285− , SnapshotNodeVerification(..)
292− , NodeBreakersStats(..)
293− , NodeBreakerStats(..)
295− , NodeTransportStats(..)
297− , NodeDataPathStats(..)
298− , NodeFSTotalStats(..)
299− , NodeNetworkStats(..)
300− , NodeThreadPoolsStats(..)
301− , NodeThreadPoolStats(..)
303− , JVMBufferPoolStats(..)
306− , NodeProcessStats(..)
309− , NodeIndicesStats(..)
313− , NodePluginInfo(..)
315− , NodeTransportInfo(..)
316− , BoundTransportAddress(..)
317− , NodeNetworkInfo(..)
319− , NetworkInterfaceName(..)
320− , NodeNetworkInterface(..)
321− , NodeThreadPoolsInfo(..)
322− , NodeThreadPoolInfo(..)
323− , ThreadPoolSize(..)
324− , ThreadPoolType(..)
327− , JVMGCCollector(..)
332− , NodeProcessInfo(..)
333− , FsSnapshotRepo(..)
334− , SnapshotCreateSettings(..)
335− , defaultSnapshotCreateSettings
336− , SnapshotSelection(..)
337− , SnapshotPattern(..)
339− , SnapshotShardFailure(..)
343− , SnapshotRestoreSettings(..)
344− , defaultSnapshotRestoreSettings
345− , RestoreRenamePattern(..)
346− , RestoreRenameToken(..)
350− , RestoreIndexSettings(..)
353− , PhraseSuggester(..)
354− , PhraseSuggesterHighlighter(..)
355− , PhraseSuggesterCollate(..)
357− , SuggestOptions(..)
358− , SuggestResponse(..)
359− , NamedSuggestionResponse(..)
360− , DirectGenerators(..)
361− , mkDirectGenerators
362− , DirectGeneratorSuggestModeTypes (..)
364 , Aggregation(..)
206 , Aggregation(..)
365 , Aggregations
207 , Aggregations
366 , AggregationResults
208 , AggregationResults
368 , Bucket(..)
209 , Bucket(..)
369 , BucketAggregation(..)
210 , BucketAggregation(..)
370 , TermsAggregation(..)
211 , TermsAggregation(..)
371− , MissingAggregation(..)
372 , ValueCountAggregation(..)
212 , ValueCountAggregation(..)
373 , FilterAggregation(..)
213 , FilterAggregation(..)
374− , CardinalityAggregation(..)
375− , MaxAggregation(..)
376 , DateHistogramAggregation(..)
214 , DateHistogramAggregation(..)
377− , DateRangeAggregation(..)
378− , DateRangeAggRange(..)
380− , DateMathAnchor(..)
381− , DateMathModifier(..)
383− , TopHitsAggregation(..)
384− , StatisticsAggregation(..)
387 , Highlights(..)
216 , Highlights(..)
388 , FieldHighlight(..)
217 , FieldHighlight(..)
@@ -396,36 +225,501 @@ module Database.Bloodhound.Types
396 , HighlightTag(..)
225 , HighlightTag(..)
397 , HitHighlight
226 , HitHighlight
400 , TermsResult(..)
228 , TermsResult(..)
401 , DateHistogramResult(..)
229 , DateHistogramResult(..)
402− , DateRangeResult(..)
230+ ) where
403− , TopHitResult(..)
231+
404−
232+import Control.Applicative
405− , EsUsername(..)
233+import Control.Monad.Error
406− , EsPassword(..)
234+import Control.Monad.Reader
407−
235+import Control.Monad.State
408− , Analysis(..)
236+import Control.Monad.Writer
409− , AnalyzerDefinition(..)
237+import Data.Aeson
410− , TokenizerDefinition(..)
238+import Data.Aeson.Types (Pair, emptyObject, parseMaybe)
411− , TokenFilterDefinition(..)
239+import qualified Data.ByteString.Lazy.Char8 as L
412− , CharFilterDefinition(..)
240+import Data.List (nub, foldl')
413− , Ngram(..)
241+import Data.List.NonEmpty (NonEmpty (..), toList)
414− , TokenChar(..)
242+import qualified Data.HashMap.Strict as HM (union)
415− , Shingle(..)
243+import qualified Data.Map.Strict as M
416− , Language(..)
244+import Data.Maybe
417− ) where
245+import Data.Text (Text)
418−
246+import qualified Data.Text as T
419−import Bloodhound.Import
247+import Data.Time.Clock (UTCTime)
420−
248+import qualified Data.Vector as V
421−import Database.Bloodhound.Internal.Aggregation
249+import GHC.Enum
422−import Database.Bloodhound.Internal.Analysis
250+import GHC.Generics (Generic)
423−import Database.Bloodhound.Internal.Client
251+import Network.HTTP.Client
424−import Database.Bloodhound.Internal.Highlight
252+import qualified Network.HTTP.Types.Method as NHTM
425−import Database.Bloodhound.Internal.Newtypes
253+
426−import Database.Bloodhound.Internal.Query
254+import Database.Bloodhound.Types.Class
427−import Database.Bloodhound.Internal.Sort
255+
428−import Database.Bloodhound.Internal.Suggest
256+-- $setup
257+-- >>> :set -XOverloadedStrings
258+-- >>> import Database.Bloodhound
259+-- >>> let testServer = (Server "http://localhost:9200")
260+-- >>> let testIndex = IndexName "twitter"
261+-- >>> let testMapping = MappingName "tweet"
262+-- >>> let defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
264+-- defaultIndexSettings is exported by Database.Bloodhound as well
265+-- no trailing slashes in servers, library handles building the path.
267+{-| Common environment for Elasticsearch calls. Connections will be
268+ pipelined according to the provided HTTP connection manager.
270+data BHEnv = BHEnv { bhServer :: Server
271+ , bhManager :: Manager
274+{-| All API calls to Elasticsearch operate within
275+ MonadBH. The idea is that it can be easily embedded in your
276+ own monad transformer stack. A default instance for a ReaderT and
277+ alias 'BH' is provided for the simple case.
279+class (Functor m, Applicative m, MonadIO m) => MonadBH m where
282+newtype BH m a = BH {
283+ unBH :: ReaderT BHEnv m a
284+ } deriving ( Functor
295+instance MonadTrans BH where
298+instance (MonadReader r m) => MonadReader r (BH m) where
300+ local f (BH (ReaderT m)) = BH $ ReaderT $ \r ->
303+instance (Functor m, Applicative m, MonadIO m) => MonadBH (BH m) where
304+ getBHEnv = BH getBHEnv
307+instance (Functor m, Applicative m, MonadIO m) => MonadBH (ReaderT BHEnv m) where
310+runBH :: BHEnv -> BH m a -> m a
311+runBH e f = runReaderT (unBH f) e
313+{-| 'Version' is embedded in 'Status' -}
314+data Version = Version { number :: Text
315+ , build_hash :: Text
316+ , build_timestamp :: UTCTime
317+ , build_snapshot :: Bool
318+ , lucene_version :: Text } deriving (Eq, Show, Generic)
320+{-| 'Status' is a data type for describing the JSON body returned by
321+ Elasticsearch when you query its status. This was deprecated in 1.2.0.
323+ <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html#indices-status>
326+data Status = Status { ok :: Maybe Bool
329+ , version :: Version
330+ , tagline :: Text } deriving (Eq, Show)
332+{-| 'IndexSettings' is used to configure the shards and replicas when you create
333+ an Elasticsearch Index.
335+ <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
339+ IndexSettings { indexShards :: ShardCount
340+ , indexReplicas :: ReplicaCount } deriving (Eq, Show)
342+{-| 'defaultIndexSettings' is an 'IndexSettings' with 3 shards and 2 replicas. -}
343+defaultIndexSettings :: IndexSettings
344+defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
346+{-| 'Reply' and 'Method' are type synonyms from 'Network.HTTP.Types.Method.Method' -}
347+type Reply = Network.HTTP.Client.Response L.ByteString
348+type Method = NHTM.Method
350+{-| 'OpenCloseIndex' is a sum type for opening and closing indices.
352+ <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
354+data OpenCloseIndex = OpenIndex | CloseIndex deriving (Eq, Show)
356+data FieldType = GeoPointType
362+ | ByteType deriving (Eq, Show)
364+data FieldDefinition =
365+ FieldDefinition { fieldType :: FieldType } deriving (Eq, Show)
367+{-| An 'IndexTemplate' defines a template that will automatically be
368+ applied to new indices created. The templates include both
369+ 'IndexSettings' and mappings, and a simple 'TemplatePattern' that
370+ controls if the template will be applied to the index created.
371+ Specify mappings as follows: @[toJSON TweetMapping, ...]@
373+ https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html
376+ IndexTemplate { templatePattern :: TemplatePattern
377+ , templateSettings :: Maybe IndexSettings
378+ , templateMappings :: [Value]
382+ MappingField { mappingFieldName :: FieldName
383+ , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
385+{-| Support for type reification of 'Mapping's is currently incomplete, for
386+ now the mapping API verbiage expects a 'ToJSON'able blob.
388+ Indexes have mappings, mappings are schemas for the documents contained in the
389+ index. I'd recommend having only one mapping per index, always having a mapping,
390+ and keeping different kinds of documents separated if possible.
392+data Mapping = Mapping { typeName :: TypeName
393+ , mappingFields :: [MappingField] } deriving (Eq, Show)
395+{-| 'BulkOperation' is a sum type for expressing the four kinds of bulk
396+ operation index, create, delete, and update. 'BulkIndex' behaves like an
397+ "upsert", 'BulkCreate' will fail if a document already exists at the DocId.
399+ <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html#docs-bulk>
402+ BulkIndex IndexName MappingName DocId Value
403+ | BulkCreate IndexName MappingName DocId Value
404+ | BulkDelete IndexName MappingName DocId
405+ | BulkUpdate IndexName MappingName DocId Value deriving (Eq, Show)
407+{-| 'EsResult' describes the standard wrapper JSON document that you see in
408+ successful Elasticsearch lookups or lookups that couldn't find the document.
410+data EsResult a = EsResult { _index :: Text
413+ , foundResult :: Maybe (EsResultFound a)} deriving (Eq, Show)
416+{-| 'EsResultFound' contains the document and its metadata inside of an
417+ 'EsResult' when the document was successfully found.
419+data EsResultFound a = EsResultFound { _version :: DocVersion
420+ , _source :: a } deriving (Eq, Show)
424+{-| 'DocVersion' is an integer version number for a document between 1
425+and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
427+newtype DocVersion = DocVersion {
428+ docVersionNumber :: Int
429+ } deriving (Eq, Show, Ord, ToJSON)
431+-- | Smart constructor for in-range doc version
432+mkDocVersion :: Int -> Maybe DocVersion
434+ | i >= (docVersionNumber minBound) && i <= (docVersionNumber maxBound) =
436+ | otherwise = Nothing
439+{-| 'ExternalDocVersion' is a convenience wrapper if your code uses its
440+own version numbers instead of ones from ES.
442+newtype ExternalDocVersion = ExternalDocVersion DocVersion
443+ deriving (Eq, Show, Ord, Bounded, Enum, ToJSON)
445+{-| 'VersionControl' is specified when indexing documents as a
446+optimistic concurrency control.
448+data VersionControl = NoVersionControl
449+ -- ^ Don't send a version. This is a pure overwrite.
450+ | InternalVersion DocVersion
451+ -- ^ Use the default ES versioning scheme. Only
452+ -- index the document if the version is the same
453+ -- as the one specified. Only applicable to
454+ -- updates, as you should be getting Version from
456+ | ExternalGT ExternalDocVersion
457+ -- ^ Use your own version numbering. Only index
458+ -- the document if the version is strictly higher
459+ -- OR the document doesn't exist. The given
460+ -- version will be used as the new version number
461+ -- for the stored document. N.B. All updates must
462+ -- increment this number, meaning there is some
463+ -- global, external ordering of updates.
464+ | ExternalGTE ExternalDocVersion
465+ -- ^ Use your own version numbering. Only index
466+ -- the document if the version is equal or higher
467+ -- than the stored version. Will succeed if there
468+ -- is no existing document. The given version will
469+ -- be used as the new version number for the
470+ -- stored document. Use with care, as this could
471+ -- result in data loss.
472+ | ForceVersion ExternalDocVersion
473+ -- ^ The document will always be indexed and the
474+ -- given version will be the new version. This is
475+ -- typically used for correcting errors. Use with
476+ -- care, as this could result in data loss.
477+ deriving (Show, Eq, Ord)
479+{-| 'DocumentParent' is used to specify a parent document.
481+newtype DocumentParent = DocumentParent DocId
484+{-| 'IndexDocumentSettings' are special settings supplied when indexing
485+a document. For the best backwards compatiblity when new fields are
486+added, you should probably prefer to start with 'defaultIndexDocumentSettings'
488+data IndexDocumentSettings =
489+ IndexDocumentSettings { idsVersionControl :: VersionControl
490+ , idsParent :: Maybe DocumentParent
491+ } deriving (Eq, Show)
493+{-| Reasonable default settings. Chooses no version control and no parent.
495+defaultIndexDocumentSettings :: IndexDocumentSettings
496+defaultIndexDocumentSettings = IndexDocumentSettings NoVersionControl Nothing
498+{-| 'Sort' is a synonym for a list of 'SortSpec's. Sort behavior is order
499+ dependent with later sorts acting as tie-breakers for earlier sorts.
501+type Sort = [SortSpec]
503+{-| The two main kinds of 'SortSpec' are 'DefaultSortSpec' and
504+ 'GeoDistanceSortSpec'. The latter takes a 'SortOrder', 'GeoPoint', and
505+ 'DistanceUnit' to express "nearness" to a single geographical point as a
508+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
510+data SortSpec = DefaultSortSpec DefaultSort
511+ | GeoDistanceSortSpec SortOrder GeoPoint DistanceUnit deriving (Eq, Show)
513+{-| 'DefaultSort' is usually the kind of 'SortSpec' you'll want. There's a
514+ 'mkSort' convenience function for when you want to specify only the most
517+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
520+ DefaultSort { sortFieldName :: FieldName
521+ , sortOrder :: SortOrder
523+ , ignoreUnmapped :: Bool
524+ , sortMode :: Maybe SortMode
525+ , missingSort :: Maybe Missing
526+ , nestedFilter :: Maybe Filter } deriving (Eq, Show)
528+{-| 'SortOrder' is 'Ascending' or 'Descending', as you might expect. These get
529+ encoded into "asc" or "desc" when turned into JSON.
531+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
533+data SortOrder = Ascending
534+ | Descending deriving (Eq, Show)
536+{-| 'Missing' prescribes how to handle missing fields. A missing field can be
537+ sorted last, first, or using a custom value as a substitute.
539+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_missing_values>
541+data Missing = LastMissing
543+ | CustomMissing Text deriving (Eq, Show)
545+{-| 'SortMode' prescribes how to handle sorting array/multi-valued fields.
547+http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_sort_mode_option
549+data SortMode = SortMin
552+ | SortAvg deriving (Eq, Show)
554+{-| 'mkSort' defaults everything but the 'FieldName' and the 'SortOrder' so
555+ that you can concisely describe the usual kind of 'SortSpec's you want.
557+mkSort :: FieldName -> SortOrder -> DefaultSort
558+mkSort fieldName sOrder = DefaultSort fieldName sOrder False Nothing Nothing Nothing
560+{-| 'Cache' is for telling ES whether it should cache a 'Filter' not.
561+ 'Query's cannot be cached.
563+type Cache = Bool -- caching on/off
564+defaultCache :: Cache
567+{-| 'PrefixValue' is used in 'PrefixQuery' as the main query component.
569+type PrefixValue = Text
571+{-| 'BooleanOperator' is the usual And/Or operators with an ES compatible
572+ JSON encoding baked in. Used all over the place.
574+data BooleanOperator = And | Or deriving (Eq, Show)
576+{-| 'ShardCount' is part of 'IndexSettings'
578+newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic)
580+{-| 'ReplicaCount' is part of 'IndexSettings'
582+newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic)
584+{-| 'Server' is used with the client functions to point at the ES instance
586+newtype Server = Server Text deriving (Eq, Show)
588+{-| 'IndexName' is used to describe which index to query/create/delete
590+newtype IndexName = IndexName Text deriving (Eq, Generic, Show)
592+{-| 'TemplateName' is used to describe which template to query/create/delete
594+newtype TemplateName = TemplateName Text deriving (Eq, Show, Generic)
596+{-| 'TemplatePattern' represents a pattern which is matched against index names
598+newtype TemplatePattern = TemplatePattern Text deriving (Eq, Show, Generic)
600+{-| 'MappingName' is part of mappings which are how ES describes and schematizes
601+ the data in the indices.
603+newtype MappingName = MappingName Text deriving (Eq, Generic, Show)
605+{-| 'DocId' is a generic wrapper value for expressing unique Document IDs.
606+ Can be set by the user or created by ES itself. Often used in client
607+ functions for poking at specific documents.
609+newtype DocId = DocId Text deriving (Eq, Generic, Show)
611+{-| 'QueryString' is used to wrap query text bodies, be they human written or not.
613+newtype QueryString = QueryString Text deriving (Eq, Generic, Show)
615+{-| 'FieldName' is used all over the place wherever a specific field within
616+ a document needs to be specified, usually in 'Query's or 'Filter's.
618+newtype FieldName = FieldName Text deriving (Eq, Show)
621+{-| 'Script' is often used in place of 'FieldName' to specify more
622+complex ways of extracting a value from a document.
624+newtype Script = Script { scriptText :: Text } deriving (Eq, Show)
626+{-| 'CacheName' is used in 'RegexpFilter' for describing the
627+ 'CacheKey' keyed caching behavior.
629+newtype CacheName = CacheName Text deriving (Eq, Show)
631+{-| 'CacheKey' is used in 'RegexpFilter' to key regex caching.
634+ CacheKey Text deriving (Eq, Show)
636+ Existence Bool deriving (Eq, Show)
638+ NullValue Bool deriving (Eq, Show)
639+newtype CutoffFrequency =
640+ CutoffFrequency Double deriving (Eq, Show, Generic)
642+ Analyzer Text deriving (Eq, Show, Generic)
643+newtype MaxExpansions =
644+ MaxExpansions Int deriving (Eq, Show, Generic)
646+{-| 'Lenient', if set to true, will cause format based failures to be
647+ ignored. I don't know what the bloody default is, Elasticsearch
648+ documentation didn't say what it was. Let me know if you figure it out.
651+ Lenient Bool deriving (Eq, Show, Generic)
653+ Tiebreaker Double deriving (Eq, Show, Generic)
655+ Boost Double deriving (Eq, Show, Generic)
657+ BoostTerms Double deriving (Eq, Show, Generic)
659+{-| 'MinimumMatch' controls how many should clauses in the bool query should
660+ match. Can be an absolute value (2) or a percentage (30%) or a
661+ combination of both.
663+newtype MinimumMatch =
664+ MinimumMatch Int deriving (Eq, Show, Generic)
665+newtype MinimumMatchText =
666+ MinimumMatchText Text deriving (Eq, Show)
667+newtype DisableCoord =
668+ DisableCoord Bool deriving (Eq, Show, Generic)
669+newtype IgnoreTermFrequency =
670+ IgnoreTermFrequency Bool deriving (Eq, Show, Generic)
671+newtype MinimumTermFrequency =
672+ MinimumTermFrequency Int deriving (Eq, Show, Generic)
673+newtype MaxQueryTerms =
674+ MaxQueryTerms Int deriving (Eq, Show, Generic)
676+ Fuzziness Double deriving (Eq, Show, Generic)
678+{-| 'PrefixLength' is the prefix length used in queries, defaults to 0. -}
679+newtype PrefixLength =
680+ PrefixLength Int deriving (Eq, Show, Generic)
682+ TypeName Text deriving (Eq, Show, Generic)
683+newtype PercentMatch =
684+ PercentMatch Double deriving (Eq, Show, Generic)
686+ StopWord Text deriving (Eq, Show, Generic)
688+ QueryPath Text deriving (Eq, Show, Generic)
690+{-| Allowing a wildcard at the beginning of a word (eg "*ing") is particularly
691+ heavy, because all terms in the index need to be examined, just in case
692+ they match. Leading wildcards can be disabled by setting
693+ 'AllowLeadingWildcard' to false. -}
694+newtype AllowLeadingWildcard =
695+ AllowLeadingWildcard Bool deriving (Eq, Show, Generic)
696+newtype LowercaseExpanded =
697+ LowercaseExpanded Bool deriving (Eq, Show, Generic)
698+newtype EnablePositionIncrements =
699+ EnablePositionIncrements Bool deriving (Eq, Show, Generic)
701+{-| By default, wildcard terms in a query are not analyzed.
702+ Setting 'AnalyzeWildcard' to true enables best-effort analysis.
704+newtype AnalyzeWildcard = AnalyzeWildcard Bool deriving (Eq, Show, Generic)
706+{-| 'GeneratePhraseQueries' defaults to false.
708+newtype GeneratePhraseQueries =
709+ GeneratePhraseQueries Bool deriving (Eq, Show, Generic)
711+{-| 'Locale' is used for string conversions - defaults to ROOT.
713+newtype Locale = Locale Text deriving (Eq, Show, Generic)
714+newtype MaxWordLength = MaxWordLength Int deriving (Eq, Show, Generic)
715+newtype MinWordLength = MinWordLength Int deriving (Eq, Show, Generic)
717+{-| 'PhraseSlop' sets the default slop for phrases, 0 means exact
718+ phrase matches. Default is 0.
720+newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show, Generic)
721+newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show, Generic)
722+newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show, Generic)
430{-| 'unpackId' is a silly convenience function that gets used once.
724{-| 'unpackId' is a silly convenience function that gets used once.
@@ -433,6 +727,8 @@ unpackId :: DocId -> Text
433unpackId (DocId docId) = docId
727unpackId (DocId docId) = docId
435type TrackSortScores = Bool
729type TrackSortScores = Bool
730+newtype From = From Int deriving (Eq, Show, ToJSON)
731+newtype Size = Size Int deriving (Eq, Show, ToJSON)
437data Search = Search { queryBody :: Maybe Query
733data Search = Search { queryBody :: Maybe Query
438 , filterBody :: Maybe Filter
734 , filterBody :: Maybe Filter
@@ -444,87 +740,1638 @@ data Search = Search { queryBody :: Maybe Query
444 , from :: From
740 , from :: From
445 , size :: Size
741 , size :: Size
446 , searchType :: SearchType
742 , searchType :: SearchType
447− , searchAfterKey :: Maybe SearchAfterKey
448 , fields :: Maybe [FieldName]
743 , fields :: Maybe [FieldName]
449− , scriptFields :: Maybe ScriptFields
450− , source :: Maybe Source
744+ , source :: Maybe Source } deriving (Eq, Show)
451− , suggestBody :: Maybe Suggest -- ^ Only one Suggestion request / response per Search is supported.
452− } deriving (Eq, Show)
455−instance ToJSON Search where
456− toJSON (Search mquery sFilter sort searchAggs
457− highlight sTrackSortScores sFrom sSize _ sAfter sFields
458− sScriptFields sSource sSuggest) =
459− omitNulls [ "query" .= query'
461− , "aggregations" .= searchAggs
462− , "highlight" .= highlight
465− , "track_scores" .= sTrackSortScores
466− , "search_after" .= sAfter
467− , "fields" .= sFields
468− , "script_fields" .= sScriptFields
469− , "_source" .= sSource
470− , "suggest" .= sSuggest]
472− where query' = case sFilter of
477− $ mkBoolQuery (maybeToList mquery)
480data SearchType = SearchTypeQueryThenFetch
746data SearchType = SearchTypeQueryThenFetch
481 | SearchTypeDfsQueryThenFetch
747 | SearchTypeDfsQueryThenFetch
750+ | SearchTypeQueryAndFetch
751+ | SearchTypeDfsQueryAndFetch
482 deriving (Eq, Show)
752 deriving (Eq, Show)
484data Source =
754data Source =
485− NoSource
755+ NoSource
486 | SourcePatterns PatternOrPatterns
756 | SourcePatterns PatternOrPatterns
487 | SourceIncludeExclude Include Exclude
757 | SourceIncludeExclude Include Exclude
488− deriving (Eq, Show)
758+ deriving (Show, Eq)
760+data PatternOrPatterns = PopPattern Pattern
761+ | PopPatterns [Pattern] deriving (Eq, Show)
763+data Include = Include [Pattern] deriving (Eq, Show)
764+data Exclude = Exclude [Pattern] deriving (Eq, Show)
766+newtype Pattern = Pattern Text deriving (Eq, Show)
768+data Highlights = Highlights { globalsettings :: Maybe HighlightSettings
769+ , highlightFields :: [FieldHighlight]
770+ } deriving (Show, Eq)
772+data FieldHighlight = FieldHighlight FieldName (Maybe HighlightSettings)
776+data HighlightSettings = Plain PlainHighlight
777+ | Postings PostingsHighlight
778+ | FastVector FastVectorHighlight
780+data PlainHighlight =
781+ PlainHighlight { plainCommon :: Maybe CommonHighlight
782+ , plainNonPost :: Maybe NonPostings } deriving (Show, Eq)
784+ -- This requires that index_options are set to 'offset' in the mapping.
785+data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Show, Eq)
787+-- This requires that term_vector is set to 'with_positions_offsets' in the mapping.
788+data FastVectorHighlight =
789+ FastVectorHighlight { fvCommon :: Maybe CommonHighlight
790+ , fvNonPostSettings :: Maybe NonPostings
791+ , boundaryChars :: Maybe Text
792+ , boundaryMaxScan :: Maybe Int
793+ , fragmentOffset :: Maybe Int
794+ , matchedFields :: [Text]
795+ , phraseLimit :: Maybe Int
796+ } deriving (Show, Eq)
798+data CommonHighlight =
799+ CommonHighlight { order :: Maybe Text
800+ , forceSource :: Maybe Bool
801+ , tag :: Maybe HighlightTag
802+ , encoder :: Maybe HighlightEncoder
803+ , noMatchSize :: Maybe Int
804+ , highlightQuery :: Maybe Query
805+ , requireFieldMatch :: Maybe Bool
806+ } deriving (Show, Eq)
808+-- Settings that are only applicable to FastVector and Plain highlighters.
810+ NonPostings { fragmentSize :: Maybe Int
811+ , numberOfFragments :: Maybe Int} deriving (Show, Eq)
813+data HighlightEncoder = DefaultEncoder
817+-- NOTE: Should the tags use some kind of HTML type, rather than Text?
818+data HighlightTag = TagSchema Text
819+ | CustomTags ([Text], [Text]) -- Only uses more than the first value in the lists if fvh
824+ TermQuery Term (Maybe Boost)
825+ | TermsQuery (NonEmpty Term)
826+ | QueryMatchQuery MatchQuery
827+ | QueryMultiMatchQuery MultiMatchQuery
828+ | QueryBoolQuery BoolQuery
829+ | QueryBoostingQuery BoostingQuery
830+ | QueryCommonTermsQuery CommonTermsQuery
831+ | ConstantScoreFilter Filter Boost
832+ | ConstantScoreQuery Query Boost
833+ | QueryDisMaxQuery DisMaxQuery
834+ | QueryFilteredQuery FilteredQuery
835+ | QueryFuzzyLikeThisQuery FuzzyLikeThisQuery
836+ | QueryFuzzyLikeFieldQuery FuzzyLikeFieldQuery
837+ | QueryFuzzyQuery FuzzyQuery
838+ | QueryHasChildQuery HasChildQuery
839+ | QueryHasParentQuery HasParentQuery
840+ | IdsQuery MappingName [DocId]
841+ | QueryIndicesQuery IndicesQuery
842+ | MatchAllQuery (Maybe Boost)
843+ | QueryMoreLikeThisQuery MoreLikeThisQuery
844+ | QueryMoreLikeThisFieldQuery MoreLikeThisFieldQuery
845+ | QueryNestedQuery NestedQuery
846+ | QueryPrefixQuery PrefixQuery
847+ | QueryQueryStringQuery QueryStringQuery
848+ | QuerySimpleQueryStringQuery SimpleQueryStringQuery
849+ | QueryRangeQuery RangeQuery
850+ | QueryRegexpQuery RegexpQuery
854+ RegexpQuery { regexpQueryField :: FieldName
855+ , regexpQuery :: Regexp
856+ , regexpQueryFlags :: RegexpFlags
857+ , regexpQueryBoost :: Maybe Boost
858+ } deriving (Eq, Show)
861+ RangeQuery { rangeQueryField :: FieldName
862+ , rangeQueryRange :: RangeValue
863+ , rangeQueryBoost :: Boost } deriving (Eq, Show)
865+mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
866+mkRangeQuery f r = RangeQuery f r (Boost 1.0)
868+data SimpleQueryStringQuery =
869+ SimpleQueryStringQuery
870+ { simpleQueryStringQuery :: QueryString
871+ , simpleQueryStringField :: Maybe FieldOrFields
872+ , simpleQueryStringOperator :: Maybe BooleanOperator
873+ , simpleQueryStringAnalyzer :: Maybe Analyzer
874+ , simpleQueryStringFlags :: Maybe [SimpleQueryFlag]
875+ , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
876+ , simpleQueryStringLocale :: Maybe Locale
877+ } deriving (Eq, Show)
879+data SimpleQueryFlag =
886+ | SimpleQueryPrecedence
888+ | SimpleQueryWhitespace
891+ | SimpleQuerySlop deriving (Eq, Show)
893+-- use_dis_max and tie_breaker when fields are plural?
894+data QueryStringQuery =
896+ { queryStringQuery :: QueryString
897+ , queryStringDefaultField :: Maybe FieldName
898+ , queryStringOperator :: Maybe BooleanOperator
899+ , queryStringAnalyzer :: Maybe Analyzer
900+ , queryStringAllowLeadingWildcard :: Maybe AllowLeadingWildcard
901+ , queryStringLowercaseExpanded :: Maybe LowercaseExpanded
902+ , queryStringEnablePositionIncrements :: Maybe EnablePositionIncrements
903+ , queryStringFuzzyMaxExpansions :: Maybe MaxExpansions
904+ , queryStringFuzziness :: Maybe Fuzziness
905+ , queryStringFuzzyPrefixLength :: Maybe PrefixLength
906+ , queryStringPhraseSlop :: Maybe PhraseSlop
907+ , queryStringBoost :: Maybe Boost
908+ , queryStringAnalyzeWildcard :: Maybe AnalyzeWildcard
909+ , queryStringGeneratePhraseQueries :: Maybe GeneratePhraseQueries
910+ , queryStringMinimumShouldMatch :: Maybe MinimumMatch
911+ , queryStringLenient :: Maybe Lenient
912+ , queryStringLocale :: Maybe Locale
913+ } deriving (Eq, Show)
915+mkQueryStringQuery :: QueryString -> QueryStringQuery
916+mkQueryStringQuery qs =
917+ QueryStringQuery qs Nothing Nothing
918+ Nothing Nothing Nothing Nothing
919+ Nothing Nothing Nothing Nothing
920+ Nothing Nothing Nothing Nothing
923+data FieldOrFields = FofField FieldName
924+ | FofFields [FieldName] deriving (Eq, Show)
928+ { prefixQueryField :: FieldName
929+ , prefixQueryPrefixValue :: Text
930+ , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show)
934+ { nestedQueryPath :: QueryPath
935+ , nestedQueryScoreType :: ScoreType
936+ , nestedQuery :: Query } deriving (Eq, Show)
938+data MoreLikeThisFieldQuery =
939+ MoreLikeThisFieldQuery
940+ { moreLikeThisFieldText :: Text
941+ , moreLikeThisFieldFields :: FieldName
942+ -- default 0.3 (30%)
943+ , moreLikeThisFieldPercentMatch :: Maybe PercentMatch
944+ , moreLikeThisFieldMinimumTermFreq :: Maybe MinimumTermFrequency
945+ , moreLikeThisFieldMaxQueryTerms :: Maybe MaxQueryTerms
946+ , moreLikeThisFieldStopWords :: Maybe [StopWord]
947+ , moreLikeThisFieldMinDocFrequency :: Maybe MinDocFrequency
948+ , moreLikeThisFieldMaxDocFrequency :: Maybe MaxDocFrequency
949+ , moreLikeThisFieldMinWordLength :: Maybe MinWordLength
950+ , moreLikeThisFieldMaxWordLength :: Maybe MaxWordLength
951+ , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
952+ , moreLikeThisFieldBoost :: Maybe Boost
953+ , moreLikeThisFieldAnalyzer :: Maybe Analyzer
954+ } deriving (Eq, Show)
956+data MoreLikeThisQuery =
958+ { moreLikeThisText :: Text
959+ , moreLikeThisFields :: Maybe [FieldName]
960+ -- default 0.3 (30%)
961+ , moreLikeThisPercentMatch :: Maybe PercentMatch
962+ , moreLikeThisMinimumTermFreq :: Maybe MinimumTermFrequency
963+ , moreLikeThisMaxQueryTerms :: Maybe MaxQueryTerms
964+ , moreLikeThisStopWords :: Maybe [StopWord]
965+ , moreLikeThisMinDocFrequency :: Maybe MinDocFrequency
966+ , moreLikeThisMaxDocFrequency :: Maybe MaxDocFrequency
967+ , moreLikeThisMinWordLength :: Maybe MinWordLength
968+ , moreLikeThisMaxWordLength :: Maybe MaxWordLength
969+ , moreLikeThisBoostTerms :: Maybe BoostTerms
970+ , moreLikeThisBoost :: Maybe Boost
971+ , moreLikeThisAnalyzer :: Maybe Analyzer
972+ } deriving (Eq, Show)
976+ { indicesQueryIndices :: [IndexName]
977+ , indicesQuery :: Query
979+ , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show)
981+data HasParentQuery =
983+ { hasParentQueryType :: TypeName
984+ , hasParentQuery :: Query
985+ , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show)
989+ { hasChildQueryType :: TypeName
990+ , hasChildQuery :: Query
991+ , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show)
997+ | ScoreTypeNone deriving (Eq, Show)
1000+ FuzzyQuery { fuzzyQueryField :: FieldName
1001+ , fuzzyQueryValue :: Text
1002+ , fuzzyQueryPrefixLength :: PrefixLength
1003+ , fuzzyQueryMaxExpansions :: MaxExpansions
1004+ , fuzzyQueryFuzziness :: Fuzziness
1005+ , fuzzyQueryBoost :: Maybe Boost
1006+ } deriving (Eq, Show)
1008+data FuzzyLikeFieldQuery =
1009+ FuzzyLikeFieldQuery
1010+ { fuzzyLikeField :: FieldName
1011+ -- anaphora is good for the soul.
1012+ , fuzzyLikeFieldText :: Text
1013+ , fuzzyLikeFieldMaxQueryTerms :: MaxQueryTerms
1014+ , fuzzyLikeFieldIgnoreTermFrequency :: IgnoreTermFrequency
1015+ , fuzzyLikeFieldFuzziness :: Fuzziness
1016+ , fuzzyLikeFieldPrefixLength :: PrefixLength
1017+ , fuzzyLikeFieldBoost :: Boost
1018+ , fuzzyLikeFieldAnalyzer :: Maybe Analyzer
1019+ } deriving (Eq, Show)
1021+data FuzzyLikeThisQuery =
1023+ { fuzzyLikeFields :: [FieldName]
1024+ , fuzzyLikeText :: Text
1025+ , fuzzyLikeMaxQueryTerms :: MaxQueryTerms
1026+ , fuzzyLikeIgnoreTermFrequency :: IgnoreTermFrequency
1027+ , fuzzyLikeFuzziness :: Fuzziness
1028+ , fuzzyLikePrefixLength :: PrefixLength
1029+ , fuzzyLikeBoost :: Boost
1030+ , fuzzyLikeAnalyzer :: Maybe Analyzer
1031+ } deriving (Eq, Show)
1033+data FilteredQuery =
1035+ { filteredQuery :: Query
1036+ , filteredFilter :: Filter } deriving (Eq, Show)
1039+ DisMaxQuery { disMaxQueries :: [Query]
1041+ , disMaxTiebreaker :: Tiebreaker
1042+ , disMaxBoost :: Maybe Boost
1043+ } deriving (Eq, Show)
1046+ MatchQuery { matchQueryField :: FieldName
1047+ , matchQueryQueryString :: QueryString
1048+ , matchQueryOperator :: BooleanOperator
1049+ , matchQueryZeroTerms :: ZeroTermsQuery
1050+ , matchQueryCutoffFrequency :: Maybe CutoffFrequency
1051+ , matchQueryMatchType :: Maybe MatchQueryType
1052+ , matchQueryAnalyzer :: Maybe Analyzer
1053+ , matchQueryMaxExpansions :: Maybe MaxExpansions
1054+ , matchQueryLenient :: Maybe Lenient
1055+ , matchQueryBoost :: Maybe Boost } deriving (Eq, Show)
1057+{-| 'mkMatchQuery' is a convenience function that defaults the less common parameters,
1058+ enabling you to provide only the 'FieldName' and 'QueryString' to make a 'MatchQuery'
1060+mkMatchQuery :: FieldName -> QueryString -> MatchQuery
1061+mkMatchQuery field query = MatchQuery field query Or ZeroTermsNone Nothing Nothing Nothing Nothing Nothing Nothing
1063+data MatchQueryType =
1065+ | MatchPhrasePrefix deriving (Eq, Show)
1067+data MultiMatchQuery =
1068+ MultiMatchQuery { multiMatchQueryFields :: [FieldName]
1069+ , multiMatchQueryString :: QueryString
1070+ , multiMatchQueryOperator :: BooleanOperator
1071+ , multiMatchQueryZeroTerms :: ZeroTermsQuery
1072+ , multiMatchQueryTiebreaker :: Maybe Tiebreaker
1073+ , multiMatchQueryType :: Maybe MultiMatchQueryType
1074+ , multiMatchQueryCutoffFrequency :: Maybe CutoffFrequency
1075+ , multiMatchQueryAnalyzer :: Maybe Analyzer
1076+ , multiMatchQueryMaxExpansions :: Maybe MaxExpansions
1077+ , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show)
1079+{-| 'mkMultiMatchQuery' is a convenience function that defaults the less common parameters,
1080+ enabling you to provide only the list of 'FieldName's and 'QueryString' to
1081+ make a 'MultiMatchQuery'.
1084+mkMultiMatchQuery :: [FieldName] -> QueryString -> MultiMatchQuery
1085+mkMultiMatchQuery matchFields query =
1086+ MultiMatchQuery matchFields query
1087+ Or ZeroTermsNone Nothing Nothing Nothing Nothing Nothing Nothing
1089+data MultiMatchQueryType =
1090+ MultiMatchBestFields
1091+ | MultiMatchMostFields
1092+ | MultiMatchCrossFields
1094+ | MultiMatchPhrasePrefix deriving (Eq, Show)
1097+ BoolQuery { boolQueryMustMatch :: [Query]
1098+ , boolQueryMustNotMatch :: [Query]
1099+ , boolQueryShouldMatch :: [Query]
1100+ , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
1101+ , boolQueryBoost :: Maybe Boost
1102+ , boolQueryDisableCoord :: Maybe DisableCoord
1103+ } deriving (Eq, Show)
1105+mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
1106+mkBoolQuery must mustNot should =
1107+ BoolQuery must mustNot should Nothing Nothing Nothing
1109+data BoostingQuery =
1110+ BoostingQuery { positiveQuery :: Query
1111+ , negativeQuery :: Query
1112+ , negativeBoost :: Boost } deriving (Eq, Show)
1114+data CommonTermsQuery =
1115+ CommonTermsQuery { commonField :: FieldName
1116+ , commonQuery :: QueryString
1117+ , commonCutoffFrequency :: CutoffFrequency
1118+ , commonLowFreqOperator :: BooleanOperator
1119+ , commonHighFreqOperator :: BooleanOperator
1120+ , commonMinimumShouldMatch :: Maybe CommonMinimumMatch
1121+ , commonBoost :: Maybe Boost
1122+ , commonAnalyzer :: Maybe Analyzer
1123+ , commonDisableCoord :: Maybe DisableCoord
1124+ } deriving (Eq, Show)
1126+data CommonMinimumMatch =
1127+ CommonMinimumMatchHighLow MinimumMatchHighLow
1128+ | CommonMinimumMatch MinimumMatch
1129+ deriving (Eq, Show)
1131+data MinimumMatchHighLow =
1132+ MinimumMatchHighLow { lowFreq :: MinimumMatch
1133+ , highFreq :: MinimumMatch } deriving (Eq, Show)
1135+data Filter = AndFilter [Filter] Cache
1136+ | OrFilter [Filter] Cache
1137+ | NotFilter Filter Cache
1139+ | BoolFilter BoolMatch
1140+ | ExistsFilter FieldName -- always cached
1141+ | GeoBoundingBoxFilter GeoBoundingBoxConstraint
1142+ | GeoDistanceFilter GeoPoint Distance DistanceType OptimizeBbox Cache
1143+ | GeoDistanceRangeFilter GeoPoint DistanceRange
1144+ | GeoPolygonFilter FieldName [LatLon]
1145+ | IdsFilter MappingName [DocId]
1147+ | MissingFilter FieldName Existence NullValue
1148+ | PrefixFilter FieldName PrefixValue Cache
1149+ | QueryFilter Query Cache
1150+ | RangeFilter FieldName RangeValue RangeExecution Cache
1151+ | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
1152+ | TermFilter Term Cache
1153+ deriving (Eq, Show)
1155+data ZeroTermsQuery = ZeroTermsNone
1156+ | ZeroTermsAll deriving (Eq, Show)
1158+data RangeExecution = RangeExecutionIndex
1159+ | RangeExecutionFielddata deriving (Eq, Show)
1161+newtype Regexp = Regexp Text deriving (Eq, Show)
1163+data RegexpFlags = AllRegexpFlags
1165+ | SomeRegexpFlags (NonEmpty RegexpFlag) deriving (Eq, Show)
1167+data RegexpFlag = AnyString
1172+ | Interval deriving (Eq, Show)
1174+newtype LessThan = LessThan Double deriving (Eq, Show)
1175+newtype LessThanEq = LessThanEq Double deriving (Eq, Show)
1176+newtype GreaterThan = GreaterThan Double deriving (Eq, Show)
1177+newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show)
1179+newtype LessThanD = LessThanD UTCTime deriving (Eq, Show)
1180+newtype LessThanEqD = LessThanEqD UTCTime deriving (Eq, Show)
1181+newtype GreaterThanD = GreaterThanD UTCTime deriving (Eq, Show)
1182+newtype GreaterThanEqD = GreaterThanEqD UTCTime deriving (Eq, Show)
1184+data RangeValue = RangeDateLte LessThanEqD
1185+ | RangeDateLt LessThanD
1186+ | RangeDateGte GreaterThanEqD
1187+ | RangeDateGt GreaterThanD
1188+ | RangeDateGtLt GreaterThanD LessThanD
1189+ | RangeDateGteLte GreaterThanEqD LessThanEqD
1190+ | RangeDateGteLt GreaterThanEqD LessThanD
1191+ | RangeDateGtLte GreaterThanD LessThanEqD
1192+ | RangeDoubleLte LessThanEq
1193+ | RangeDoubleLt LessThan
1194+ | RangeDoubleGte GreaterThanEq
1195+ | RangeDoubleGt GreaterThan
1196+ | RangeDoubleGtLt GreaterThan LessThan
1197+ | RangeDoubleGteLte GreaterThanEq LessThanEq
1198+ | RangeDoubleGteLt GreaterThanEq LessThan
1199+ | RangeDoubleGtLte GreaterThan LessThanEq
1200+ deriving (Eq, Show)
1202+rangeValueToPair :: RangeValue -> [Pair]
1203+rangeValueToPair rv = case rv of
1204+ RangeDateLte (LessThanEqD t) -> ["lte" .= t]
1205+ RangeDateGte (GreaterThanEqD t) -> ["gte" .= t]
1206+ RangeDateLt (LessThanD t) -> ["lt" .= t]
1207+ RangeDateGt (GreaterThanD t) -> ["gt" .= t]
1208+ RangeDateGteLte (GreaterThanEqD l) (LessThanEqD g) -> ["gte" .= l, "lte" .= g]
1209+ RangeDateGtLte (GreaterThanD l) (LessThanEqD g) -> ["gt" .= l, "lte" .= g]
1210+ RangeDateGteLt (GreaterThanEqD l) (LessThanD g) -> ["gte" .= l, "lt" .= g]
1211+ RangeDateGtLt (GreaterThanD l) (LessThanD g) -> ["gt" .= l, "lt" .= g]
1212+ RangeDoubleLte (LessThanEq t) -> ["lte" .= t]
1213+ RangeDoubleGte (GreaterThanEq t) -> ["gte" .= t]
1214+ RangeDoubleLt (LessThan t) -> ["lt" .= t]
1215+ RangeDoubleGt (GreaterThan t) -> ["gt" .= t]
1216+ RangeDoubleGteLte (GreaterThanEq l) (LessThanEq g) -> ["gte" .= l, "lte" .= g]
1217+ RangeDoubleGtLte (GreaterThan l) (LessThanEq g) -> ["gt" .= l, "lte" .= g]
1218+ RangeDoubleGteLt (GreaterThanEq l) (LessThan g) -> ["gte" .= l, "lt" .= g]
1219+ RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
1221+data Term = Term { termField :: Text
1222+ , termValue :: Text } deriving (Eq, Show)
1224+data BoolMatch = MustMatch Term Cache
1225+ | MustNotMatch Term Cache
1226+ | ShouldMatch [Term] Cache deriving (Eq, Show)
1228+-- "memory" or "indexed"
1229+data GeoFilterType = GeoFilterMemory
1230+ | GeoFilterIndexed deriving (Eq, Show)
1232+data LatLon = LatLon { lat :: Double
1233+ , lon :: Double } deriving (Eq, Show)
1235+data GeoBoundingBox =
1236+ GeoBoundingBox { topLeft :: LatLon
1237+ , bottomRight :: LatLon } deriving (Eq, Show)
1239+data GeoBoundingBoxConstraint =
1240+ GeoBoundingBoxConstraint { geoBBField :: FieldName
1241+ , constraintBox :: GeoBoundingBox
1242+ , bbConstraintcache :: Cache
1243+ , geoType :: GeoFilterType
1244+ } deriving (Eq, Show)
1247+ GeoPoint { geoField :: FieldName
1248+ , latLon :: LatLon} deriving (Eq, Show)
1250+data DistanceUnit = Miles
1258+ | NauticalMiles deriving (Eq, Show)
1260+data DistanceType = Arc
1261+ | SloppyArc -- doesn't exist <1.0
1262+ | Plane deriving (Eq, Show)
1264+data OptimizeBbox = OptimizeGeoFilterType GeoFilterType
1265+ | NoOptimizeBbox deriving (Eq, Show)
1268+ Distance { coefficient :: Double
1269+ , unit :: DistanceUnit } deriving (Eq, Show)
1271+data DistanceRange =
1272+ DistanceRange { distanceFrom :: Distance
1273+ , distanceTo :: Distance } deriving (Eq, Show)
1275+data SearchResult a =
1276+ SearchResult { took :: Int
1278+ , shards :: ShardResult
1279+ , searchHits :: SearchHits a
1280+ , aggregations :: Maybe AggregationResults
1281+ , scrollId :: Maybe ScrollId } deriving (Eq, Show)
1283+type ScrollId = Text -- Fixme: Newtype
1285+type Score = Maybe Double
1288+ SearchHits { hitsTotal :: Int
1289+ , maxScore :: Score
1290+ , hits :: [Hit a] } deriving (Eq, Show)
1293+instance Monoid (SearchHits a) where
1294+ mempty = SearchHits 0 Nothing mempty
1295+ mappend (SearchHits ta ma ha) (SearchHits tb mb hb) =
1296+ SearchHits (ta + tb) (max ma mb) (ha <> hb)
1300+ Hit { hitIndex :: IndexName
1301+ , hitType :: MappingName
1302+ , hitDocId :: DocId
1303+ , hitScore :: Score
1305+ , hitHighlight :: Maybe HitHighlight } deriving (Eq, Show)
1308+ ShardResult { shardTotal :: Int
1309+ , shardsSuccessful :: Int
1310+ , shardsFailed :: Int } deriving (Eq, Show, Generic)
1312+type HitHighlight = M.Map Text [Text]
1314+showText :: Show a => a -> Text
1315+showText = T.pack . show
1317+type Aggregations = M.Map Text Aggregation
1319+emptyAggregations :: Aggregations
1320+emptyAggregations = M.empty
1322+mkAggregations :: Text -> Aggregation -> Aggregations
1323+mkAggregations name aggregation = M.insert name aggregation emptyAggregations
1325+data TermOrder = TermOrder{ termSortField :: Text
1326+ , termSortOrder :: SortOrder } deriving (Eq, Show)
1328+data TermInclusion = TermInclusion Text
1329+ | TermPattern Text Text deriving (Eq, Show)
1331+data CollectionMode = BreadthFirst
1332+ | DepthFirst deriving (Eq, Show)
1334+data ExecutionHint = Ordinals
1336+ | GlobalOrdinalsHash
1337+ | GlobalOrdinalsLowCardinality
1338+ | Map deriving (Eq, Show)
1340+data TimeInterval = Weeks
1344+ | Seconds deriving (Eq)
1346+data Interval = Year
1354+ | FractionalInterval Float TimeInterval deriving (Eq, Show)
1356+data Aggregation = TermsAgg TermsAggregation
1357+ | DateHistogramAgg DateHistogramAggregation
1358+ | ValueCountAgg ValueCountAggregation
1359+ | FilterAgg FilterAggregation deriving (Eq, Show)
1362+data TermsAggregation = TermsAggregation { term :: Either Text Text
1363+ , termInclude :: Maybe TermInclusion
1364+ , termExclude :: Maybe TermInclusion
1365+ , termOrder :: Maybe TermOrder
1366+ , termMinDocCount :: Maybe Int
1367+ , termSize :: Maybe Int
1368+ , termShardSize :: Maybe Int
1369+ , termCollectMode :: Maybe CollectionMode
1370+ , termExecutionHint :: Maybe ExecutionHint
1371+ , termAggs :: Maybe Aggregations
1372+ } deriving (Eq, Show)
1374+data DateHistogramAggregation = DateHistogramAggregation { dateField :: FieldName
1375+ , dateInterval :: Interval
1376+ , dateFormat :: Maybe Text
1377+ -- pre and post deprecated in 1.5
1378+ , datePreZone :: Maybe Text
1379+ , datePostZone :: Maybe Text
1380+ , datePreOffset :: Maybe Text
1381+ , datePostOffset :: Maybe Text
1382+ , dateAggs :: Maybe Aggregations
1383+ } deriving (Eq, Show)
1385+-- | See <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html> for more information.
1386+data ValueCountAggregation = FieldValueCount FieldName
1387+ | ScriptValueCount Script deriving (Eq, Show)
1389+-- | 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.
1390+data FilterAggregation = FilterAggregation { faFilter :: Filter
1391+ , faAggs :: Maybe Aggregations} deriving (Eq, Show)
1393+mkTermsAggregation :: Text -> TermsAggregation
1394+mkTermsAggregation t = TermsAggregation (Left t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1396+mkTermsScriptAggregation :: Text -> TermsAggregation
1397+mkTermsScriptAggregation t = TermsAggregation (Right t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1399+mkDateHistogram :: FieldName -> Interval -> DateHistogramAggregation
1400+mkDateHistogram t i = DateHistogramAggregation t i Nothing Nothing Nothing Nothing Nothing Nothing
1402+instance ToJSON TermOrder where
1403+ toJSON (TermOrder termSortField termSortOrder) = object [termSortField .= termSortOrder]
1405+instance ToJSON TermInclusion where
1406+ toJSON (TermInclusion x) = toJSON x
1407+ toJSON (TermPattern pattern flags) = omitNulls [ "pattern" .= pattern,
1410+instance ToJSON CollectionMode where
1411+ toJSON BreadthFirst = "breadth_first"
1412+ toJSON DepthFirst = "depth_first"
1414+instance ToJSON ExecutionHint where
1415+ toJSON Ordinals = "ordinals"
1416+ toJSON GlobalOrdinals = "global_ordinals"
1417+ toJSON GlobalOrdinalsHash = "global_ordinals_hash"
1418+ toJSON GlobalOrdinalsLowCardinality = "global_ordinals_low_cardinality"
1421+instance ToJSON Interval where
1422+ toJSON Year = "year"
1423+ toJSON Quarter = "quarter"
1424+ toJSON Month = "month"
1425+ toJSON Week = "week"
1427+ toJSON Hour = "hour"
1428+ toJSON Minute = "minute"
1429+ toJSON Second = "second"
1430+ toJSON (FractionalInterval fraction interval) = toJSON $ show fraction ++ show interval
1432+instance Show TimeInterval where
1439+instance ToJSON Aggregation where
1440+ toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint termAggs)) =
1441+ omitNulls ["terms" .= omitNulls [ toJSON' term,
1442+ "include" .= include,
1443+ "exclude" .= exclude,
1445+ "min_doc_count" .= minDocCount,
1447+ "shard_size" .= shardSize,
1448+ "collect_mode" .= collectMode,
1449+ "execution_hint" .= executionHint
1451+ "aggs" .= termAggs ]
1453+ toJSON' x = case x of { Left y -> "field" .= y; Right y -> "script" .= y }
1455+ toJSON (DateHistogramAgg (DateHistogramAggregation field interval format preZone postZone preOffset postOffset dateHistoAggs)) =
1456+ omitNulls ["date_histogram" .= omitNulls [ "field" .= field,
1457+ "interval" .= interval,
1458+ "format" .= format,
1459+ "pre_zone" .= preZone,
1460+ "post_zone" .= postZone,
1461+ "pre_offset" .= preOffset,
1462+ "post_offset" .= postOffset
1464+ "aggs" .= dateHistoAggs ]
1465+ toJSON (ValueCountAgg a) = object ["value_count" .= v]
1466+ where v = case a of
1467+ (FieldValueCount (FieldName n)) -> object ["field" .= n]
1468+ (ScriptValueCount (Script s)) -> object ["script" .= s]
1469+ toJSON (FilterAgg (FilterAggregation filt ags)) =
1470+ omitNulls [ "filter" .= filt
1473+type AggregationResults = M.Map Text Value
1475+class BucketAggregation a where
1477+ docCount :: a -> Int
1478+ aggs :: a -> Maybe AggregationResults
1481+data Bucket a = Bucket { buckets :: [a]} deriving (Show)
1483+data TermsResult = TermsResult { termKey :: Text
1484+ , termsDocCount :: Int
1485+ , termsAggs :: Maybe AggregationResults } deriving (Show)
1487+data DateHistogramResult = DateHistogramResult { dateKey :: Int
1488+ , dateKeyStr :: Maybe Text
1489+ , dateDocCount :: Int
1490+ , dateHistogramAggs :: Maybe AggregationResults } deriving (Show)
1492+toTerms :: Text -> AggregationResults -> Maybe (Bucket TermsResult)
1493+toTerms t a = M.lookup t a >>= deserialize
1494+ where deserialize = parseMaybe parseJSON
1496+toDateHistogram :: Text -> AggregationResults -> Maybe (Bucket DateHistogramResult)
1497+toDateHistogram t a = M.lookup t a >>= deserialize
1498+ where deserialize = parseMaybe parseJSON
1500+instance BucketAggregation TermsResult where
1502+ docCount = termsDocCount
1505+instance BucketAggregation DateHistogramResult where
1506+ key = showText . dateKey
1507+ docCount = dateDocCount
1508+ aggs = dateHistogramAggs
1510+instance (FromJSON a, BucketAggregation a) => FromJSON (Bucket a) where
1511+ parseJSON (Object v) = Bucket <$>
1513+ parseJSON _ = mempty
1515+instance FromJSON TermsResult where
1516+ parseJSON (Object v) = TermsResult <$>
1518+ v .: "doc_count" <*>
1519+ v .:? "aggregations"
1520+ parseJSON _ = mempty
1522+instance FromJSON DateHistogramResult where
1523+ parseJSON (Object v) = DateHistogramResult <$>
1525+ v .:? "key_as_string" <*>
1526+ v .: "doc_count" <*>
1527+ v .:? "aggregations"
1528+ parseJSON _ = mempty
1530+instance Monoid Filter where
1531+ mempty = IdentityFilter
1532+ mappend a b = AndFilter [a, b] defaultCache
1534+instance Seminearring Filter where
1535+ a <||> b = OrFilter [a, b] defaultCache
1537+instance ToJSON Filter where
1538+ toJSON (AndFilter filters cache) =
1540+ object [ "filters" .= fmap toJSON filters
1541+ , "_cache" .= cache]]
1543+ toJSON (OrFilter filters cache) =
1545+ object [ "filters" .= fmap toJSON filters
1546+ , "_cache" .= cache]]
1548+ toJSON (NotFilter notFilter cache) =
1550+ object ["filter" .= notFilter
1551+ , "_cache" .= cache]]
1553+ toJSON (IdentityFilter) =
1554+ object ["match_all" .= object []]
1556+ toJSON (TermFilter (Term termFilterField termFilterValue) cache) =
1557+ object ["term" .= object base]
1558+ where base = [termFilterField .= termFilterValue,
1561+ toJSON (ExistsFilter (FieldName fieldName)) =
1562+ object ["exists" .= object
1563+ ["field" .= fieldName]]
1565+ toJSON (BoolFilter boolMatch) =
1566+ object ["bool" .= boolMatch]
1568+ toJSON (GeoBoundingBoxFilter bbConstraint) =
1569+ object ["geo_bounding_box" .= bbConstraint]
1571+ toJSON (GeoDistanceFilter (GeoPoint (FieldName distanceGeoField) geoDistLatLon)
1572+ distance distanceType optimizeBbox cache) =
1573+ object ["geo_distance" .=
1574+ object ["distance" .= distance
1575+ , "distance_type" .= distanceType
1576+ , "optimize_bbox" .= optimizeBbox
1577+ , distanceGeoField .= geoDistLatLon
1578+ , "_cache" .= cache]]
1580+ toJSON (GeoDistanceRangeFilter (GeoPoint (FieldName gddrField) drLatLon)
1581+ (DistanceRange geoDistRangeDistFrom drDistanceTo)) =
1582+ object ["geo_distance_range" .=
1583+ object ["from" .= geoDistRangeDistFrom
1584+ , "to" .= drDistanceTo
1585+ , gddrField .= drLatLon]]
1587+ toJSON (GeoPolygonFilter (FieldName geoPolygonFilterField) latLons) =
1588+ object ["geo_polygon" .=
1589+ object [geoPolygonFilterField .=
1590+ object ["points" .= fmap toJSON latLons]]]
1592+ toJSON (IdsFilter (MappingName mappingName) values) =
1594+ object ["type" .= mappingName
1595+ , "values" .= fmap unpackId values]]
1597+ toJSON (LimitFilter limit) =
1598+ object ["limit" .= object ["value" .= limit]]
1600+ toJSON (MissingFilter (FieldName fieldName) (Existence existence) (NullValue nullValue)) =
1601+ object ["missing" .=
1602+ object ["field" .= fieldName
1603+ , "existence" .= existence
1604+ , "null_value" .= nullValue]]
1606+ toJSON (PrefixFilter (FieldName fieldName) fieldValue cache) =
1607+ object ["prefix" .=
1608+ object [fieldName .= fieldValue
1609+ , "_cache" .= cache]]
1611+ toJSON (QueryFilter query False) =
1612+ object ["query" .= toJSON query ]
1613+ toJSON (QueryFilter query True) =
1614+ object ["fquery" .=
1615+ object [ "query" .= toJSON query
1616+ , "_cache" .= True ]]
1618+ toJSON (RangeFilter (FieldName fieldName) rangeValue rangeExecution cache) =
1620+ object [ fieldName .= object (rangeValueToPair rangeValue)
1621+ , "execution" .= rangeExecution
1622+ , "_cache" .= cache]]
1624+ toJSON (RegexpFilter (FieldName fieldName)
1625+ (Regexp regexText) flags (CacheName cacheName) cache (CacheKey cacheKey)) =
1626+ object ["regexp" .=
1627+ object [fieldName .=
1628+ object ["value" .= regexText
1629+ , "flags" .= flags]
1630+ , "_name" .= cacheName
1631+ , "_cache" .= cache
1632+ , "_cache_key" .= cacheKey]]
1634+instance ToJSON GeoPoint where
1635+ toJSON (GeoPoint (FieldName geoPointField) geoPointLatLon) =
1636+ object [ geoPointField .= geoPointLatLon ]
1639+instance ToJSON Query where
1640+ toJSON (TermQuery (Term termQueryField termQueryValue) boost) =
1642+ object [termQueryField .= object merged]]
1644+ base = [ "value" .= termQueryValue ]
1645+ boosted = maybe [] (return . ("boost" .=)) boost
1646+ merged = mappend base boosted
1648+ toJSON (TermsQuery terms) =
1649+ object [ "terms" .= object conjoined ]
1650+ where conjoined = [ getTermsField terms .=
1651+ fmap (toJSON . getTermValue) (toList terms)]
1652+ getTermsField ((Term f _ ) :| _) = f
1653+ getTermValue (Term _ v) = v
1654+ toJSON (IdsQuery idsQueryMappingName docIds) =
1655+ object [ "ids" .= object conjoined ]
1656+ where conjoined = [ "type" .= idsQueryMappingName
1657+ , "values" .= fmap toJSON docIds ]
1659+ toJSON (QueryQueryStringQuery qQueryStringQuery) =
1660+ object [ "query_string" .= qQueryStringQuery ]
1662+ toJSON (QueryMatchQuery matchQuery) =
1663+ object [ "match" .= matchQuery ]
1665+ toJSON (QueryMultiMatchQuery multiMatchQuery) =
1666+ toJSON multiMatchQuery
1668+ toJSON (QueryBoolQuery boolQuery) =
1669+ object [ "bool" .= boolQuery ]
1671+ toJSON (QueryBoostingQuery boostingQuery) =
1672+ object [ "boosting" .= boostingQuery ]
1674+ toJSON (QueryCommonTermsQuery commonTermsQuery) =
1675+ object [ "common" .= commonTermsQuery ]
1677+ toJSON (ConstantScoreFilter csFilter boost) =
1678+ object [ "constant_score" .= csFilter
1679+ , "boost" .= boost]
1681+ toJSON (ConstantScoreQuery query boost) =
1682+ object [ "constant_score" .= query
1683+ , "boost" .= boost]
1685+ toJSON (QueryDisMaxQuery disMaxQuery) =
1686+ object [ "dis_max" .= disMaxQuery ]
1688+ toJSON (QueryFilteredQuery qFilteredQuery) =
1689+ object [ "filtered" .= qFilteredQuery ]
1691+ toJSON (QueryFuzzyLikeThisQuery fuzzyQuery) =
1692+ object [ "fuzzy_like_this" .= fuzzyQuery ]
1694+ toJSON (QueryFuzzyLikeFieldQuery fuzzyFieldQuery) =
1695+ object [ "fuzzy_like_this_field" .= fuzzyFieldQuery ]
1697+ toJSON (QueryFuzzyQuery fuzzyQuery) =
1698+ object [ "fuzzy" .= fuzzyQuery ]
1700+ toJSON (QueryHasChildQuery childQuery) =
1701+ object [ "has_child" .= childQuery ]
1703+ toJSON (QueryHasParentQuery parentQuery) =
1704+ object [ "has_parent" .= parentQuery ]
1706+ toJSON (QueryIndicesQuery qIndicesQuery) =
1707+ object [ "indices" .= qIndicesQuery ]
1709+ toJSON (MatchAllQuery boost) =
1710+ object [ "match_all" .= omitNulls [ "boost" .= boost ] ]
1712+ toJSON (QueryMoreLikeThisQuery query) =
1713+ object [ "more_like_this" .= query ]
1715+ toJSON (QueryMoreLikeThisFieldQuery query) =
1716+ object [ "more_like_this_field" .= query ]
1718+ toJSON (QueryNestedQuery query) =
1719+ object [ "nested" .= query ]
1721+ toJSON (QueryPrefixQuery query) =
1722+ object [ "prefix" .= query ]
1724+ toJSON (QueryRangeQuery query) =
1725+ object [ "range" .= query ]
1727+ toJSON (QueryRegexpQuery query) =
1728+ object [ "regexp" .= query ]
1730+ toJSON (QuerySimpleQueryStringQuery query) =
1731+ object [ "simple_query_string" .= query ]
1734+omitNulls :: [(Text, Value)] -> Value
1735+omitNulls = object . filter notNull where
1736+ notNull (_, Null) = False
1737+ notNull (_, Array a) = (not . V.null) a
1741+instance ToJSON SimpleQueryStringQuery where
1742+ toJSON SimpleQueryStringQuery {..} =
1743+ omitNulls (base ++ maybeAdd)
1744+ where base = [ "query" .= simpleQueryStringQuery ]
1745+ maybeAdd = [ "fields" .= simpleQueryStringField
1746+ , "default_operator" .= simpleQueryStringOperator
1747+ , "analyzer" .= simpleQueryStringAnalyzer
1748+ , "flags" .= simpleQueryStringFlags
1749+ , "lowercase_expanded_terms" .= simpleQueryStringLowercaseExpanded
1750+ , "locale" .= simpleQueryStringLocale ]
1753+instance ToJSON FieldOrFields where
1754+ toJSON (FofField fieldName) =
1756+ toJSON (FofFields fieldNames) =
1759+instance ToJSON SimpleQueryFlag where
1760+ toJSON SimpleQueryAll = "ALL"
1761+ toJSON SimpleQueryNone = "NONE"
1762+ toJSON SimpleQueryAnd = "AND"
1763+ toJSON SimpleQueryOr = "OR"
1764+ toJSON SimpleQueryPrefix = "PREFIX"
1765+ toJSON SimpleQueryPhrase = "PHRASE"
1766+ toJSON SimpleQueryPrecedence = "PRECEDENCE"
1767+ toJSON SimpleQueryEscape = "ESCAPE"
1768+ toJSON SimpleQueryWhitespace = "WHITESPACE"
1769+ toJSON SimpleQueryFuzzy = "FUZZY"
1770+ toJSON SimpleQueryNear = "NEAR"
1771+ toJSON SimpleQuerySlop = "SLOP"
1774+instance ToJSON RegexpQuery where
1775+ toJSON (RegexpQuery (FieldName rqQueryField)
1776+ (Regexp regexpQueryQuery) rqQueryFlags
1778+ object [ rqQueryField .= omitNulls base ]
1779+ where base = [ "value" .= regexpQueryQuery
1780+ , "flags" .= rqQueryFlags
1781+ , "boost" .= rqQueryBoost ]
1784+instance ToJSON QueryStringQuery where
1785+ toJSON (QueryStringQuery qsQueryString
1786+ qsDefaultField qsOperator
1787+ qsAnalyzer qsAllowWildcard
1788+ qsLowercaseExpanded qsEnablePositionIncrements
1789+ qsFuzzyMaxExpansions qsFuzziness
1790+ qsFuzzyPrefixLength qsPhraseSlop
1791+ qsBoost qsAnalyzeWildcard
1792+ qsGeneratePhraseQueries qsMinimumShouldMatch
1793+ qsLenient qsLocale) =
1796+ base = [ "query" .= qsQueryString
1797+ , "default_field" .= qsDefaultField
1798+ , "default_operator" .= qsOperator
1799+ , "analyzer" .= qsAnalyzer
1800+ , "allow_leading_wildcard" .= qsAllowWildcard
1801+ , "lowercase_expanded_terms" .= qsLowercaseExpanded
1802+ , "enable_position_increments" .= qsEnablePositionIncrements
1803+ , "fuzzy_max_expansions" .= qsFuzzyMaxExpansions
1804+ , "fuzziness" .= qsFuzziness
1805+ , "fuzzy_prefix_length" .= qsFuzzyPrefixLength
1806+ , "phrase_slop" .= qsPhraseSlop
1807+ , "boost" .= qsBoost
1808+ , "analyze_wildcard" .= qsAnalyzeWildcard
1809+ , "auto_generate_phrase_queries" .= qsGeneratePhraseQueries
1810+ , "minimum_should_match" .= qsMinimumShouldMatch
1811+ , "lenient" .= qsLenient
1812+ , "locale" .= qsLocale ]
1815+instance ToJSON RangeQuery where
1816+ toJSON (RangeQuery (FieldName fieldName) range boost) =
1817+ object [ fieldName .= conjoined ]
1818+ where conjoined = [ "boost" .= boost ] ++ (rangeValueToPair range)
1821+instance ToJSON PrefixQuery where
1822+ toJSON (PrefixQuery (FieldName fieldName) queryValue boost) =
1823+ object [ fieldName .= omitNulls base ]
1824+ where base = [ "value" .= queryValue
1825+ , "boost" .= boost ]
1828+instance ToJSON NestedQuery where
1829+ toJSON (NestedQuery nqPath nqScoreType nqQuery) =
1830+ object [ "path" .= nqPath
1831+ , "score_mode" .= nqScoreType
1832+ , "query" .= nqQuery ]
1835+instance ToJSON MoreLikeThisFieldQuery where
1836+ toJSON (MoreLikeThisFieldQuery text (FieldName fieldName)
1837+ percent mtf mqt stopwords mindf maxdf
1838+ minwl maxwl boostTerms boost analyzer) =
1839+ object [ fieldName .= omitNulls base ]
1840+ where base = [ "like_text" .= text
1841+ , "percent_terms_to_match" .= percent
1842+ , "min_term_freq" .= mtf
1843+ , "max_query_terms" .= mqt
1844+ , "stop_words" .= stopwords
1845+ , "min_doc_freq" .= mindf
1846+ , "max_doc_freq" .= maxdf
1847+ , "min_word_length" .= minwl
1848+ , "max_word_length" .= maxwl
1849+ , "boost_terms" .= boostTerms
1851+ , "analyzer" .= analyzer ]
1854+instance ToJSON MoreLikeThisQuery where
1855+ toJSON (MoreLikeThisQuery text fields percent
1856+ mtf mqt stopwords mindf maxdf
1857+ minwl maxwl boostTerms boost analyzer) =
1859+ where base = [ "like_text" .= text
1860+ , "fields" .= fields
1861+ , "percent_terms_to_match" .= percent
1862+ , "min_term_freq" .= mtf
1863+ , "max_query_terms" .= mqt
1864+ , "stop_words" .= stopwords
1865+ , "min_doc_freq" .= mindf
1866+ , "max_doc_freq" .= maxdf
1867+ , "min_word_length" .= minwl
1868+ , "max_word_length" .= maxwl
1869+ , "boost_terms" .= boostTerms
1871+ , "analyzer" .= analyzer ]
1874+instance ToJSON IndicesQuery where
1875+ toJSON (IndicesQuery indices query noMatch) =
1876+ omitNulls [ "indices" .= indices
1877+ , "no_match_query" .= noMatch
1878+ , "query" .= query ]
1881+instance ToJSON HasParentQuery where
1882+ toJSON (HasParentQuery queryType query scoreType) =
1883+ omitNulls [ "parent_type" .= queryType
1884+ , "score_type" .= scoreType
1885+ , "query" .= query ]
1888+instance ToJSON HasChildQuery where
1889+ toJSON (HasChildQuery queryType query scoreType) =
1890+ omitNulls [ "query" .= query
1891+ , "score_type" .= scoreType
1892+ , "type" .= queryType ]
1895+instance ToJSON FuzzyQuery where
1896+ toJSON (FuzzyQuery (FieldName fieldName) queryText
1897+ prefixLength maxEx fuzziness boost) =
1898+ object [ fieldName .= omitNulls base ]
1899+ where base = [ "value" .= queryText
1900+ , "fuzziness" .= fuzziness
1901+ , "prefix_length" .= prefixLength
1903+ , "max_expansions" .= maxEx ]
1906+instance ToJSON FuzzyLikeFieldQuery where
1907+ toJSON (FuzzyLikeFieldQuery (FieldName fieldName)
1908+ fieldText maxTerms ignoreFreq fuzziness prefixLength
1910+ object [ fieldName .=
1911+ omitNulls [ "like_text" .= fieldText
1912+ , "max_query_terms" .= maxTerms
1913+ , "ignore_tf" .= ignoreFreq
1914+ , "fuzziness" .= fuzziness
1915+ , "prefix_length" .= prefixLength
1916+ , "analyzer" .= analyzer
1917+ , "boost" .= boost ]]
1920+instance ToJSON FuzzyLikeThisQuery where
1921+ toJSON (FuzzyLikeThisQuery fields text maxTerms
1922+ ignoreFreq fuzziness prefixLength boost analyzer) =
1924+ where base = [ "fields" .= fields
1925+ , "like_text" .= text
1926+ , "max_query_terms" .= maxTerms
1927+ , "ignore_tf" .= ignoreFreq
1928+ , "fuzziness" .= fuzziness
1929+ , "prefix_length" .= prefixLength
1930+ , "analyzer" .= analyzer
1931+ , "boost" .= boost ]
1934+instance ToJSON FilteredQuery where
1935+ toJSON (FilteredQuery query fFilter) =
1936+ object [ "query" .= query
1937+ , "filter" .= fFilter ]
1940+instance ToJSON DisMaxQuery where
1941+ toJSON (DisMaxQuery queries tiebreaker boost) =
1943+ where base = [ "queries" .= queries
1945+ , "tie_breaker" .= tiebreaker ]
1948+instance ToJSON CommonTermsQuery where
1949+ toJSON (CommonTermsQuery (FieldName fieldName)
1950+ (QueryString query) cf lfo hfo msm
1951+ boost analyzer disableCoord) =
1952+ object [fieldName .= omitNulls base ]
1953+ where base = [ "query" .= query
1954+ , "cutoff_frequency" .= cf
1955+ , "low_freq_operator" .= lfo
1956+ , "minimum_should_match" .= msm
1958+ , "analyzer" .= analyzer
1959+ , "disable_coord" .= disableCoord
1960+ , "high_freq_operator" .= hfo ]
1963+instance ToJSON CommonMinimumMatch where
1964+ toJSON (CommonMinimumMatch mm) = toJSON mm
1965+ toJSON (CommonMinimumMatchHighLow (MinimumMatchHighLow lowF highF)) =
1966+ object [ "low_freq" .= lowF
1967+ , "high_freq" .= highF ]
1969+instance ToJSON BoostingQuery where
1970+ toJSON (BoostingQuery bqPositiveQuery bqNegativeQuery bqNegativeBoost) =
1971+ object [ "positive" .= bqPositiveQuery
1972+ , "negative" .= bqNegativeQuery
1973+ , "negative_boost" .= bqNegativeBoost ]
1976+instance ToJSON BoolQuery where
1977+ toJSON (BoolQuery mustM notM shouldM bqMin boost disableCoord) =
1979+ where base = [ "must" .= mustM
1980+ , "must_not" .= notM
1981+ , "should" .= shouldM
1982+ , "minimum_should_match" .= bqMin
1984+ , "disable_coord" .= disableCoord ]
1987+instance ToJSON MatchQuery where
1988+ toJSON (MatchQuery (FieldName fieldName)
1989+ (QueryString mqQueryString) booleanOperator
1990+ zeroTermsQuery cutoffFrequency matchQueryType
1991+ analyzer maxExpansions lenient boost) =
1992+ object [ fieldName .= omitNulls base ]
1993+ where base = [ "query" .= mqQueryString
1994+ , "operator" .= booleanOperator
1995+ , "zero_terms_query" .= zeroTermsQuery
1996+ , "cutoff_frequency" .= cutoffFrequency
1997+ , "type" .= matchQueryType
1998+ , "analyzer" .= analyzer
1999+ , "max_expansions" .= maxExpansions
2000+ , "lenient" .= lenient
2001+ , "boost" .= boost ]
2004+instance ToJSON MultiMatchQuery where
2005+ toJSON (MultiMatchQuery fields (QueryString query) boolOp
2006+ ztQ tb mmqt cf analyzer maxEx lenient) =
2007+ object ["multi_match" .= omitNulls base]
2008+ where base = [ "fields" .= fmap toJSON fields
2010+ , "operator" .= boolOp
2011+ , "zero_terms_query" .= ztQ
2012+ , "tiebreaker" .= tb
2014+ , "cutoff_frequency" .= cf
2015+ , "analyzer" .= analyzer
2016+ , "max_expansions" .= maxEx
2017+ , "lenient" .= lenient ]
2020+instance ToJSON MultiMatchQueryType where
2021+ toJSON MultiMatchBestFields = "best_fields"
2022+ toJSON MultiMatchMostFields = "most_fields"
2023+ toJSON MultiMatchCrossFields = "cross_fields"
2024+ toJSON MultiMatchPhrase = "phrase"
2025+ toJSON MultiMatchPhrasePrefix = "phrase_prefix"
2027+instance ToJSON BooleanOperator where
2028+ toJSON And = String "and"
2029+ toJSON Or = String "or"
2031+instance ToJSON ZeroTermsQuery where
2032+ toJSON ZeroTermsNone = String "none"
2033+ toJSON ZeroTermsAll = String "all"
2035+instance ToJSON MatchQueryType where
2036+ toJSON MatchPhrase = "phrase"
2037+ toJSON MatchPhrasePrefix = "phrase_prefix"
2039+instance ToJSON FieldName where
2040+ toJSON (FieldName fieldName) = String fieldName
2042+instance ToJSON ReplicaCount
2043+instance ToJSON ShardCount
2044+instance ToJSON CutoffFrequency
2045+instance ToJSON Analyzer
2046+instance ToJSON MaxExpansions
2047+instance ToJSON Lenient
2048+instance ToJSON Boost
2049+instance ToJSON Version
2050+instance ToJSON Tiebreaker
2051+instance ToJSON MinimumMatch
2052+instance ToJSON DisableCoord
2053+instance ToJSON PrefixLength
2054+instance ToJSON Fuzziness
2055+instance ToJSON IgnoreTermFrequency
2056+instance ToJSON MaxQueryTerms
2057+instance ToJSON TypeName
2058+instance ToJSON IndexName
2059+instance ToJSON TemplateName
2060+instance ToJSON TemplatePattern
2061+instance ToJSON BoostTerms
2062+instance ToJSON MaxWordLength
2063+instance ToJSON MinWordLength
2064+instance ToJSON MaxDocFrequency
2065+instance ToJSON MinDocFrequency
2066+instance ToJSON PhraseSlop
2067+instance ToJSON StopWord
2068+instance ToJSON QueryPath
2069+instance ToJSON MinimumTermFrequency
2070+instance ToJSON PercentMatch
2071+instance ToJSON MappingName
2072+instance ToJSON DocId
2073+instance ToJSON QueryString
2074+instance ToJSON AllowLeadingWildcard
2075+instance ToJSON LowercaseExpanded
2076+instance ToJSON AnalyzeWildcard
2077+instance ToJSON GeneratePhraseQueries
2078+instance ToJSON Locale
2079+instance ToJSON EnablePositionIncrements
2080+instance FromJSON Version
2081+instance FromJSON IndexName
2082+instance FromJSON MappingName
2083+instance FromJSON DocId
2086+instance FromJSON Status where
2087+ parseJSON (Object v) = Status <$>
2093+ parseJSON _ = empty
2096+instance ToJSON IndexSettings where
2097+ toJSON (IndexSettings s r) = object ["settings" .=
2099+ object ["number_of_shards" .= s, "number_of_replicas" .= r]
2103+instance ToJSON IndexTemplate where
2104+ toJSON (IndexTemplate p s m) = merge
2105+ (object [ "template" .= p
2106+ , "mappings" .= foldl' merge (object []) m
2110+ merge (Object o1) (Object o2) = toJSON $ HM.union o1 o2
2112+ merge _ _ = undefined
2114+instance (FromJSON a) => FromJSON (EsResult a) where
2115+ parseJSON jsonVal@(Object v) = do
2116+ found <- v .:? "found" .!= False
2118+ then parseJSON jsonVal
2119+ else return Nothing
2120+ EsResult <$> v .: "_index" <*>
2124+ parseJSON _ = empty
2126+instance (FromJSON a) => FromJSON (EsResultFound a) where
2127+ parseJSON (Object v) = EsResultFound <$>
2128+ v .: "_version" <*>
2130+ parseJSON _ = empty
2132+instance ToJSON Search where
2133+ toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
2134+ omitNulls [ "query" .= query
2135+ , "filter" .= sFilter
2137+ , "aggregations" .= searchAggs
2138+ , "highlight" .= highlight
2141+ , "track_scores" .= sTrackSortScores
2142+ , "fields" .= sFields
2143+ , "_source" .= sSource]
490instance ToJSON Source where
2146instance ToJSON Source where
491 toJSON NoSource = toJSON False
2147 toJSON NoSource = toJSON False
492 toJSON (SourcePatterns patterns) = toJSON patterns
2148 toJSON (SourcePatterns patterns) = toJSON patterns
493− toJSON (SourceIncludeExclude incl excl) = object [ "includes" .= incl, "excludes" .= excl ]
2149+ toJSON (SourceIncludeExclude incl excl) = object [ "include" .= incl, "exclude" .= excl ]
495−data PatternOrPatterns = PopPattern Pattern
496− | PopPatterns [Pattern] deriving (Eq, Read, Show)
498instance ToJSON PatternOrPatterns where
2151instance ToJSON PatternOrPatterns where
499 toJSON (PopPattern pattern) = toJSON pattern
2152 toJSON (PopPattern pattern) = toJSON pattern
500 toJSON (PopPatterns patterns) = toJSON patterns
2153 toJSON (PopPatterns patterns) = toJSON patterns
502−data Include = Include [Pattern] deriving (Eq, Read, Show)
503−data Exclude = Exclude [Pattern] deriving (Eq, Read, Show)
505instance ToJSON Include where
2155instance ToJSON Include where
506 toJSON (Include patterns) = toJSON patterns
2156 toJSON (Include patterns) = toJSON patterns
508instance ToJSON Exclude where
2158instance ToJSON Exclude where
509 toJSON (Exclude patterns) = toJSON patterns
2159 toJSON (Exclude patterns) = toJSON patterns
511−newtype Pattern = Pattern Text deriving (Eq, Read, Show)
513instance ToJSON Pattern where
2161instance ToJSON Pattern where
514 toJSON (Pattern pattern) = toJSON pattern
2162 toJSON (Pattern pattern) = toJSON pattern
516−data SearchResult a =
2164+
517− SearchResult { took :: Int
2165+instance ToJSON FieldHighlight where
518− , timedOut :: Bool
2166+ toJSON (FieldHighlight (FieldName fName) (Just fSettings)) =
519− , shards :: ShardResult
2167+ object [ fName .= fSettings ]
520− , searchHits :: SearchHits a
2168+ toJSON (FieldHighlight (FieldName fName) Nothing) =
521− , aggregations :: Maybe AggregationResults
2169+ object [ fName .= emptyObject ]
522− , scrollId :: Maybe ScrollId
2170+
523− -- ^ Only one Suggestion request / response per
2171+instance ToJSON Highlights where
524− -- Search is supported.
2172+ toJSON (Highlights global fields) =
525− , suggest :: Maybe NamedSuggestionResponse
2173+ omitNulls (("fields" .= fields)
526− }
2174+ : highlightSettingsPairs global)
527− deriving (Eq, Show)
2175+
2176+instance ToJSON HighlightSettings where
2177+ toJSON hs = omitNulls (highlightSettingsPairs (Just hs))
2179+highlightSettingsPairs :: Maybe HighlightSettings -> [Pair]
2180+highlightSettingsPairs Nothing = []
2181+highlightSettingsPairs (Just (Plain plh)) = plainHighPairs (Just plh)
2182+highlightSettingsPairs (Just (Postings ph)) = postHighPairs (Just ph)
2183+highlightSettingsPairs (Just (FastVector fvh)) = fastVectorHighPairs (Just fvh)
2186+plainHighPairs :: Maybe PlainHighlight -> [Pair]
2187+plainHighPairs Nothing = []
2188+plainHighPairs (Just (PlainHighlight plCom plNonPost)) =
2189+ [ "type" .= String "plain"]
2190+ ++ commonHighlightPairs plCom
2191+ ++ nonPostingsToPairs plNonPost
2193+postHighPairs :: Maybe PostingsHighlight -> [Pair]
2194+postHighPairs Nothing = []
2195+postHighPairs (Just (PostingsHighlight pCom)) =
2196+ ("type" .= String "postings")
2197+ : commonHighlightPairs pCom
2199+fastVectorHighPairs :: Maybe FastVectorHighlight -> [Pair]
2200+fastVectorHighPairs Nothing = []
2201+fastVectorHighPairs (Just
2202+ (FastVectorHighlight fvCom fvNonPostSettings fvBoundChars
2203+ fvBoundMaxScan fvFragOff fvMatchedFields
2205+ [ "type" .= String "fvh"
2206+ , "boundary_chars" .= fvBoundChars
2207+ , "boundary_max_scan" .= fvBoundMaxScan
2208+ , "fragment_offset" .= fvFragOff
2209+ , "matched_fields" .= fvMatchedFields
2210+ , "phraseLimit" .= fvPhraseLim]
2211+ ++ commonHighlightPairs fvCom
2212+ ++ nonPostingsToPairs fvNonPostSettings
2214+commonHighlightPairs :: Maybe CommonHighlight -> [Pair]
2215+commonHighlightPairs Nothing = []
2216+commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder
2217+ chNoMatchSize chHighlightQuery
2218+ chRequireFieldMatch)) =
2219+ [ "order" .= chScore
2220+ , "force_source" .= chForceSource
2221+ , "encoder" .= chEncoder
2222+ , "no_match_size" .= chNoMatchSize
2223+ , "highlight_query" .= chHighlightQuery
2224+ , "require_fieldMatch" .= chRequireFieldMatch]
2225+ ++ highlightTagToPairs chTag
2228+nonPostingsToPairs :: Maybe NonPostings -> [Pair]
2229+nonPostingsToPairs Nothing = []
2230+nonPostingsToPairs (Just (NonPostings npFragSize npNumOfFrags)) =
2231+ [ "fragment_size" .= npFragSize
2232+ , "number_of_fragments" .= npNumOfFrags]
2236+instance ToJSON HighlightEncoder where
2237+ toJSON DefaultEncoder = String "default"
2238+ toJSON HTMLEncoder = String "html"
2240+highlightTagToPairs :: Maybe HighlightTag -> [Pair]
2241+highlightTagToPairs (Just (TagSchema _)) = [ "scheme" .= String "default"]
2242+highlightTagToPairs (Just (CustomTags (pre, post))) = [ "pre_tags" .= pre
2243+ , "post_tags" .= post]
2244+highlightTagToPairs Nothing = []
2246+instance ToJSON SortSpec where
2247+ toJSON (DefaultSortSpec
2248+ (DefaultSort (FieldName dsSortFieldName) dsSortOrder dsIgnoreUnmapped
2249+ dsSortMode dsMissingSort dsNestedFilter)) =
2250+ object [dsSortFieldName .= omitNulls base] where
2251+ base = [ "order" .= dsSortOrder
2252+ , "ignore_unmapped" .= dsIgnoreUnmapped
2253+ , "mode" .= dsSortMode
2254+ , "missing" .= dsMissingSort
2255+ , "nested_filter" .= dsNestedFilter ]
2257+ toJSON (GeoDistanceSortSpec gdsSortOrder (GeoPoint (FieldName field) gdsLatLon) units) =
2258+ object [ "unit" .= units
2259+ , field .= gdsLatLon
2260+ , "order" .= gdsSortOrder ]
2263+instance ToJSON SortOrder where
2264+ toJSON Ascending = String "asc"
2265+ toJSON Descending = String "desc"
2268+instance ToJSON SortMode where
2269+ toJSON SortMin = String "min"
2270+ toJSON SortMax = String "max"
2271+ toJSON SortSum = String "sum"
2272+ toJSON SortAvg = String "avg"
2275+instance ToJSON Missing where
2276+ toJSON LastMissing = String "_last"
2277+ toJSON FirstMissing = String "_first"
2278+ toJSON (CustomMissing txt) = String txt
2281+instance ToJSON ScoreType where
2282+ toJSON ScoreTypeMax = "max"
2283+ toJSON ScoreTypeAvg = "avg"
2284+ toJSON ScoreTypeSum = "sum"
2285+ toJSON ScoreTypeNone = "none"
2288+instance ToJSON Distance where
2289+ toJSON (Distance dCoefficient dUnit) =
2290+ String boltedTogether where
2291+ coefText = showText dCoefficient
2292+ (String unitText) = toJSON dUnit
2293+ boltedTogether = mappend coefText unitText
2296+instance ToJSON DistanceUnit where
2297+ toJSON Miles = String "mi"
2298+ toJSON Yards = String "yd"
2299+ toJSON Feet = String "ft"
2300+ toJSON Inches = String "in"
2301+ toJSON Kilometers = String "km"
2302+ toJSON Meters = String "m"
2303+ toJSON Centimeters = String "cm"
2304+ toJSON Millimeters = String "mm"
2305+ toJSON NauticalMiles = String "nmi"
2308+instance ToJSON DistanceType where
2309+ toJSON Arc = String "arc"
2310+ toJSON SloppyArc = String "sloppy_arc"
2311+ toJSON Plane = String "plane"
2314+instance ToJSON OptimizeBbox where
2315+ toJSON NoOptimizeBbox = String "none"
2316+ toJSON (OptimizeGeoFilterType gft) = toJSON gft
2319+instance ToJSON GeoBoundingBoxConstraint where
2320+ toJSON (GeoBoundingBoxConstraint
2321+ (FieldName gbbcGeoBBField) gbbcConstraintBox cache type') =
2322+ object [gbbcGeoBBField .= gbbcConstraintBox
2323+ , "_cache" .= cache
2327+instance ToJSON GeoFilterType where
2328+ toJSON GeoFilterMemory = String "memory"
2329+ toJSON GeoFilterIndexed = String "indexed"
2332+instance ToJSON GeoBoundingBox where
2333+ toJSON (GeoBoundingBox gbbTopLeft gbbBottomRight) =
2334+ object ["top_left" .= gbbTopLeft
2335+ , "bottom_right" .= gbbBottomRight]
2338+instance ToJSON LatLon where
2339+ toJSON (LatLon lLat lLon) =
2340+ object ["lat" .= lLat
2344+-- index for smaller ranges, fielddata for longer ranges
2345+instance ToJSON RangeExecution where
2346+ toJSON RangeExecutionIndex = "index"
2347+ toJSON RangeExecutionFielddata = "fielddata"
2350+instance ToJSON RegexpFlags where
2351+ toJSON AllRegexpFlags = String "ALL"
2352+ toJSON NoRegexpFlags = String "NONE"
2353+ toJSON (SomeRegexpFlags (h :| fs)) = String $ T.intercalate "|" flagStrs
2354+ where flagStrs = map flagStr . nub $ h:fs
2355+ flagStr AnyString = "ANYSTRING"
2356+ flagStr Automaton = "AUTOMATON"
2357+ flagStr Complement = "COMPLEMENT"
2358+ flagStr Empty = "EMPTY"
2359+ flagStr Intersection = "INTERSECTION"
2360+ flagStr Interval = "INTERVAL"
2362+instance ToJSON Term where
2363+ toJSON (Term field value) = object ["term" .= object
2367+instance ToJSON BoolMatch where
2368+ toJSON (MustMatch term cache) = object ["must" .= term,
2370+ toJSON (MustNotMatch term cache) = object ["must_not" .= term,
2372+ toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
529instance (FromJSON a) => FromJSON (SearchResult a) where
2376instance (FromJSON a) => FromJSON (SearchResult a) where
530 parseJSON (Object v) = SearchResult <$>
2377 parseJSON (Object v) = SearchResult <$>
@@ -533,10 +2380,52 @@ instance (FromJSON a) => FromJSON (SearchResult a) where
533 v .: "_shards" <*>
2380 v .: "_shards" <*>
534 v .: "hits" <*>
2381 v .: "hits" <*>
535 v .:? "aggregations" <*>
2382 v .:? "aggregations" <*>
536− v .:? "_scroll_id" <*>
2383+ v .:? "_scroll_id"
537− v .:? "suggest"
2384+ parseJSON _ = empty
2386+instance (FromJSON a) => FromJSON (SearchHits a) where
2387+ parseJSON (Object v) = SearchHits <$>
2389+ v .: "max_score" <*>
538 parseJSON _ = empty
2391 parseJSON _ = empty
540−newtype ScrollId =
2393+instance (FromJSON a) => FromJSON (Hit a) where
541− ScrollId Text
2394+ parseJSON (Object v) = Hit <$>
542− deriving (Eq, Show, Ord, ToJSON, FromJSON)
2395+ v .: "_index" <*>
2401+ parseJSON _ = empty
2403+instance FromJSON ShardResult where
2404+ parseJSON (Object v) = ShardResult <$>
2406+ v .: "successful" <*>
2408+ parseJSON _ = empty
2411+instance FromJSON DocVersion where
2414+ maybe (fail "DocVersion out of range") return $ mkDocVersion i
2416+instance Bounded DocVersion where
2417+ minBound = DocVersion 1
2418+ maxBound = DocVersion 9200000000000000000 -- 9.2e+18
2420+instance Enum DocVersion where
2422+ | x /= maxBound = DocVersion (succ $ docVersionNumber x)
2423+ | otherwise = succError "DocVersion"
2425+ | x /= minBound = DocVersion (pred $ docVersionNumber x)
2426+ | otherwise = predError "DocVersion"
2428+ fromMaybe (error $ show i ++ " out of DocVersion range") $ mkDocVersion i
2429+ fromEnum = docVersionNumber
2430+ enumFrom = boundedEnumFrom
2431+ enumFromThen = boundedEnumFromThen