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-------------------------------------------------------------------------------
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
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
27-------------------------------------------------------------------------------
31module Database.Bloodhound.Types
33 , defaultIndexSettings
34 , defaultIndexDocumentSettings
45 , mkTermsScriptAggregation
69 , IndexAliasAction(..)
70 , IndexAliasCreate(..)
71 , IndexAliasSummary(..)
72 , IndexAliasesSummary(..)
74 , SearchAliasRouting(..)
75 , IndexAliasRouting(..)
78 , ExternalDocVersion(..)
81 , IndexDocumentSettings(..)
92 , PatternOrPatterns(..)
103 , GeoBoundingBoxConstraint(..)
129 , TemplatePattern(..)
147 , MultiMatchQuery(..)
150 , CommonTermsQuery(..)
153 , FuzzyLikeThisQuery(..)
154 , FuzzyLikeFieldQuery(..)
159 , MoreLikeThisQuery(..)
160 , MoreLikeThisFieldQuery(..)
163 , QueryStringQuery(..)
164 , SimpleQueryStringQuery(..)
168 , BooleanOperator(..)
170 , CutoffFrequency(..)
175 , MultiMatchQueryType(..)
179 , CommonMinimumMatch(..)
180 , MinimumMatchHighLow(..)
183 , IgnoreTermFrequency(..)
192 , MaxDocFrequency(..)
193 , MinDocFrequency(..)
197 , MinimumTermFrequency(..)
199 , FieldDefinition(..)
202 , AllowLeadingWildcard(..)
203 , LowercaseExpanded(..)
204 , GeneratePhraseQueries(..)
206 , AnalyzeWildcard(..)
207 , EnablePositionIncrements(..)
208 , SimpleQueryFlag(..)
223 , BucketAggregation(..)
224 , TermsAggregation(..)
225 , ValueCountAggregation(..)
226 , FilterAggregation(..)
227 , DateHistogramAggregation(..)
231 , HighlightSettings(..)
233 , PostingsHighlight(..)
234 , FastVectorHighlight(..)
235 , CommonHighlight(..)
237 , HighlightEncoder(..)
242 , DateHistogramResult(..)
245import Control.Applicative
246import Control.Monad.Catch
247import Control.Monad.Except
248import Control.Monad.Reader
249import Control.Monad.State
250import Control.Monad.Writer
252import Data.Aeson.Types (Pair, Parser, emptyObject,
254import qualified Data.ByteString.Lazy.Char8 as L
256import Data.Hashable (Hashable)
257import qualified Data.HashMap.Strict as HM
258import Data.List (foldl', nub)
259import Data.List.NonEmpty (NonEmpty (..), toList)
260import qualified Data.Map.Strict as M
262import Data.Text (Text)
263import qualified Data.Text as T
264import Data.Time.Clock (UTCTime)
265import qualified Data.Traversable as DT
266import Data.Typeable (Typeable)
267import qualified Data.Vector as V
269import GHC.Generics (Generic)
270import Network.HTTP.Client
271import qualified Network.HTTP.Types.Method as NHTM
273import Database.Bloodhound.Types.Class
276-- >>> :set -XOverloadedStrings
277-- >>> import Database.Bloodhound
278-- >>> let testServer = (Server "http://localhost:9200")
279-- >>> let testIndex = IndexName "twitter"
280-- >>> let testMapping = MappingName "tweet"
281-- >>> let defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
283-- defaultIndexSettings is exported by Database.Bloodhound as well
284-- no trailing slashes in servers, library handles building the path.
286{-| Common environment for Elasticsearch calls. Connections will be
287 pipelined according to the provided HTTP connection manager.
289data BHEnv = BHEnv { bhServer :: Server
290 , bhManager :: Manager
293{-| All API calls to Elasticsearch operate within
294 MonadBH. The idea is that it can be easily embedded in your
295 own monad transformer stack. A default instance for a ReaderT and
296 alias 'BH' is provided for the simple case.
298class (Functor m, Applicative m, MonadIO m) => MonadBH m where
302 unBH :: ReaderT BHEnv m a
317instance MonadTrans BH where
320instance (MonadReader r m) => MonadReader r (BH m) where
322 local f (BH (ReaderT m)) = BH $ ReaderT $ \r ->
325instance (Functor m, Applicative m, MonadIO m) => MonadBH (BH m) where
326 getBHEnv = BH getBHEnv
329instance (Functor m, Applicative m, MonadIO m) => MonadBH (ReaderT BHEnv m) where
332runBH :: BHEnv -> BH m a -> m a
333runBH e f = runReaderT (unBH f) e
335{-| 'Version' is embedded in 'Status' -}
336data Version = Version { number :: Text
338 , build_timestamp :: UTCTime
339 , build_snapshot :: Bool
340 , lucene_version :: Text } deriving (Eq, Show, Generic, Typeable)
342{-| 'Status' is a data type for describing the JSON body returned by
343 Elasticsearch when you query its status. This was deprecated in 1.2.0.
345 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html#indices-status>
348data Status = Status { ok :: Maybe Bool
352 , tagline :: Text } deriving (Eq, Show)
354{-| 'IndexSettings' is used to configure the shards and replicas when you create
355 an Elasticsearch Index.
357 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
361 IndexSettings { indexShards :: ShardCount
362 , indexReplicas :: ReplicaCount } deriving (Eq, Show)
364{-| 'defaultIndexSettings' is an 'IndexSettings' with 3 shards and 2 replicas. -}
365defaultIndexSettings :: IndexSettings
366defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
368{-| 'Reply' and 'Method' are type synonyms from 'Network.HTTP.Types.Method.Method' -}
369type Reply = Network.HTTP.Client.Response L.ByteString
370type Method = NHTM.Method
372{-| 'OpenCloseIndex' is a sum type for opening and closing indices.
374 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-open-close.html>
376data OpenCloseIndex = OpenIndex | CloseIndex deriving (Eq, Show)
378data FieldType = GeoPointType
384 | ByteType deriving (Eq, Show)
386data FieldDefinition =
387 FieldDefinition { fieldType :: FieldType } deriving (Eq, Show)
389{-| An 'IndexTemplate' defines a template that will automatically be
390 applied to new indices created. The templates include both
391 'IndexSettings' and mappings, and a simple 'TemplatePattern' that
392 controls if the template will be applied to the index created.
393 Specify mappings as follows: @[toJSON TweetMapping, ...]@
395 https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html
398 IndexTemplate { templatePattern :: TemplatePattern
399 , templateSettings :: Maybe IndexSettings
400 , templateMappings :: [Value]
404 MappingField { mappingFieldName :: FieldName
405 , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
407{-| Support for type reification of 'Mapping's is currently incomplete, for
408 now the mapping API verbiage expects a 'ToJSON'able blob.
410 Indexes have mappings, mappings are schemas for the documents contained in the
411 index. I'd recommend having only one mapping per index, always having a mapping,
412 and keeping different kinds of documents separated if possible.
414data Mapping = Mapping { typeName :: TypeName
415 , mappingFields :: [MappingField] } deriving (Eq, Show)
417{-| 'BulkOperation' is a sum type for expressing the four kinds of bulk
418 operation index, create, delete, and update. 'BulkIndex' behaves like an
419 "upsert", 'BulkCreate' will fail if a document already exists at the DocId.
421 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html#docs-bulk>
424 BulkIndex IndexName MappingName DocId Value
425 | BulkCreate IndexName MappingName DocId Value
426 | BulkDelete IndexName MappingName DocId
427 | BulkUpdate IndexName MappingName DocId Value deriving (Eq, Show)
429{-| 'EsResult' describes the standard wrapper JSON document that you see in
430 successful Elasticsearch lookups or lookups that couldn't find the document.
432data EsResult a = EsResult { _index :: Text
435 , foundResult :: Maybe (EsResultFound a)} deriving (Eq, Show)
437{-| 'EsResultFound' contains the document and its metadata inside of an
438 'EsResult' when the document was successfully found.
440data EsResultFound a = EsResultFound { _version :: DocVersion
441 , _source :: a } deriving (Eq, Show)
443{-| 'EsError' is the generic type that will be returned when there was a
444 problem. If you can't parse the expected response, its a good idea to
447data EsError = EsError { errorStatus :: Int
448 , errorMessage :: Text } deriving (Eq, Show)
450data IndexAlias = IndexAlias { srcIndex :: IndexName
451 , indexAlias :: IndexAliasName } deriving (Eq, Show)
453newtype IndexAliasName = IndexAliasName { indexAliasName :: IndexName } deriving (Eq, Show, ToJSON)
455data IndexAliasAction = AddAlias IndexAlias IndexAliasCreate
456 | RemoveAlias IndexAlias deriving (Show, Eq, Typeable)
458data IndexAliasCreate = IndexAliasCreate { aliasCreateRouting :: Maybe AliasRouting
459 , aliasCreateFilter :: Maybe Filter}
460 deriving (Show, Eq, Typeable)
462data AliasRouting = AllAliasRouting RoutingValue
463 | GranularAliasRouting (Maybe SearchAliasRouting) (Maybe IndexAliasRouting)
464 deriving (Show, Eq, Typeable)
466newtype SearchAliasRouting = SearchAliasRouting (NonEmpty RoutingValue) deriving (Show, Eq, Typeable)
468newtype IndexAliasRouting = IndexAliasRouting RoutingValue deriving (Show, Eq, ToJSON, FromJSON, Typeable)
470newtype RoutingValue = RoutingValue { routingValue :: Text } deriving (Show, Eq, ToJSON, FromJSON, Typeable)
472newtype IndexAliasesSummary = IndexAliasesSummary { indexAliasesSummary :: [IndexAliasSummary] } deriving (Show, Eq, Typeable)
474{-| 'IndexAliasSummary' is a summary of an index alias configured for a server. -}
475data IndexAliasSummary = IndexAliasSummary { indexAliasSummaryAlias :: IndexAlias
476 , indexAliasSummaryCreate :: IndexAliasCreate} deriving (Show, Eq)
478{-| 'DocVersion' is an integer version number for a document between 1
479and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
481newtype DocVersion = DocVersion {
482 docVersionNumber :: Int
483 } deriving (Eq, Show, Ord, ToJSON)
485-- | Smart constructor for in-range doc version
486mkDocVersion :: Int -> Maybe DocVersion
488 | i >= (docVersionNumber minBound) && i <= (docVersionNumber maxBound) =
490 | otherwise = Nothing
493{-| 'ExternalDocVersion' is a convenience wrapper if your code uses its
494own version numbers instead of ones from ES.
496newtype ExternalDocVersion = ExternalDocVersion DocVersion
497 deriving (Eq, Show, Ord, Bounded, Enum, ToJSON)
499{-| 'VersionControl' is specified when indexing documents as a
500optimistic concurrency control.
502data VersionControl = NoVersionControl
503 -- ^ Don't send a version. This is a pure overwrite.
504 | InternalVersion DocVersion
505 -- ^ Use the default ES versioning scheme. Only
506 -- index the document if the version is the same
507 -- as the one specified. Only applicable to
508 -- updates, as you should be getting Version from
510 | ExternalGT ExternalDocVersion
511 -- ^ Use your own version numbering. Only index
512 -- the document if the version is strictly higher
513 -- OR the document doesn't exist. The given
514 -- version will be used as the new version number
515 -- for the stored document. N.B. All updates must
516 -- increment this number, meaning there is some
517 -- global, external ordering of updates.
518 | ExternalGTE ExternalDocVersion
519 -- ^ Use your own version numbering. Only index
520 -- the document if the version is equal or higher
521 -- than the stored version. Will succeed if there
522 -- is no existing document. The given version will
523 -- be used as the new version number for the
524 -- stored document. Use with care, as this could
525 -- result in data loss.
526 | ForceVersion ExternalDocVersion
527 -- ^ The document will always be indexed and the
528 -- given version will be the new version. This is
529 -- typically used for correcting errors. Use with
530 -- care, as this could result in data loss.
531 deriving (Show, Eq, Ord)
533{-| 'DocumentParent' is used to specify a parent document.
535newtype DocumentParent = DocumentParent DocId
538{-| 'IndexDocumentSettings' are special settings supplied when indexing
539a document. For the best backwards compatiblity when new fields are
540added, you should probably prefer to start with 'defaultIndexDocumentSettings'
542data IndexDocumentSettings =
543 IndexDocumentSettings { idsVersionControl :: VersionControl
544 , idsParent :: Maybe DocumentParent
545 } deriving (Eq, Show)
547{-| Reasonable default settings. Chooses no version control and no parent.
549defaultIndexDocumentSettings :: IndexDocumentSettings
550defaultIndexDocumentSettings = IndexDocumentSettings NoVersionControl Nothing
552{-| 'Sort' is a synonym for a list of 'SortSpec's. Sort behavior is order
553 dependent with later sorts acting as tie-breakers for earlier sorts.
555type Sort = [SortSpec]
557{-| The two main kinds of 'SortSpec' are 'DefaultSortSpec' and
558 'GeoDistanceSortSpec'. The latter takes a 'SortOrder', 'GeoPoint', and
559 'DistanceUnit' to express "nearness" to a single geographical point as a
562<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
564data SortSpec = DefaultSortSpec DefaultSort
565 | GeoDistanceSortSpec SortOrder GeoPoint DistanceUnit deriving (Eq, Show)
567{-| 'DefaultSort' is usually the kind of 'SortSpec' you'll want. There's a
568 'mkSort' convenience function for when you want to specify only the most
571<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
574 DefaultSort { sortFieldName :: FieldName
575 , sortOrder :: SortOrder
577 , ignoreUnmapped :: Bool
578 , sortMode :: Maybe SortMode
579 , missingSort :: Maybe Missing
580 , nestedFilter :: Maybe Filter } deriving (Eq, Show)
582{-| 'SortOrder' is 'Ascending' or 'Descending', as you might expect. These get
583 encoded into "asc" or "desc" when turned into JSON.
585<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
587data SortOrder = Ascending
588 | Descending deriving (Eq, Show)
590{-| 'Missing' prescribes how to handle missing fields. A missing field can be
591 sorted last, first, or using a custom value as a substitute.
593<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_missing_values>
595data Missing = LastMissing
597 | CustomMissing Text deriving (Eq, Show)
599{-| 'SortMode' prescribes how to handle sorting array/multi-valued fields.
601http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_sort_mode_option
603data SortMode = SortMin
606 | SortAvg deriving (Eq, Show)
608{-| 'mkSort' defaults everything but the 'FieldName' and the 'SortOrder' so
609 that you can concisely describe the usual kind of 'SortSpec's you want.
611mkSort :: FieldName -> SortOrder -> DefaultSort
612mkSort fieldName sOrder = DefaultSort fieldName sOrder False Nothing Nothing Nothing
614{-| 'Cache' is for telling ES whether it should cache a 'Filter' not.
615 'Query's cannot be cached.
617type Cache = Bool -- caching on/off
621{-| 'PrefixValue' is used in 'PrefixQuery' as the main query component.
623type PrefixValue = Text
625{-| 'BooleanOperator' is the usual And/Or operators with an ES compatible
626 JSON encoding baked in. Used all over the place.
628data BooleanOperator = And | Or deriving (Eq, Show, Typeable)
630{-| 'ShardCount' is part of 'IndexSettings'
632newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
634{-| 'ReplicaCount' is part of 'IndexSettings'
636newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
638{-| 'Server' is used with the client functions to point at the ES instance
640newtype Server = Server Text deriving (Eq, Show)
642{-| 'IndexName' is used to describe which index to query/create/delete
644newtype IndexName = IndexName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
646{-| 'TemplateName' is used to describe which template to query/create/delete
648newtype TemplateName = TemplateName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
650{-| 'TemplatePattern' represents a pattern which is matched against index names
652newtype TemplatePattern = TemplatePattern Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
654{-| 'MappingName' is part of mappings which are how ES describes and schematizes
655 the data in the indices.
657newtype MappingName = MappingName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
659{-| 'DocId' is a generic wrapper value for expressing unique Document IDs.
660 Can be set by the user or created by ES itself. Often used in client
661 functions for poking at specific documents.
663newtype DocId = DocId Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
665{-| 'QueryString' is used to wrap query text bodies, be they human written or not.
667newtype QueryString = QueryString Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
669{-| 'FieldName' is used all over the place wherever a specific field within
670 a document needs to be specified, usually in 'Query's or 'Filter's.
672newtype FieldName = FieldName Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
675{-| 'Script' is often used in place of 'FieldName' to specify more
676complex ways of extracting a value from a document.
678newtype Script = Script { scriptText :: Text } deriving (Eq, Show)
680{-| 'CacheName' is used in 'RegexpFilter' for describing the
681 'CacheKey' keyed caching behavior.
683newtype CacheName = CacheName Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
685{-| 'CacheKey' is used in 'RegexpFilter' to key regex caching.
688 CacheKey Text deriving (Eq, Show, ToJSON, FromJSON, Typeable)
690 Existence Bool deriving (Eq, Show, ToJSON, FromJSON, Typeable)
692 NullValue Bool deriving (Eq, Show, ToJSON, FromJSON, Typeable)
693newtype CutoffFrequency =
694 CutoffFrequency Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
696 Analyzer Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
697newtype MaxExpansions =
698 MaxExpansions Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
700{-| 'Lenient', if set to true, will cause format based failures to be
701 ignored. I don't know what the bloody default is, Elasticsearch
702 documentation didn't say what it was. Let me know if you figure it out.
705 Lenient Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
707 Tiebreaker Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
709 Boost Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
711 BoostTerms Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
713{-| 'MinimumMatch' controls how many should clauses in the bool query should
714 match. Can be an absolute value (2) or a percentage (30%) or a
717newtype MinimumMatch =
718 MinimumMatch Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
719newtype DisableCoord =
720 DisableCoord Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
721newtype IgnoreTermFrequency =
722 IgnoreTermFrequency Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
723newtype MinimumTermFrequency =
724 MinimumTermFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
725newtype MaxQueryTerms =
726 MaxQueryTerms Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
728 Fuzziness Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
730{-| 'PrefixLength' is the prefix length used in queries, defaults to 0. -}
731newtype PrefixLength =
732 PrefixLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
734 TypeName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
735newtype PercentMatch =
736 PercentMatch Double deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
738 StopWord Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
740 QueryPath Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
742{-| Allowing a wildcard at the beginning of a word (eg "*ing") is particularly
743 heavy, because all terms in the index need to be examined, just in case
744 they match. Leading wildcards can be disabled by setting
745 'AllowLeadingWildcard' to false. -}
746newtype AllowLeadingWildcard =
747 AllowLeadingWildcard Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
748newtype LowercaseExpanded =
749 LowercaseExpanded Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
750newtype EnablePositionIncrements =
751 EnablePositionIncrements Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
753{-| By default, wildcard terms in a query are not analyzed.
754 Setting 'AnalyzeWildcard' to true enables best-effort analysis.
756newtype AnalyzeWildcard = AnalyzeWildcard Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
758{-| 'GeneratePhraseQueries' defaults to false.
760newtype GeneratePhraseQueries =
761 GeneratePhraseQueries Bool deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
763{-| 'Locale' is used for string conversions - defaults to ROOT.
765newtype Locale = Locale Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
766newtype MaxWordLength = MaxWordLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
767newtype MinWordLength = MinWordLength Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
769{-| 'PhraseSlop' sets the default slop for phrases, 0 means exact
770 phrase matches. Default is 0.
772newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
773newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
774newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
776{-| 'unpackId' is a silly convenience function that gets used once.
778unpackId :: DocId -> Text
779unpackId (DocId docId) = docId
781type TrackSortScores = Bool
782newtype From = From Int deriving (Eq, Show, ToJSON)
783newtype Size = Size Int deriving (Eq, Show, ToJSON)
785data Search = Search { queryBody :: Maybe Query
786 , filterBody :: Maybe Filter
787 , sortBody :: Maybe Sort
788 , aggBody :: Maybe Aggregations
789 , highlight :: Maybe Highlights
791 , trackSortScores :: TrackSortScores
794 , searchType :: SearchType
795 , fields :: Maybe [FieldName]
796 , source :: Maybe Source } deriving (Eq, Show)
798data SearchType = SearchTypeQueryThenFetch
799 | SearchTypeDfsQueryThenFetch
802 | SearchTypeQueryAndFetch
803 | SearchTypeDfsQueryAndFetch
808 | SourcePatterns PatternOrPatterns
809 | SourceIncludeExclude Include Exclude
812data PatternOrPatterns = PopPattern Pattern
813 | PopPatterns [Pattern] deriving (Eq, Show)
815data Include = Include [Pattern] deriving (Eq, Show)
816data Exclude = Exclude [Pattern] deriving (Eq, Show)
818newtype Pattern = Pattern Text deriving (Eq, Show)
820data Highlights = Highlights { globalsettings :: Maybe HighlightSettings
821 , highlightFields :: [FieldHighlight]
822 } deriving (Show, Eq)
824data FieldHighlight = FieldHighlight FieldName (Maybe HighlightSettings)
828data HighlightSettings = Plain PlainHighlight
829 | Postings PostingsHighlight
830 | FastVector FastVectorHighlight
833 PlainHighlight { plainCommon :: Maybe CommonHighlight
834 , plainNonPost :: Maybe NonPostings } deriving (Show, Eq)
836 -- This requires that index_options are set to 'offset' in the mapping.
837data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Show, Eq)
839-- This requires that term_vector is set to 'with_positions_offsets' in the mapping.
840data FastVectorHighlight =
841 FastVectorHighlight { fvCommon :: Maybe CommonHighlight
842 , fvNonPostSettings :: Maybe NonPostings
843 , boundaryChars :: Maybe Text
844 , boundaryMaxScan :: Maybe Int
845 , fragmentOffset :: Maybe Int
846 , matchedFields :: [Text]
847 , phraseLimit :: Maybe Int
848 } deriving (Show, Eq)
850data CommonHighlight =
851 CommonHighlight { order :: Maybe Text
852 , forceSource :: Maybe Bool
853 , tag :: Maybe HighlightTag
854 , encoder :: Maybe HighlightEncoder
855 , noMatchSize :: Maybe Int
856 , highlightQuery :: Maybe Query
857 , requireFieldMatch :: Maybe Bool
858 } deriving (Show, Eq)
860-- Settings that are only applicable to FastVector and Plain highlighters.
862 NonPostings { fragmentSize :: Maybe Int
863 , numberOfFragments :: Maybe Int} deriving (Show, Eq)
865data HighlightEncoder = DefaultEncoder
869-- NOTE: Should the tags use some kind of HTML type, rather than Text?
870data HighlightTag = TagSchema Text
871 | CustomTags ([Text], [Text]) -- Only uses more than the first value in the lists if fvh
876 TermQuery Term (Maybe Boost)
877 | TermsQuery Text (NonEmpty Text)
878 | QueryMatchQuery MatchQuery
879 | QueryMultiMatchQuery MultiMatchQuery
880 | QueryBoolQuery BoolQuery
881 | QueryBoostingQuery BoostingQuery
882 | QueryCommonTermsQuery CommonTermsQuery
883 | ConstantScoreFilter Filter Boost
884 | ConstantScoreQuery Query Boost
885 | QueryDisMaxQuery DisMaxQuery
886 | QueryFilteredQuery FilteredQuery
887 | QueryFuzzyLikeThisQuery FuzzyLikeThisQuery
888 | QueryFuzzyLikeFieldQuery FuzzyLikeFieldQuery
889 | QueryFuzzyQuery FuzzyQuery
890 | QueryHasChildQuery HasChildQuery
891 | QueryHasParentQuery HasParentQuery
892 | IdsQuery MappingName [DocId]
893 | QueryIndicesQuery IndicesQuery
894 | MatchAllQuery (Maybe Boost)
895 | QueryMoreLikeThisQuery MoreLikeThisQuery
896 | QueryMoreLikeThisFieldQuery MoreLikeThisFieldQuery
897 | QueryNestedQuery NestedQuery
898 | QueryPrefixQuery PrefixQuery
899 | QueryQueryStringQuery QueryStringQuery
900 | QuerySimpleQueryStringQuery SimpleQueryStringQuery
901 | QueryRangeQuery RangeQuery
902 | QueryRegexpQuery RegexpQuery
903 deriving (Eq, Show, Typeable)
906 RegexpQuery { regexpQueryField :: FieldName
907 , regexpQuery :: Regexp
908 , regexpQueryFlags :: RegexpFlags
909 , regexpQueryBoost :: Maybe Boost
910 } deriving (Eq, Show, Typeable)
913 RangeQuery { rangeQueryField :: FieldName
914 , rangeQueryRange :: RangeValue
915 , rangeQueryBoost :: Boost } deriving (Eq, Show, Typeable)
917mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
918mkRangeQuery f r = RangeQuery f r (Boost 1.0)
920data SimpleQueryStringQuery =
921 SimpleQueryStringQuery
922 { simpleQueryStringQuery :: QueryString
923 , simpleQueryStringField :: Maybe FieldOrFields
924 , simpleQueryStringOperator :: Maybe BooleanOperator
925 , simpleQueryStringAnalyzer :: Maybe Analyzer
926 , simpleQueryStringFlags :: Maybe (NonEmpty SimpleQueryFlag)
927 , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
928 , simpleQueryStringLocale :: Maybe Locale
929 } deriving (Eq, Show, Typeable)
931data SimpleQueryFlag =
938 | SimpleQueryPrecedence
940 | SimpleQueryWhitespace
943 | SimpleQuerySlop deriving (Eq, Show, Typeable)
945-- use_dis_max and tie_breaker when fields are plural?
946data QueryStringQuery =
948 { queryStringQuery :: QueryString
949 , queryStringDefaultField :: Maybe FieldName
950 , queryStringOperator :: Maybe BooleanOperator
951 , queryStringAnalyzer :: Maybe Analyzer
952 , queryStringAllowLeadingWildcard :: Maybe AllowLeadingWildcard
953 , queryStringLowercaseExpanded :: Maybe LowercaseExpanded
954 , queryStringEnablePositionIncrements :: Maybe EnablePositionIncrements
955 , queryStringFuzzyMaxExpansions :: Maybe MaxExpansions
956 , queryStringFuzziness :: Maybe Fuzziness
957 , queryStringFuzzyPrefixLength :: Maybe PrefixLength
958 , queryStringPhraseSlop :: Maybe PhraseSlop
959 , queryStringBoost :: Maybe Boost
960 , queryStringAnalyzeWildcard :: Maybe AnalyzeWildcard
961 , queryStringGeneratePhraseQueries :: Maybe GeneratePhraseQueries
962 , queryStringMinimumShouldMatch :: Maybe MinimumMatch
963 , queryStringLenient :: Maybe Lenient
964 , queryStringLocale :: Maybe Locale
965 } deriving (Eq, Show, Typeable)
967mkQueryStringQuery :: QueryString -> QueryStringQuery
968mkQueryStringQuery qs =
969 QueryStringQuery qs Nothing Nothing
970 Nothing Nothing Nothing Nothing
971 Nothing Nothing Nothing Nothing
972 Nothing Nothing Nothing Nothing
975data FieldOrFields = FofField FieldName
976 | FofFields (NonEmpty FieldName) deriving (Eq, Show, Typeable)
980 { prefixQueryField :: FieldName
981 , prefixQueryPrefixValue :: Text
982 , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show, Typeable)
986 { nestedQueryPath :: QueryPath
987 , nestedQueryScoreType :: ScoreType
988 , nestedQuery :: Query } deriving (Eq, Show, Typeable)
990data MoreLikeThisFieldQuery =
991 MoreLikeThisFieldQuery
992 { moreLikeThisFieldText :: Text
993 , moreLikeThisFieldFields :: FieldName
995 , moreLikeThisFieldPercentMatch :: Maybe PercentMatch
996 , moreLikeThisFieldMinimumTermFreq :: Maybe MinimumTermFrequency
997 , moreLikeThisFieldMaxQueryTerms :: Maybe MaxQueryTerms
998 , moreLikeThisFieldStopWords :: Maybe (NonEmpty StopWord)
999 , moreLikeThisFieldMinDocFrequency :: Maybe MinDocFrequency
1000 , moreLikeThisFieldMaxDocFrequency :: Maybe MaxDocFrequency
1001 , moreLikeThisFieldMinWordLength :: Maybe MinWordLength
1002 , moreLikeThisFieldMaxWordLength :: Maybe MaxWordLength
1003 , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
1004 , moreLikeThisFieldBoost :: Maybe Boost
1005 , moreLikeThisFieldAnalyzer :: Maybe Analyzer
1006 } deriving (Eq, Show, Typeable)
1008data MoreLikeThisQuery =
1010 { moreLikeThisText :: Text
1011 , moreLikeThisFields :: Maybe (NonEmpty FieldName)
1012 -- default 0.3 (30%)
1013 , moreLikeThisPercentMatch :: Maybe PercentMatch
1014 , moreLikeThisMinimumTermFreq :: Maybe MinimumTermFrequency
1015 , moreLikeThisMaxQueryTerms :: Maybe MaxQueryTerms
1016 , moreLikeThisStopWords :: Maybe (NonEmpty StopWord)
1017 , moreLikeThisMinDocFrequency :: Maybe MinDocFrequency
1018 , moreLikeThisMaxDocFrequency :: Maybe MaxDocFrequency
1019 , moreLikeThisMinWordLength :: Maybe MinWordLength
1020 , moreLikeThisMaxWordLength :: Maybe MaxWordLength
1021 , moreLikeThisBoostTerms :: Maybe BoostTerms
1022 , moreLikeThisBoost :: Maybe Boost
1023 , moreLikeThisAnalyzer :: Maybe Analyzer
1024 } deriving (Eq, Show, Typeable)
1028 { indicesQueryIndices :: [IndexName]
1029 , indicesQuery :: Query
1031 , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show, Typeable)
1033data HasParentQuery =
1035 { hasParentQueryType :: TypeName
1036 , hasParentQuery :: Query
1037 , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Typeable)
1041 { hasChildQueryType :: TypeName
1042 , hasChildQuery :: Query
1043 , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show, Typeable)
1049 | ScoreTypeNone deriving (Eq, Show, Typeable)
1052 FuzzyQuery { fuzzyQueryField :: FieldName
1053 , fuzzyQueryValue :: Text
1054 , fuzzyQueryPrefixLength :: PrefixLength
1055 , fuzzyQueryMaxExpansions :: MaxExpansions
1056 , fuzzyQueryFuzziness :: Fuzziness
1057 , fuzzyQueryBoost :: Maybe Boost
1058 } deriving (Eq, Show, Typeable)
1060data FuzzyLikeFieldQuery =
1062 { fuzzyLikeField :: FieldName
1063 -- anaphora is good for the soul.
1064 , fuzzyLikeFieldText :: Text
1065 , fuzzyLikeFieldMaxQueryTerms :: MaxQueryTerms
1066 , fuzzyLikeFieldIgnoreTermFrequency :: IgnoreTermFrequency
1067 , fuzzyLikeFieldFuzziness :: Fuzziness
1068 , fuzzyLikeFieldPrefixLength :: PrefixLength
1069 , fuzzyLikeFieldBoost :: Boost
1070 , fuzzyLikeFieldAnalyzer :: Maybe Analyzer
1071 } deriving (Eq, Show, Typeable)
1073data FuzzyLikeThisQuery =
1075 { fuzzyLikeFields :: [FieldName]
1076 , fuzzyLikeText :: Text
1077 , fuzzyLikeMaxQueryTerms :: MaxQueryTerms
1078 , fuzzyLikeIgnoreTermFrequency :: IgnoreTermFrequency
1079 , fuzzyLikeFuzziness :: Fuzziness
1080 , fuzzyLikePrefixLength :: PrefixLength
1081 , fuzzyLikeBoost :: Boost
1082 , fuzzyLikeAnalyzer :: Maybe Analyzer
1083 } deriving (Eq, Show, Typeable)
1087 { filteredQuery :: Query
1088 , filteredFilter :: Filter } deriving (Eq, Show, Typeable)
1091 DisMaxQuery { disMaxQueries :: [Query]
1093 , disMaxTiebreaker :: Tiebreaker
1094 , disMaxBoost :: Maybe Boost
1095 } deriving (Eq, Show, Typeable)
1098 MatchQuery { matchQueryField :: FieldName
1099 , matchQueryQueryString :: QueryString
1100 , matchQueryOperator :: BooleanOperator
1101 , matchQueryZeroTerms :: ZeroTermsQuery
1102 , matchQueryCutoffFrequency :: Maybe CutoffFrequency
1103 , matchQueryMatchType :: Maybe MatchQueryType
1104 , matchQueryAnalyzer :: Maybe Analyzer
1105 , matchQueryMaxExpansions :: Maybe MaxExpansions
1106 , matchQueryLenient :: Maybe Lenient
1107 , matchQueryBoost :: Maybe Boost } deriving (Eq, Show, Typeable)
1109{-| 'mkMatchQuery' is a convenience function that defaults the less common parameters,
1110 enabling you to provide only the 'FieldName' and 'QueryString' to make a 'MatchQuery'
1112mkMatchQuery :: FieldName -> QueryString -> MatchQuery
1113mkMatchQuery field query = MatchQuery field query Or ZeroTermsNone Nothing Nothing Nothing Nothing Nothing Nothing
1115data MatchQueryType =
1117 | MatchPhrasePrefix deriving (Eq, Show, Typeable)
1119data MultiMatchQuery =
1120 MultiMatchQuery { multiMatchQueryFields :: [FieldName]
1121 , multiMatchQueryString :: QueryString
1122 , multiMatchQueryOperator :: BooleanOperator
1123 , multiMatchQueryZeroTerms :: ZeroTermsQuery
1124 , multiMatchQueryTiebreaker :: Maybe Tiebreaker
1125 , multiMatchQueryType :: Maybe MultiMatchQueryType
1126 , multiMatchQueryCutoffFrequency :: Maybe CutoffFrequency
1127 , multiMatchQueryAnalyzer :: Maybe Analyzer
1128 , multiMatchQueryMaxExpansions :: Maybe MaxExpansions
1129 , multiMatchQueryLenient :: Maybe Lenient } deriving (Eq, Show, Typeable)
1131{-| 'mkMultiMatchQuery' is a convenience function that defaults the less common parameters,
1132 enabling you to provide only the list of 'FieldName's and 'QueryString' to
1133 make a 'MultiMatchQuery'.
1136mkMultiMatchQuery :: [FieldName] -> QueryString -> MultiMatchQuery
1137mkMultiMatchQuery matchFields query =
1138 MultiMatchQuery matchFields query
1139 Or ZeroTermsNone Nothing Nothing Nothing Nothing Nothing Nothing
1141data MultiMatchQueryType =
1142 MultiMatchBestFields
1143 | MultiMatchMostFields
1144 | MultiMatchCrossFields
1146 | MultiMatchPhrasePrefix deriving (Eq, Show, Typeable)
1149 BoolQuery { boolQueryMustMatch :: [Query]
1150 , boolQueryMustNotMatch :: [Query]
1151 , boolQueryShouldMatch :: [Query]
1152 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
1153 , boolQueryBoost :: Maybe Boost
1154 , boolQueryDisableCoord :: Maybe DisableCoord
1155 } deriving (Eq, Show, Typeable)
1157mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
1158mkBoolQuery must mustNot should =
1159 BoolQuery must mustNot should Nothing Nothing Nothing
1162 BoostingQuery { positiveQuery :: Query
1163 , negativeQuery :: Query
1164 , negativeBoost :: Boost } deriving (Eq, Show, Typeable)
1166data CommonTermsQuery =
1167 CommonTermsQuery { commonField :: FieldName
1168 , commonQuery :: QueryString
1169 , commonCutoffFrequency :: CutoffFrequency
1170 , commonLowFreqOperator :: BooleanOperator
1171 , commonHighFreqOperator :: BooleanOperator
1172 , commonMinimumShouldMatch :: Maybe CommonMinimumMatch
1173 , commonBoost :: Maybe Boost
1174 , commonAnalyzer :: Maybe Analyzer
1175 , commonDisableCoord :: Maybe DisableCoord
1176 } deriving (Eq, Show, Typeable)
1178data CommonMinimumMatch =
1179 CommonMinimumMatchHighLow MinimumMatchHighLow
1180 | CommonMinimumMatch MinimumMatch
1181 deriving (Eq, Show, Typeable)
1183data MinimumMatchHighLow =
1184 MinimumMatchHighLow { lowFreq :: MinimumMatch
1185 , highFreq :: MinimumMatch } deriving (Eq, Show, Typeable)
1187data Filter = AndFilter [Filter] Cache
1188 | OrFilter [Filter] Cache
1189 | NotFilter Filter Cache
1191 | BoolFilter BoolMatch
1192 | ExistsFilter FieldName -- always cached
1193 | GeoBoundingBoxFilter GeoBoundingBoxConstraint
1194 | GeoDistanceFilter GeoPoint Distance DistanceType OptimizeBbox Cache
1195 | GeoDistanceRangeFilter GeoPoint DistanceRange
1196 | GeoPolygonFilter FieldName [LatLon]
1197 | IdsFilter MappingName [DocId]
1199 | MissingFilter FieldName Existence NullValue
1200 | PrefixFilter FieldName PrefixValue Cache
1201 | QueryFilter Query Cache
1202 | RangeFilter FieldName RangeValue RangeExecution Cache
1203 | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
1204 | TermFilter Term Cache
1205 deriving (Eq, Show, Typeable)
1207data ZeroTermsQuery = ZeroTermsNone
1208 | ZeroTermsAll deriving (Eq, Show, Typeable)
1210data RangeExecution = RangeExecutionIndex
1211 | RangeExecutionFielddata deriving (Eq, Show, Typeable)
1213newtype Regexp = Regexp Text deriving (Eq, Show, FromJSON)
1215data RegexpFlags = AllRegexpFlags
1217 | SomeRegexpFlags (NonEmpty RegexpFlag) deriving (Eq, Show)
1219data RegexpFlag = AnyString
1224 | Interval deriving (Eq, Show)
1226newtype LessThan = LessThan Double deriving (Eq, Show)
1227newtype LessThanEq = LessThanEq Double deriving (Eq, Show)
1228newtype GreaterThan = GreaterThan Double deriving (Eq, Show)
1229newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show)
1231newtype LessThanD = LessThanD UTCTime deriving (Eq, Show)
1232newtype LessThanEqD = LessThanEqD UTCTime deriving (Eq, Show)
1233newtype GreaterThanD = GreaterThanD UTCTime deriving (Eq, Show)
1234newtype GreaterThanEqD = GreaterThanEqD UTCTime deriving (Eq, Show)
1236data RangeValue = RangeDateLte LessThanEqD
1237 | RangeDateLt LessThanD
1238 | RangeDateGte GreaterThanEqD
1239 | RangeDateGt GreaterThanD
1240 | RangeDateGtLt GreaterThanD LessThanD
1241 | RangeDateGteLte GreaterThanEqD LessThanEqD
1242 | RangeDateGteLt GreaterThanEqD LessThanD
1243 | RangeDateGtLte GreaterThanD LessThanEqD
1244 | RangeDoubleLte LessThanEq
1245 | RangeDoubleLt LessThan
1246 | RangeDoubleGte GreaterThanEq
1247 | RangeDoubleGt GreaterThan
1248 | RangeDoubleGtLt GreaterThan LessThan
1249 | RangeDoubleGteLte GreaterThanEq LessThanEq
1250 | RangeDoubleGteLt GreaterThanEq LessThan
1251 | RangeDoubleGtLte GreaterThan LessThanEq
1254rangeValueToPair :: RangeValue -> [Pair]
1255rangeValueToPair rv = case rv of
1256 RangeDateLte (LessThanEqD t) -> ["lte" .= t]
1257 RangeDateGte (GreaterThanEqD t) -> ["gte" .= t]
1258 RangeDateLt (LessThanD t) -> ["lt" .= t]
1259 RangeDateGt (GreaterThanD t) -> ["gt" .= t]
1260 RangeDateGteLte (GreaterThanEqD l) (LessThanEqD g) -> ["gte" .= l, "lte" .= g]
1261 RangeDateGtLte (GreaterThanD l) (LessThanEqD g) -> ["gt" .= l, "lte" .= g]
1262 RangeDateGteLt (GreaterThanEqD l) (LessThanD g) -> ["gte" .= l, "lt" .= g]
1263 RangeDateGtLt (GreaterThanD l) (LessThanD g) -> ["gt" .= l, "lt" .= g]
1264 RangeDoubleLte (LessThanEq t) -> ["lte" .= t]
1265 RangeDoubleGte (GreaterThanEq t) -> ["gte" .= t]
1266 RangeDoubleLt (LessThan t) -> ["lt" .= t]
1267 RangeDoubleGt (GreaterThan t) -> ["gt" .= t]
1268 RangeDoubleGteLte (GreaterThanEq l) (LessThanEq g) -> ["gte" .= l, "lte" .= g]
1269 RangeDoubleGtLte (GreaterThan l) (LessThanEq g) -> ["gt" .= l, "lte" .= g]
1270 RangeDoubleGteLt (GreaterThanEq l) (LessThan g) -> ["gte" .= l, "lt" .= g]
1271 RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
1273data Term = Term { termField :: Text
1274 , termValue :: Text } deriving (Eq, Show, Typeable)
1276data BoolMatch = MustMatch Term Cache
1277 | MustNotMatch Term Cache
1278 | ShouldMatch [Term] Cache deriving (Eq, Show, Typeable)
1280-- "memory" or "indexed"
1281data GeoFilterType = GeoFilterMemory
1282 | GeoFilterIndexed deriving (Eq, Show, Typeable)
1284data LatLon = LatLon { lat :: Double
1285 , lon :: Double } deriving (Eq, Show, Typeable)
1287data GeoBoundingBox =
1288 GeoBoundingBox { topLeft :: LatLon
1289 , bottomRight :: LatLon } deriving (Eq, Show, Typeable)
1291data GeoBoundingBoxConstraint =
1292 GeoBoundingBoxConstraint { geoBBField :: FieldName
1293 , constraintBox :: GeoBoundingBox
1294 , bbConstraintcache :: Cache
1295 , geoType :: GeoFilterType
1296 } deriving (Eq, Show, Typeable)
1299 GeoPoint { geoField :: FieldName
1300 , latLon :: LatLon} deriving (Eq, Show, Typeable)
1302data DistanceUnit = Miles
1310 | NauticalMiles deriving (Eq, Show, Typeable)
1312data DistanceType = Arc
1313 | SloppyArc -- doesn't exist <1.0
1314 | Plane deriving (Eq, Show, Typeable)
1316data OptimizeBbox = OptimizeGeoFilterType GeoFilterType
1317 | NoOptimizeBbox deriving (Eq, Show, Typeable)
1320 Distance { coefficient :: Double
1321 , unit :: DistanceUnit } deriving (Eq, Show, Typeable)
1324 DistanceRange { distanceFrom :: Distance
1325 , distanceTo :: Distance } deriving (Eq, Show)
1327data SearchResult a =
1328 SearchResult { took :: Int
1330 , shards :: ShardResult
1331 , searchHits :: SearchHits a
1332 , aggregations :: Maybe AggregationResults
1333 , scrollId :: Maybe ScrollId } deriving (Eq, Show)
1335newtype ScrollId = ScrollId Text deriving (Eq, Show, Ord, ToJSON, FromJSON)
1337type Score = Maybe Double
1340 SearchHits { hitsTotal :: Int
1342 , hits :: [Hit a] } deriving (Eq, Show)
1345instance Monoid (SearchHits a) where
1346 mempty = SearchHits 0 Nothing mempty
1347 mappend (SearchHits ta ma ha) (SearchHits tb mb hb) =
1348 SearchHits (ta + tb) (max ma mb) (ha <> hb)
1352 Hit { hitIndex :: IndexName
1353 , hitType :: MappingName
1356 , hitSource :: Maybe a
1357 , hitHighlight :: Maybe HitHighlight } deriving (Eq, Show)
1360 ShardResult { shardTotal :: Int
1361 , shardsSuccessful :: Int
1362 , shardsFailed :: Int } deriving (Eq, Show, Generic)
1364type HitHighlight = M.Map Text [Text]
1366showText :: Show a => a -> Text
1367showText = T.pack . show
1369type Aggregations = M.Map Text Aggregation
1371emptyAggregations :: Aggregations
1372emptyAggregations = M.empty
1374mkAggregations :: Text -> Aggregation -> Aggregations
1375mkAggregations name aggregation = M.insert name aggregation emptyAggregations
1377data TermOrder = TermOrder{ termSortField :: Text
1378 , termSortOrder :: SortOrder } deriving (Eq, Show)
1380data TermInclusion = TermInclusion Text
1381 | TermPattern Text Text deriving (Eq, Show)
1383data CollectionMode = BreadthFirst
1384 | DepthFirst deriving (Eq, Show)
1386data ExecutionHint = Ordinals
1388 | GlobalOrdinalsHash
1389 | GlobalOrdinalsLowCardinality
1390 | Map deriving (Eq, Show)
1392data TimeInterval = Weeks
1396 | Seconds deriving (Eq)
1406 | FractionalInterval Float TimeInterval deriving (Eq, Show)
1408data Aggregation = TermsAgg TermsAggregation
1409 | DateHistogramAgg DateHistogramAggregation
1410 | ValueCountAgg ValueCountAggregation
1411 | FilterAgg FilterAggregation deriving (Eq, Show)
1414data TermsAggregation = TermsAggregation { term :: Either Text Text
1415 , termInclude :: Maybe TermInclusion
1416 , termExclude :: Maybe TermInclusion
1417 , termOrder :: Maybe TermOrder
1418 , termMinDocCount :: Maybe Int
1419 , termSize :: Maybe Int
1420 , termShardSize :: Maybe Int
1421 , termCollectMode :: Maybe CollectionMode
1422 , termExecutionHint :: Maybe ExecutionHint
1423 , termAggs :: Maybe Aggregations
1424 } deriving (Eq, Show)
1426data DateHistogramAggregation = DateHistogramAggregation { dateField :: FieldName
1427 , dateInterval :: Interval
1428 , dateFormat :: Maybe Text
1429 -- pre and post deprecated in 1.5
1430 , datePreZone :: Maybe Text
1431 , datePostZone :: Maybe Text
1432 , datePreOffset :: Maybe Text
1433 , datePostOffset :: Maybe Text
1434 , dateAggs :: Maybe Aggregations
1435 } deriving (Eq, Show)
1437-- | See <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html> for more information.
1438data ValueCountAggregation = FieldValueCount FieldName
1439 | ScriptValueCount Script deriving (Eq, Show)
1441-- | 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.
1442data FilterAggregation = FilterAggregation { faFilter :: Filter
1443 , faAggs :: Maybe Aggregations} deriving (Eq, Show)
1445mkTermsAggregation :: Text -> TermsAggregation
1446mkTermsAggregation t = TermsAggregation (Left t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1448mkTermsScriptAggregation :: Text -> TermsAggregation
1449mkTermsScriptAggregation t = TermsAggregation (Right t) Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
1451mkDateHistogram :: FieldName -> Interval -> DateHistogramAggregation
1452mkDateHistogram t i = DateHistogramAggregation t i Nothing Nothing Nothing Nothing Nothing Nothing
1454instance ToJSON Version where
1455 toJSON Version {..} = object ["number" .= number
1456 ,"build_hash" .= build_hash
1457 ,"build_timestamp" .= build_timestamp
1458 ,"build_snapshot" .= build_snapshot
1459 ,"lucene_version" .= lucene_version]
1461instance FromJSON Version where
1462 parseJSON = withObject "Version" parse
1463 where parse o = Version
1465 <*> o .: "build_hash"
1466 <*> o .: "build_timestamp"
1467 <*> o .: "build_snapshot"
1468 <*> o .: "lucene_version"
1470instance ToJSON TermOrder where
1471 toJSON (TermOrder termSortField termSortOrder) = object [termSortField .= termSortOrder]
1473instance ToJSON TermInclusion where
1474 toJSON (TermInclusion x) = toJSON x
1475 toJSON (TermPattern pattern flags) = omitNulls [ "pattern" .= pattern,
1478instance ToJSON CollectionMode where
1479 toJSON BreadthFirst = "breadth_first"
1480 toJSON DepthFirst = "depth_first"
1482instance ToJSON ExecutionHint where
1483 toJSON Ordinals = "ordinals"
1484 toJSON GlobalOrdinals = "global_ordinals"
1485 toJSON GlobalOrdinalsHash = "global_ordinals_hash"
1486 toJSON GlobalOrdinalsLowCardinality = "global_ordinals_low_cardinality"
1489instance ToJSON Interval where
1490 toJSON Year = "year"
1491 toJSON Quarter = "quarter"
1492 toJSON Month = "month"
1493 toJSON Week = "week"
1495 toJSON Hour = "hour"
1496 toJSON Minute = "minute"
1497 toJSON Second = "second"
1498 toJSON (FractionalInterval fraction interval) = toJSON $ show fraction ++ show interval
1500instance Show TimeInterval where
1507instance ToJSON Aggregation where
1508 toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint termAggs)) =
1509 omitNulls ["terms" .= omitNulls [ toJSON' term,
1510 "include" .= include,
1511 "exclude" .= exclude,
1513 "min_doc_count" .= minDocCount,
1515 "shard_size" .= shardSize,
1516 "collect_mode" .= collectMode,
1517 "execution_hint" .= executionHint
1519 "aggs" .= termAggs ]
1521 toJSON' x = case x of { Left y -> "field" .= y; Right y -> "script" .= y }
1523 toJSON (DateHistogramAgg (DateHistogramAggregation field interval format preZone postZone preOffset postOffset dateHistoAggs)) =
1524 omitNulls ["date_histogram" .= omitNulls [ "field" .= field,
1525 "interval" .= interval,
1527 "pre_zone" .= preZone,
1528 "post_zone" .= postZone,
1529 "pre_offset" .= preOffset,
1530 "post_offset" .= postOffset
1532 "aggs" .= dateHistoAggs ]
1533 toJSON (ValueCountAgg a) = object ["value_count" .= v]
1535 (FieldValueCount (FieldName n)) -> object ["field" .= n]
1536 (ScriptValueCount (Script s)) -> object ["script" .= s]
1537 toJSON (FilterAgg (FilterAggregation filt ags)) =
1538 omitNulls [ "filter" .= filt
1541type AggregationResults = M.Map Text Value
1543class BucketAggregation a where
1545 docCount :: a -> Int
1546 aggs :: a -> Maybe AggregationResults
1549data Bucket a = Bucket { buckets :: [a]} deriving (Show)
1551data TermsResult = TermsResult { termKey :: Text
1552 , termsDocCount :: Int
1553 , termsAggs :: Maybe AggregationResults } deriving (Show)
1555data DateHistogramResult = DateHistogramResult { dateKey :: Int
1556 , dateKeyStr :: Maybe Text
1557 , dateDocCount :: Int
1558 , dateHistogramAggs :: Maybe AggregationResults } deriving (Show)
1560toTerms :: Text -> AggregationResults -> Maybe (Bucket TermsResult)
1561toTerms t a = M.lookup t a >>= deserialize
1562 where deserialize = parseMaybe parseJSON
1564toDateHistogram :: Text -> AggregationResults -> Maybe (Bucket DateHistogramResult)
1565toDateHistogram t a = M.lookup t a >>= deserialize
1566 where deserialize = parseMaybe parseJSON
1568instance BucketAggregation TermsResult where
1570 docCount = termsDocCount
1573instance BucketAggregation DateHistogramResult where
1574 key = showText . dateKey
1575 docCount = dateDocCount
1576 aggs = dateHistogramAggs
1578instance (FromJSON a, BucketAggregation a) => FromJSON (Bucket a) where
1579 parseJSON (Object v) = Bucket <$>
1581 parseJSON _ = mempty
1583instance FromJSON TermsResult where
1584 parseJSON (Object v) = TermsResult <$>
1586 v .: "doc_count" <*>
1587 v .:? "aggregations"
1588 parseJSON _ = mempty
1590instance FromJSON DateHistogramResult where
1591 parseJSON (Object v) = DateHistogramResult <$>
1593 v .:? "key_as_string" <*>
1594 v .: "doc_count" <*>
1595 v .:? "aggregations"
1596 parseJSON _ = mempty
1598instance Monoid Filter where
1599 mempty = IdentityFilter
1600 mappend a b = AndFilter [a, b] defaultCache
1602instance Seminearring Filter where
1603 a <||> b = OrFilter [a, b] defaultCache
1605instance ToJSON Filter where
1606 toJSON (AndFilter filters cache) =
1608 object [ "filters" .= fmap toJSON filters
1609 , "_cache" .= cache]]
1611 toJSON (OrFilter filters cache) =
1613 object [ "filters" .= fmap toJSON filters
1614 , "_cache" .= cache]]
1616 toJSON (NotFilter notFilter cache) =
1618 object ["filter" .= notFilter
1619 , "_cache" .= cache]]
1621 toJSON (IdentityFilter) =
1622 object ["match_all" .= object []]
1624 toJSON (TermFilter (Term termFilterField termFilterValue) cache) =
1625 object ["term" .= object base]
1626 where base = [termFilterField .= termFilterValue,
1629 toJSON (ExistsFilter (FieldName fieldName)) =
1630 object ["exists" .= object
1631 ["field" .= fieldName]]
1633 toJSON (BoolFilter boolMatch) =
1634 object ["bool" .= boolMatch]
1636 toJSON (GeoBoundingBoxFilter bbConstraint) =
1637 object ["geo_bounding_box" .= bbConstraint]
1639 toJSON (GeoDistanceFilter (GeoPoint (FieldName distanceGeoField) geoDistLatLon)
1640 distance distanceType optimizeBbox cache) =
1641 object ["geo_distance" .=
1642 object ["distance" .= distance
1643 , "distance_type" .= distanceType
1644 , "optimize_bbox" .= optimizeBbox
1645 , distanceGeoField .= geoDistLatLon
1646 , "_cache" .= cache]]
1648 toJSON (GeoDistanceRangeFilter (GeoPoint (FieldName gddrField) drLatLon)
1649 (DistanceRange geoDistRangeDistFrom drDistanceTo)) =
1650 object ["geo_distance_range" .=
1651 object ["from" .= geoDistRangeDistFrom
1652 , "to" .= drDistanceTo
1653 , gddrField .= drLatLon]]
1655 toJSON (GeoPolygonFilter (FieldName geoPolygonFilterField) latLons) =
1656 object ["geo_polygon" .=
1657 object [geoPolygonFilterField .=
1658 object ["points" .= fmap toJSON latLons]]]
1660 toJSON (IdsFilter (MappingName mappingName) values) =
1662 object ["type" .= mappingName
1663 , "values" .= fmap unpackId values]]
1665 toJSON (LimitFilter limit) =
1666 object ["limit" .= object ["value" .= limit]]
1668 toJSON (MissingFilter (FieldName fieldName) (Existence existence) (NullValue nullValue)) =
1669 object ["missing" .=
1670 object ["field" .= fieldName
1671 , "existence" .= existence
1672 , "null_value" .= nullValue]]
1674 toJSON (PrefixFilter (FieldName fieldName) fieldValue cache) =
1676 object [fieldName .= fieldValue
1677 , "_cache" .= cache]]
1679 toJSON (QueryFilter query False) =
1680 object ["query" .= toJSON query ]
1681 toJSON (QueryFilter query True) =
1683 object [ "query" .= toJSON query
1684 , "_cache" .= True ]]
1686 toJSON (RangeFilter (FieldName fieldName) rangeValue rangeExecution cache) =
1688 object [ fieldName .= object (rangeValueToPair rangeValue)
1689 , "execution" .= rangeExecution
1690 , "_cache" .= cache]]
1692 toJSON (RegexpFilter (FieldName fieldName)
1693 (Regexp regexText) flags (CacheName cacheName) cache (CacheKey cacheKey)) =
1695 object [fieldName .=
1696 object ["value" .= regexText
1698 , "_name" .= cacheName
1700 , "_cache_key" .= cacheKey]]
1702instance FromJSON Filter where
1703 parseJSON = withObject "Filter" parse
1704 where parse o = andFilter `taggedWith` "and"
1705 <|> orFilter `taggedWith` "or"
1706 <|> notFilter `taggedWith` "not"
1707 <|> identityFilter `taggedWith` "match_all"
1708 <|> boolFilter `taggedWith` "bool"
1709 <|> existsFilter `taggedWith` "exists"
1710 <|> geoBoundingBoxFilter `taggedWith` "geo_bounding_box"
1711 <|> geoDistanceFilter `taggedWith` "geo_distance"
1712 <|> geoDistanceRangeFilter `taggedWith` "geo_distance_range"
1713 <|> geoPolygonFilter `taggedWith` "geo_polygon"
1714 <|> idsFilter `taggedWith` "ids"
1715 <|> limitFilter `taggedWith` "limit"
1716 <|> missingFilter `taggedWith` "missing"
1717 <|> prefixFilter `taggedWith` "prefix"
1718 <|> queryFilter `taggedWith` "query"
1719 <|> fqueryFilter `taggedWith` "fquery"
1720 <|> rangeFilter `taggedWith` "range"
1721 <|> regexpFilter `taggedWith` "regexp"
1722 <|> termFilter `taggedWith` "term"
1723 where taggedWith parser k = parser =<< o .: k
1724 andFilter o = AndFilter <$> o .: "filters"
1725 <*> o .:? "_cache" .!= defaultCache
1726 orFilter o = OrFilter <$> o .: "filters"
1727 <*> o .:? "_cache" .!= defaultCache
1728 notFilter o = NotFilter <$> o .: "filter"
1729 <*> o .: "_cache" .!= defaultCache
1730 identityFilter :: Object -> Parser Filter
1732 | HM.null m = pure IdentityFilter
1733 | otherwise = fail ("Identityfilter expected empty object but got " <> show m)
1734 boolFilter = pure . BoolFilter
1735 existsFilter o = ExistsFilter <$> o .: "field"
1736 geoBoundingBoxFilter = pure . GeoBoundingBoxFilter
1737 geoDistanceFilter o = do
1738 case HM.toList (deleteSeveral ["distance", "distance_type", "optimize_bbox", "_cache"] o) of
1740 gp <- GeoPoint (FieldName fn) <$> parseJSON v
1741 GeoDistanceFilter gp <$> o .: "distance"
1742 <*> o .: "distance_type"
1743 <*> o .: "optimize_bbox"
1744 <*> o .:? "_cache" .!= defaultCache
1745 _ -> fail "Could not find GeoDistanceFilter field name"
1746 geoDistanceRangeFilter o = do
1747 case HM.toList (deleteSeveral ["from", "to"] o) of
1749 gp <- GeoPoint (FieldName fn) <$> parseJSON v
1750 rng <- DistanceRange <$> o .: "from" <*> o .: "to"
1751 return (GeoDistanceRangeFilter gp rng)
1752 _ -> fail "Could not find GeoDistanceRangeFilter field name"
1753 geoPolygonFilter = fieldTagged $ \fn o -> GeoPolygonFilter fn <$> o .: "points"
1754 idsFilter o = IdsFilter <$> o .: "type"
1756 limitFilter o = LimitFilter <$> o .: "value"
1757 missingFilter o = MissingFilter <$> o .: "field"
1758 <*> o .: "existence"
1759 <*> o .: "null_value"
1760 prefixFilter o = case HM.toList (HM.delete "_cache" o) of
1761 [(fn, String v)] -> PrefixFilter (FieldName fn) v <$> o .:? "_cache" .!= defaultCache
1762 _ -> fail "Could not parse PrefixFilter"
1764 queryFilter q = pure (QueryFilter q False)
1765 fqueryFilter o = QueryFilter <$> o .: "query" <*> pure True
1766 rangeFilter o = case HM.toList (deleteSeveral ["execution", "_cache"] o) of
1767 [(fn, v)] -> RangeFilter (FieldName fn)
1769 <*> o .: "execution"
1770 <*> o .:? "_cache" .!= defaultCache
1771 _ -> fail "Could not find field name for RangeFilter"
1772 regexpFilter o = case HM.toList (deleteSeveral ["_name", "_cache", "_cache_key"] o) of
1773 [(fn, Object o')] -> RegexpFilter (FieldName fn)
1777 <*> o .:? "_cache" .!= defaultCache
1778 <*> o .: "_cache_key"
1779 _ -> fail "Could not find field name for RegexpFilter"
1780 termFilter o = case HM.toList (HM.delete "_cache" o) of
1781 [(termField, String termVal)] -> TermFilter (Term termField termVal)
1782 <$> o .:? "_cache" .!= defaultCache
1783 _ -> fail "Could not find term field for TermFilter"
1785fieldTagged :: Monad m => (FieldName -> Object -> m a) -> Object -> m a
1786fieldTagged f o = case HM.toList o of
1787 [(k, Object o')] -> f (FieldName k) o'
1788 _ -> fail "Expected object with 1 field-named key"
1790instance ToJSON GeoPoint where
1791 toJSON (GeoPoint (FieldName geoPointField) geoPointLatLon) =
1792 object [ geoPointField .= geoPointLatLon ]
1795instance ToJSON Query where
1796 toJSON (TermQuery (Term termQueryField termQueryValue) boost) =
1798 object [termQueryField .= object merged]]
1800 base = [ "value" .= termQueryValue ]
1801 boosted = maybe [] (return . ("boost" .=)) boost
1802 merged = mappend base boosted
1804 toJSON (TermsQuery fieldName terms) =
1805 object [ "terms" .= object conjoined ]
1806 where conjoined = [fieldName .= terms]
1807 toJSON (IdsQuery idsQueryMappingName docIds) =
1808 object [ "ids" .= object conjoined ]
1809 where conjoined = [ "type" .= idsQueryMappingName
1810 , "values" .= fmap toJSON docIds ]
1812 toJSON (QueryQueryStringQuery qQueryStringQuery) =
1813 object [ "query_string" .= qQueryStringQuery ]
1815 toJSON (QueryMatchQuery matchQuery) =
1816 object [ "match" .= matchQuery ]
1818 toJSON (QueryMultiMatchQuery multiMatchQuery) =
1819 toJSON multiMatchQuery
1821 toJSON (QueryBoolQuery boolQuery) =
1822 object [ "bool" .= boolQuery ]
1824 toJSON (QueryBoostingQuery boostingQuery) =
1825 object [ "boosting" .= boostingQuery ]
1827 toJSON (QueryCommonTermsQuery commonTermsQuery) =
1828 object [ "common" .= commonTermsQuery ]
1830 toJSON (ConstantScoreFilter csFilter boost) =
1831 object ["constant_score" .= object ["filter" .= csFilter
1832 , "boost" .= boost]]
1834 toJSON (ConstantScoreQuery query boost) =
1835 object ["constant_score" .= object ["query" .= query
1836 , "boost" .= boost]]
1838 toJSON (QueryDisMaxQuery disMaxQuery) =
1839 object [ "dis_max" .= disMaxQuery ]
1841 toJSON (QueryFilteredQuery qFilteredQuery) =
1842 object [ "filtered" .= qFilteredQuery ]
1844 toJSON (QueryFuzzyLikeThisQuery fuzzyQuery) =
1845 object [ "fuzzy_like_this" .= fuzzyQuery ]
1847 toJSON (QueryFuzzyLikeFieldQuery fuzzyFieldQuery) =
1848 object [ "fuzzy_like_this_field" .= fuzzyFieldQuery ]
1850 toJSON (QueryFuzzyQuery fuzzyQuery) =
1851 object [ "fuzzy" .= fuzzyQuery ]
1853 toJSON (QueryHasChildQuery childQuery) =
1854 object [ "has_child" .= childQuery ]
1856 toJSON (QueryHasParentQuery parentQuery) =
1857 object [ "has_parent" .= parentQuery ]
1859 toJSON (QueryIndicesQuery qIndicesQuery) =
1860 object [ "indices" .= qIndicesQuery ]
1862 toJSON (MatchAllQuery boost) =
1863 object [ "match_all" .= omitNulls [ "boost" .= boost ] ]
1865 toJSON (QueryMoreLikeThisQuery query) =
1866 object [ "more_like_this" .= query ]
1868 toJSON (QueryMoreLikeThisFieldQuery query) =
1869 object [ "more_like_this_field" .= query ]
1871 toJSON (QueryNestedQuery query) =
1872 object [ "nested" .= query ]
1874 toJSON (QueryPrefixQuery query) =
1875 object [ "prefix" .= query ]
1877 toJSON (QueryRangeQuery query) =
1878 object [ "range" .= query ]
1880 toJSON (QueryRegexpQuery query) =
1881 object [ "regexp" .= query ]
1883 toJSON (QuerySimpleQueryStringQuery query) =
1884 object [ "simple_query_string" .= query ]
1886instance FromJSON Query where
1887 parseJSON v = withObject "Query" parse v
1888 where parse o = termQuery `taggedWith` "term"
1889 <|> termsQuery `taggedWith` "terms"
1890 <|> idsQuery `taggedWith` "ids"
1891 <|> queryQueryStringQuery `taggedWith` "query_string"
1892 <|> queryMatchQuery `taggedWith` "match"
1893 <|> queryMultiMatchQuery --TODO: is this a precedence issue?
1894 <|> queryBoolQuery `taggedWith` "bool"
1895 <|> queryBoostingQuery `taggedWith` "boosting"
1896 <|> queryCommonTermsQuery `taggedWith` "common"
1897 <|> constantScoreFilter `taggedWith` "constant_score"
1898 <|> constantScoreQuery `taggedWith` "constant_score"
1899 <|> queryDisMaxQuery `taggedWith` "dis_max"
1900 <|> queryFilteredQuery `taggedWith` "filtered"
1901 <|> queryFuzzyLikeThisQuery `taggedWith` "fuzzy_like_this"
1902 <|> queryFuzzyLikeFieldQuery `taggedWith` "fuzzy_like_this_field"
1903 <|> queryFuzzyQuery `taggedWith` "fuzzy"
1904 <|> queryHasChildQuery `taggedWith` "has_child"
1905 <|> queryHasParentQuery `taggedWith` "has_parent"
1906 <|> queryIndicesQuery `taggedWith` "indices"
1907 <|> matchAllQuery `taggedWith` "match_all"
1908 <|> queryMoreLikeThisQuery `taggedWith` "more_like_this"
1909 <|> queryMoreLikeThisFieldQuery `taggedWith` "more_like_this_field"
1910 <|> queryNestedQuery `taggedWith` "nested"
1911 <|> queryPrefixQuery `taggedWith` "prefix"
1912 <|> queryRangeQuery `taggedWith` "range"
1913 <|> queryRegexpQuery `taggedWith` "regexp"
1914 <|> querySimpleQueryStringQuery `taggedWith` "simple_query_string"
1915 where taggedWith parser k = parser =<< o .: k
1916 termQuery = fieldTagged $ \(FieldName fn) o ->
1917 TermQuery <$> (Term fn <$> o .: "value") <*> o .:? "boost"
1918 termsQuery o = case HM.toList o of
1919 [(fn, vs)] -> do vals <- parseJSON vs
1921 x:xs -> return (TermsQuery fn (x :| xs))
1922 _ -> fail "Expected non empty list of values"
1923 _ -> fail "Expected object with 1 field-named key"
1924 idsQuery o = IdsQuery <$> o .: "type"
1926 queryQueryStringQuery = pure . QueryQueryStringQuery
1927 queryMatchQuery = pure . QueryMatchQuery
1928 queryMultiMatchQuery = QueryMultiMatchQuery <$> parseJSON v
1929 queryBoolQuery = pure . QueryBoolQuery
1930 queryBoostingQuery = pure . QueryBoostingQuery
1931 queryCommonTermsQuery = pure . QueryCommonTermsQuery
1932 constantScoreFilter o = case HM.lookup "filter" o of
1933 Just x -> ConstantScoreFilter <$> parseJSON x
1935 _ -> fail "Does not appear to be a ConstantScoreFilter"
1936 constantScoreQuery o = case HM.lookup "query" o of
1937 Just x -> ConstantScoreQuery <$> parseJSON x
1939 _ -> fail "Does not appear to be a ConstantScoreQuery"
1940 queryDisMaxQuery = pure . QueryDisMaxQuery
1941 queryFilteredQuery = pure . QueryFilteredQuery
1942 queryFuzzyLikeThisQuery = pure . QueryFuzzyLikeThisQuery
1943 queryFuzzyLikeFieldQuery = pure . QueryFuzzyLikeFieldQuery
1944 queryFuzzyQuery = pure . QueryFuzzyQuery
1945 queryHasChildQuery = pure . QueryHasChildQuery
1946 queryHasParentQuery = pure . QueryHasParentQuery
1947 queryIndicesQuery = pure . QueryIndicesQuery
1948 matchAllQuery o = MatchAllQuery <$> o .:? "boost"
1949 queryMoreLikeThisQuery = pure . QueryMoreLikeThisQuery
1950 queryMoreLikeThisFieldQuery = pure . QueryMoreLikeThisFieldQuery
1951 queryNestedQuery = pure . QueryNestedQuery
1952 queryPrefixQuery = pure . QueryPrefixQuery
1953 queryRangeQuery = pure . QueryRangeQuery
1954 queryRegexpQuery = pure . QueryRegexpQuery
1955 querySimpleQueryStringQuery = pure . QuerySimpleQueryStringQuery
1958omitNulls :: [(Text, Value)] -> Value
1959omitNulls = object . filter notNull where
1960 notNull (_, Null) = False
1961 notNull (_, Array a) = (not . V.null) a
1965instance ToJSON SimpleQueryStringQuery where
1966 toJSON SimpleQueryStringQuery {..} =
1967 omitNulls (base ++ maybeAdd)
1968 where base = [ "query" .= simpleQueryStringQuery ]
1969 maybeAdd = [ "fields" .= simpleQueryStringField
1970 , "default_operator" .= simpleQueryStringOperator
1971 , "analyzer" .= simpleQueryStringAnalyzer
1972 , "flags" .= simpleQueryStringFlags
1973 , "lowercase_expanded_terms" .= simpleQueryStringLowercaseExpanded
1974 , "locale" .= simpleQueryStringLocale ]
1976instance FromJSON SimpleQueryStringQuery where
1977 parseJSON = withObject "SimpleQueryStringQuery" parse
1978 where parse o = SimpleQueryStringQuery <$> o .: "query"
1980 <*> o .:? "default_operator"
1981 <*> o .:? "analyzer"
1982 <*> (parseFlags <$> o .:? "flags")
1983 <*> o .:? "lowercase_expanded_terms"
1985 parseFlags (Just (x:xs)) = Just (x :| xs)
1986 parseFlags _ = Nothing
1988instance ToJSON FieldOrFields where
1989 toJSON (FofField fieldName) =
1991 toJSON (FofFields fieldNames) =
1994instance FromJSON FieldOrFields where
1995 parseJSON v = FofField <$> parseJSON v
1996 <|> FofFields <$> (parseNEJSON =<< parseJSON v)
1998instance ToJSON SimpleQueryFlag where
1999 toJSON SimpleQueryAll = "ALL"
2000 toJSON SimpleQueryNone = "NONE"
2001 toJSON SimpleQueryAnd = "AND"
2002 toJSON SimpleQueryOr = "OR"
2003 toJSON SimpleQueryPrefix = "PREFIX"
2004 toJSON SimpleQueryPhrase = "PHRASE"
2005 toJSON SimpleQueryPrecedence = "PRECEDENCE"
2006 toJSON SimpleQueryEscape = "ESCAPE"
2007 toJSON SimpleQueryWhitespace = "WHITESPACE"
2008 toJSON SimpleQueryFuzzy = "FUZZY"
2009 toJSON SimpleQueryNear = "NEAR"
2010 toJSON SimpleQuerySlop = "SLOP"
2012instance FromJSON SimpleQueryFlag where
2013 parseJSON = withText "SimpleQueryFlag" parse
2014 where parse "ALL" = pure SimpleQueryAll
2015 parse "NONE" = pure SimpleQueryNone
2016 parse "AND" = pure SimpleQueryAnd
2017 parse "OR" = pure SimpleQueryOr
2018 parse "PREFIX" = pure SimpleQueryPrefix
2019 parse "PHRASE" = pure SimpleQueryPhrase
2020 parse "PRECEDENCE" = pure SimpleQueryPrecedence
2021 parse "ESCAPE" = pure SimpleQueryEscape
2022 parse "WHITESPACE" = pure SimpleQueryWhitespace
2023 parse "FUZZY" = pure SimpleQueryFuzzy
2024 parse "NEAR" = pure SimpleQueryNear
2025 parse "SLOP" = pure SimpleQuerySlop
2026 parse f = fail ("Unexpected SimpleQueryFlag: " <> show f)
2028instance ToJSON RegexpQuery where
2029 toJSON (RegexpQuery (FieldName rqQueryField)
2030 (Regexp regexpQueryQuery) rqQueryFlags
2032 object [ rqQueryField .= omitNulls base ]
2033 where base = [ "value" .= regexpQueryQuery
2034 , "flags" .= rqQueryFlags
2035 , "boost" .= rqQueryBoost ]
2037instance FromJSON RegexpQuery where
2038 parseJSON = withObject "RegexpQuery" parse
2039 where parse = fieldTagged $ \fn o ->
2045instance ToJSON QueryStringQuery where
2046 toJSON (QueryStringQuery qsQueryString
2047 qsDefaultField qsOperator
2048 qsAnalyzer qsAllowWildcard
2049 qsLowercaseExpanded qsEnablePositionIncrements
2050 qsFuzzyMaxExpansions qsFuzziness
2051 qsFuzzyPrefixLength qsPhraseSlop
2052 qsBoost qsAnalyzeWildcard
2053 qsGeneratePhraseQueries qsMinimumShouldMatch
2054 qsLenient qsLocale) =
2057 base = [ "query" .= qsQueryString
2058 , "default_field" .= qsDefaultField
2059 , "default_operator" .= qsOperator
2060 , "analyzer" .= qsAnalyzer
2061 , "allow_leading_wildcard" .= qsAllowWildcard
2062 , "lowercase_expanded_terms" .= qsLowercaseExpanded
2063 , "enable_position_increments" .= qsEnablePositionIncrements
2064 , "fuzzy_max_expansions" .= qsFuzzyMaxExpansions
2065 , "fuzziness" .= qsFuzziness
2066 , "fuzzy_prefix_length" .= qsFuzzyPrefixLength
2067 , "phrase_slop" .= qsPhraseSlop
2068 , "boost" .= qsBoost
2069 , "analyze_wildcard" .= qsAnalyzeWildcard
2070 , "auto_generate_phrase_queries" .= qsGeneratePhraseQueries
2071 , "minimum_should_match" .= qsMinimumShouldMatch
2072 , "lenient" .= qsLenient
2073 , "locale" .= qsLocale ]
2075instance FromJSON QueryStringQuery where
2076 parseJSON = withObject "QueryStringQuery" parse
2077 where parse o = QueryStringQuery
2079 <*> o .:? "default_field"
2080 <*> o .:? "default_operator"
2081 <*> o .:? "analyzer"
2082 <*> o .:? "allow_leading_wildcard"
2083 <*> o .:? "lowercase_expanded_terms"
2084 <*> o .:? "enable_position_increments"
2085 <*> o .:? "fuzzy_max_expansions"
2086 <*> o .:? "fuzziness"
2087 <*> o .:? "fuzzy_prefix_length"
2088 <*> o .:? "phrase_slop"
2090 <*> o .:? "analyze_wildcard"
2091 <*> o .:? "auto_generate_phrase_queries"
2092 <*> o .:? "minimum_should_match"
2096instance ToJSON RangeQuery where
2097 toJSON (RangeQuery (FieldName fieldName) range boost) =
2098 object [ fieldName .= object conjoined ]
2099 where conjoined = [ "boost" .= boost ] ++ (rangeValueToPair range)
2101instance FromJSON RangeQuery where
2102 parseJSON = withObject "RangeQuery" parse
2103 where parse = fieldTagged $ \fn o ->
2105 <$> parseJSON (Object o)
2108instance FromJSON RangeValue where
2109 parseJSON = withObject "RangeValue" parse
2110 where parse o = parseDate o
2112 parseDate o = do lt <- o .:? "lt"
2116 case (lt, lte, gt, gte) of
2117 (Just a, _, Just b, _) -> return (RangeDateGtLt (GreaterThanD b) (LessThanD a))
2118 (Just a, _, _, Just b)-> return (RangeDateGteLt (GreaterThanEqD b) (LessThanD a))
2119 (_, Just a, Just b, _)-> return (RangeDateGtLte (GreaterThanD b) (LessThanEqD a))
2120 (_, Just a, _, Just b)-> return (RangeDateGteLte (GreaterThanEqD b) (LessThanEqD a))
2121 (_, _, Just a, _)-> return (RangeDateGt (GreaterThanD a))
2122 (Just a, _, _, _)-> return (RangeDateLt (LessThanD a))
2123 (_, _, _, Just a)-> return (RangeDateGte (GreaterThanEqD a))
2124 (_, Just a, _, _)-> return (RangeDateLte (LessThanEqD a))
2125 (Nothing, Nothing, Nothing, Nothing) -> mzero
2126 parseDouble o = do lt <- o .:? "lt"
2130 case (lt, lte, gt, gte) of
2131 (Just a, _, Just b, _) -> return (RangeDoubleGtLt (GreaterThan b) (LessThan a))
2132 (Just a, _, _, Just b)-> return (RangeDoubleGteLt (GreaterThanEq b) (LessThan a))
2133 (_, Just a, Just b, _)-> return (RangeDoubleGtLte (GreaterThan b) (LessThanEq a))
2134 (_, Just a, _, Just b)-> return (RangeDoubleGteLte (GreaterThanEq b) (LessThanEq a))
2135 (_, _, Just a, _)-> return (RangeDoubleGt (GreaterThan a))
2136 (Just a, _, _, _)-> return (RangeDoubleLt (LessThan a))
2137 (_, _, _, Just a)-> return (RangeDoubleGte (GreaterThanEq a))
2138 (_, Just a, _, _)-> return (RangeDoubleLte (LessThanEq a))
2139 (Nothing, Nothing, Nothing, Nothing) -> mzero
2141instance ToJSON PrefixQuery where
2142 toJSON (PrefixQuery (FieldName fieldName) queryValue boost) =
2143 object [ fieldName .= omitNulls base ]
2144 where base = [ "value" .= queryValue
2145 , "boost" .= boost ]
2147instance FromJSON PrefixQuery where
2148 parseJSON = withObject "PrefixQuery" parse
2149 where parse = fieldTagged $ \fn o ->
2154instance ToJSON NestedQuery where
2155 toJSON (NestedQuery nqPath nqScoreType nqQuery) =
2156 object [ "path" .= nqPath
2157 , "score_mode" .= nqScoreType
2158 , "query" .= nqQuery ]
2160instance FromJSON NestedQuery where
2161 parseJSON = withObject "NestedQuery" parse
2162 where parse o = NestedQuery
2164 <*> o .: "score_mode"
2167instance ToJSON MoreLikeThisFieldQuery where
2168 toJSON (MoreLikeThisFieldQuery text (FieldName fieldName)
2169 percent mtf mqt stopwords mindf maxdf
2170 minwl maxwl boostTerms boost analyzer) =
2171 object [ fieldName .= omitNulls base ]
2172 where base = [ "like_text" .= text
2173 , "percent_terms_to_match" .= percent
2174 , "min_term_freq" .= mtf
2175 , "max_query_terms" .= mqt
2176 , "stop_words" .= stopwords
2177 , "min_doc_freq" .= mindf
2178 , "max_doc_freq" .= maxdf
2179 , "min_word_length" .= minwl
2180 , "max_word_length" .= maxwl
2181 , "boost_terms" .= boostTerms
2183 , "analyzer" .= analyzer ]
2185instance FromJSON MoreLikeThisFieldQuery where
2186 parseJSON = withObject "MoreLikeThisFieldQuery" parse
2187 where parse = fieldTagged $ \fn o ->
2188 MoreLikeThisFieldQuery
2189 <$> o .: "like_text"
2191 <*> o .:? "percent_terms_to_match"
2192 <*> o .:? "min_term_freq"
2193 <*> o .:? "max_query_terms"
2194 <*> (optionalNE =<< o .:? "stop_words")
2195 <*> o .:? "min_doc_freq"
2196 <*> o .:? "max_doc_freq"
2197 <*> o .:? "min_word_length"
2198 <*> o .:? "max_word_length"
2199 <*> o .:? "boost_terms"
2201 <*> o .:? "analyzer"
2202 optionalNE = maybe (pure Nothing) (fmap Just . parseNEJSON)
2204instance ToJSON MoreLikeThisQuery where
2205 toJSON (MoreLikeThisQuery text fields percent
2206 mtf mqt stopwords mindf maxdf
2207 minwl maxwl boostTerms boost analyzer) =
2209 where base = [ "like_text" .= text
2210 , "fields" .= fields
2211 , "percent_terms_to_match" .= percent
2212 , "min_term_freq" .= mtf
2213 , "max_query_terms" .= mqt
2214 , "stop_words" .= stopwords
2215 , "min_doc_freq" .= mindf
2216 , "max_doc_freq" .= maxdf
2217 , "min_word_length" .= minwl
2218 , "max_word_length" .= maxwl
2219 , "boost_terms" .= boostTerms
2221 , "analyzer" .= analyzer ]
2223instance FromJSON MoreLikeThisQuery where
2224 parseJSON = withObject "MoreLikeThisQuery" parse
2225 where parse o = MoreLikeThisQuery
2226 <$> o .: "like_text"
2227 <*> (optionalNE =<< o .:? "fields")
2228 <*> o .:? "percent_terms_to_match"
2229 <*> o .:? "min_term_freq"
2230 <*> o .:? "max_query_terms"
2231 <*> (optionalNE =<< o .:? "stop_words")
2232 <*> o .:? "min_doc_freq"
2233 <*> o .:? "max_doc_freq"
2234 <*> o .:? "min_word_length"
2235 <*> o .:? "max_word_length"
2236 <*> o .:? "boost_terms"
2238 <*> o .:? "analyzer"
2239 optionalNE = maybe (pure Nothing) (fmap Just . parseNEJSON)
2241instance ToJSON IndicesQuery where
2242 toJSON (IndicesQuery indices query noMatch) =
2243 omitNulls [ "indices" .= indices
2244 , "no_match_query" .= noMatch
2245 , "query" .= query ]
2247instance FromJSON IndicesQuery where
2248 parseJSON = withObject "IndicesQuery" parse
2249 where parse o = IndicesQuery
2250 <$> o .:? "indices" .!= []
2252 <*> o .:? "no_match_query"
2254instance ToJSON HasParentQuery where
2255 toJSON (HasParentQuery queryType query scoreType) =
2256 omitNulls [ "parent_type" .= queryType
2257 , "score_type" .= scoreType
2258 , "query" .= query ]
2260instance FromJSON HasParentQuery where
2261 parseJSON = withObject "HasParentQuery" parse
2262 where parse o = HasParentQuery
2263 <$> o .: "parent_type"
2265 <*> o .:? "score_type"
2267instance ToJSON HasChildQuery where
2268 toJSON (HasChildQuery queryType query scoreType) =
2269 omitNulls [ "query" .= query
2270 , "score_type" .= scoreType
2271 , "type" .= queryType ]
2273instance FromJSON HasChildQuery where
2274 parseJSON = withObject "HasChildQuery" parse
2275 where parse o = HasChildQuery
2278 <*> o .:? "score_type"
2280instance ToJSON FuzzyQuery where
2281 toJSON (FuzzyQuery (FieldName fieldName) queryText
2282 prefixLength maxEx fuzziness boost) =
2283 object [ fieldName .= omitNulls base ]
2284 where base = [ "value" .= queryText
2285 , "fuzziness" .= fuzziness
2286 , "prefix_length" .= prefixLength
2288 , "max_expansions" .= maxEx ]
2290instance FromJSON FuzzyQuery where
2291 parseJSON = withObject "FuzzyQuery" parse
2292 where parse = fieldTagged $ \fn o ->
2295 <*> o .: "prefix_length"
2296 <*> o .: "max_expansions"
2297 <*> o .: "fuzziness"
2300instance ToJSON FuzzyLikeFieldQuery where
2301 toJSON (FuzzyLikeFieldQuery (FieldName fieldName)
2302 fieldText maxTerms ignoreFreq fuzziness prefixLength
2304 object [ fieldName .=
2305 omitNulls [ "like_text" .= fieldText
2306 , "max_query_terms" .= maxTerms
2307 , "ignore_tf" .= ignoreFreq
2308 , "fuzziness" .= fuzziness
2309 , "prefix_length" .= prefixLength
2310 , "analyzer" .= analyzer
2311 , "boost" .= boost ]]
2313instance FromJSON FuzzyLikeFieldQuery where
2314 parseJSON = withObject "FuzzyLikeFieldQuery" parse
2315 where parse = fieldTagged $ \fn o ->
2316 FuzzyLikeFieldQuery fn
2317 <$> o .: "like_text"
2318 <*> o .: "max_query_terms"
2319 <*> o .: "ignore_tf"
2320 <*> o .: "fuzziness"
2321 <*> o .: "prefix_length"
2323 <*> o .:? "analyzer"
2325instance ToJSON FuzzyLikeThisQuery where
2326 toJSON (FuzzyLikeThisQuery fields text maxTerms
2327 ignoreFreq fuzziness prefixLength boost analyzer) =
2329 where base = [ "fields" .= fields
2330 , "like_text" .= text
2331 , "max_query_terms" .= maxTerms
2332 , "ignore_tf" .= ignoreFreq
2333 , "fuzziness" .= fuzziness
2334 , "prefix_length" .= prefixLength
2335 , "analyzer" .= analyzer
2336 , "boost" .= boost ]
2338instance FromJSON FuzzyLikeThisQuery where
2339 parseJSON = withObject "FuzzyLikeThisQuery" parse
2340 where parse o = FuzzyLikeThisQuery
2341 <$> o .:? "fields" .!= []
2342 <*> o .: "like_text"
2343 <*> o .: "max_query_terms"
2344 <*> o .: "ignore_tf"
2345 <*> o .: "fuzziness"
2346 <*> o .: "prefix_length"
2348 <*> o .:? "analyzer"
2350instance ToJSON FilteredQuery where
2351 toJSON (FilteredQuery query fFilter) =
2352 object [ "query" .= query
2353 , "filter" .= fFilter ]
2355instance FromJSON FilteredQuery where
2356 parseJSON = withObject "FilteredQuery" parse
2357 where parse o = FilteredQuery
2361instance ToJSON DisMaxQuery where
2362 toJSON (DisMaxQuery queries tiebreaker boost) =
2364 where base = [ "queries" .= queries
2366 , "tie_breaker" .= tiebreaker ]
2368instance FromJSON DisMaxQuery where
2369 parseJSON = withObject "DisMaxQuery" parse
2370 where parse o = DisMaxQuery
2371 <$> o .:? "queries" .!= []
2372 <*> o .: "tie_breaker"
2375instance ToJSON CommonTermsQuery where
2376 toJSON (CommonTermsQuery (FieldName fieldName)
2377 (QueryString query) cf lfo hfo msm
2378 boost analyzer disableCoord) =
2379 object [fieldName .= omitNulls base ]
2380 where base = [ "query" .= query
2381 , "cutoff_frequency" .= cf
2382 , "low_freq_operator" .= lfo
2383 , "minimum_should_match" .= msm
2385 , "analyzer" .= analyzer
2386 , "disable_coord" .= disableCoord
2387 , "high_freq_operator" .= hfo ]
2389instance FromJSON CommonTermsQuery where
2390 parseJSON = withObject "CommonTermsQuery" parse
2391 where parse = fieldTagged $ \fn o ->
2394 <*> o .: "cutoff_frequency"
2395 <*> o .: "low_freq_operator"
2396 <*> o .: "high_freq_operator"
2397 <*> o .:? "minimum_should_match"
2399 <*> o .:? "analyzer"
2400 <*> o .:? "disable_coord"
2402instance ToJSON CommonMinimumMatch where
2403 toJSON (CommonMinimumMatch mm) = toJSON mm
2404 toJSON (CommonMinimumMatchHighLow (MinimumMatchHighLow lowF highF)) =
2405 object [ "low_freq" .= lowF
2406 , "high_freq" .= highF ]
2408instance FromJSON CommonMinimumMatch where
2409 parseJSON v = parseMinimum v
2410 <|> parseMinimumHighLow v
2411 where parseMinimum = fmap CommonMinimumMatch . parseJSON
2412 parseMinimumHighLow = fmap CommonMinimumMatchHighLow . withObject "CommonMinimumMatchHighLow" (\o ->
2415 <*> o .: "high_freq")
2418instance ToJSON BoostingQuery where
2419 toJSON (BoostingQuery bqPositiveQuery bqNegativeQuery bqNegativeBoost) =
2420 object [ "positive" .= bqPositiveQuery
2421 , "negative" .= bqNegativeQuery
2422 , "negative_boost" .= bqNegativeBoost ]
2424instance FromJSON BoostingQuery where
2425 parseJSON = withObject "BoostingQuery" parse
2426 where parse o = BoostingQuery
2429 <*> o .: "negative_boost"
2431instance ToJSON BoolQuery where
2432 toJSON (BoolQuery mustM notM shouldM bqMin boost disableCoord) =
2434 where base = [ "must" .= mustM
2435 , "must_not" .= notM
2436 , "should" .= shouldM
2437 , "minimum_should_match" .= bqMin
2439 , "disable_coord" .= disableCoord ]
2441instance FromJSON BoolQuery where
2442 parseJSON = withObject "BoolQuery" parse
2443 where parse o = BoolQuery
2444 <$> o .:? "must" .!= []
2445 <*> o .:? "must_not" .!= []
2446 <*> o .:? "should" .!= []
2447 <*> o .:? "minimum_should_match"
2449 <*> o .:? "disable_coord"
2451instance ToJSON MatchQuery where
2452 toJSON (MatchQuery (FieldName fieldName)
2453 (QueryString mqQueryString) booleanOperator
2454 zeroTermsQuery cutoffFrequency matchQueryType
2455 analyzer maxExpansions lenient boost) =
2456 object [ fieldName .= omitNulls base ]
2457 where base = [ "query" .= mqQueryString
2458 , "operator" .= booleanOperator
2459 , "zero_terms_query" .= zeroTermsQuery
2460 , "cutoff_frequency" .= cutoffFrequency
2461 , "type" .= matchQueryType
2462 , "analyzer" .= analyzer
2463 , "max_expansions" .= maxExpansions
2464 , "lenient" .= lenient
2465 , "boost" .= boost ]
2467instance FromJSON MatchQuery where
2468 parseJSON = withObject "MatchQuery" parse
2469 where parse = fieldTagged $ \fn o ->
2473 <*> o .: "zero_terms_query"
2474 <*> o .:? "cutoff_frequency"
2476 <*> o .:? "analyzer"
2477 <*> o .:? "max_expansions"
2481instance ToJSON MultiMatchQuery where
2482 toJSON (MultiMatchQuery fields (QueryString query) boolOp
2483 ztQ tb mmqt cf analyzer maxEx lenient) =
2484 object ["multi_match" .= omitNulls base]
2485 where base = [ "fields" .= fmap toJSON fields
2487 , "operator" .= boolOp
2488 , "zero_terms_query" .= ztQ
2489 , "tiebreaker" .= tb
2491 , "cutoff_frequency" .= cf
2492 , "analyzer" .= analyzer
2493 , "max_expansions" .= maxEx
2494 , "lenient" .= lenient ]
2496instance FromJSON MultiMatchQuery where
2497 parseJSON = withObject "MultiMatchQuery" parse
2498 where parse raw = do o <- raw .: "multi_match"
2500 <$> o .:? "fields" .!= []
2503 <*> o .: "zero_terms_query"
2504 <*> o .:? "tiebreaker"
2506 <*> o .:? "cutoff_frequency"
2507 <*> o .:? "analyzer"
2508 <*> o .:? "max_expansions"
2511instance ToJSON MultiMatchQueryType where
2512 toJSON MultiMatchBestFields = "best_fields"
2513 toJSON MultiMatchMostFields = "most_fields"
2514 toJSON MultiMatchCrossFields = "cross_fields"
2515 toJSON MultiMatchPhrase = "phrase"
2516 toJSON MultiMatchPhrasePrefix = "phrase_prefix"
2518instance FromJSON MultiMatchQueryType where
2519 parseJSON = withText "MultiMatchPhrasePrefix" parse
2520 where parse "best_fields" = pure MultiMatchBestFields
2521 parse "most_fields" = pure MultiMatchMostFields
2522 parse "cross_fields" = pure MultiMatchCrossFields
2523 parse "phrase" = pure MultiMatchPhrase
2524 parse "phrase_prefix" = pure MultiMatchPhrasePrefix
2525 parse t = fail ("Unexpected MultiMatchPhrasePrefix: " <> show t)
2527instance ToJSON BooleanOperator where
2528 toJSON And = String "and"
2529 toJSON Or = String "or"
2531instance FromJSON BooleanOperator where
2532 parseJSON = withText "BooleanOperator" parse
2533 where parse "and" = pure And
2534 parse "or" = pure Or
2535 parse o = fail ("Unexpected BooleanOperator: " <> show o)
2537instance ToJSON ZeroTermsQuery where
2538 toJSON ZeroTermsNone = String "none"
2539 toJSON ZeroTermsAll = String "all"
2541instance FromJSON ZeroTermsQuery where
2542 parseJSON = withText "ZeroTermsQuery" parse
2543 where parse "none" = pure ZeroTermsNone
2544 parse "all" = pure ZeroTermsAll
2545 parse q = fail ("Unexpected ZeroTermsQuery: " <> show q)
2547instance ToJSON MatchQueryType where
2548 toJSON MatchPhrase = "phrase"
2549 toJSON MatchPhrasePrefix = "phrase_prefix"
2551instance FromJSON MatchQueryType where
2552 parseJSON = withText "MatchQueryType" parse
2553 where parse "phrase" = pure MatchPhrase
2554 parse "phrase_prefix" = pure MatchPhrasePrefix
2555 parse t = fail ("Unexpected MatchQueryType: " <> show t)
2557instance FromJSON Status where
2558 parseJSON (Object v) = Status <$>
2567instance ToJSON IndexSettings where
2568 toJSON (IndexSettings s r) = object ["settings" .=
2570 object ["number_of_shards" .= s, "number_of_replicas" .= r]
2574instance ToJSON IndexTemplate where
2575 toJSON (IndexTemplate p s m) = merge
2576 (object [ "template" .= p
2577 , "mappings" .= foldl' merge (object []) m
2581 merge (Object o1) (Object o2) = toJSON $ HM.union o1 o2
2583 merge _ _ = undefined
2585instance (FromJSON a) => FromJSON (EsResult a) where
2586 parseJSON jsonVal@(Object v) = do
2587 found <- v .:? "found" .!= False
2589 then parseJSON jsonVal
2591 EsResult <$> v .: "_index" <*>
2597instance (FromJSON a) => FromJSON (EsResultFound a) where
2598 parseJSON (Object v) = EsResultFound <$>
2603instance FromJSON EsError where
2604 parseJSON (Object v) = EsError <$>
2609instance FromJSON IndexAliasesSummary where
2610 parseJSON = withObject "IndexAliasesSummary" parse
2611 where parse o = IndexAliasesSummary . mconcat <$> mapM (uncurry go) (HM.toList o)
2612 go ixn = withObject "index aliases" $ \ia -> do
2613 aliases <- ia .: "aliases"
2614 forM (HM.toList aliases) $ \(aName, v) -> do
2615 let indexAlias = IndexAlias (IndexName ixn) (IndexAliasName (IndexName aName))
2616 IndexAliasSummary indexAlias <$> parseJSON v
2619instance ToJSON IndexAliasAction where
2620 toJSON (AddAlias ia opts) = object ["add" .= (iaObj <> optsObj)]
2621 where Object iaObj = toJSON ia
2622 Object optsObj = toJSON opts
2623 toJSON (RemoveAlias ia) = object ["remove" .= iaObj]
2624 where Object iaObj = toJSON ia
2626instance ToJSON IndexAlias where
2627 toJSON IndexAlias {..} = object ["index" .= srcIndex
2628 , "alias" .= indexAlias
2631instance ToJSON IndexAliasCreate where
2632 toJSON IndexAliasCreate {..} = Object (filterObj <> routingObj)
2633 where filterObj = maybe mempty (HM.singleton "filter" . toJSON) aliasCreateFilter
2634 Object routingObj = maybe (Object mempty) toJSON aliasCreateRouting
2636instance ToJSON AliasRouting where
2637 toJSON (AllAliasRouting v) = object ["routing" .= v]
2638 toJSON (GranularAliasRouting srch idx) = object (catMaybes prs)
2639 where prs = [("search_routing" .=) <$> srch
2640 ,("index_routing" .=) <$> idx]
2642instance FromJSON AliasRouting where
2643 parseJSON = withObject "AliasRouting" parse
2644 where parse o = parseAll o <|> parseGranular o
2645 parseAll o = AllAliasRouting <$> o .: "routing"
2646 parseGranular o = do
2647 sr <- o .:? "search_routing"
2648 ir <- o .:? "index_routing"
2649 if isNothing sr && isNothing ir
2650 then fail "Both search_routing and index_routing can't be blank"
2651 else return (GranularAliasRouting sr ir)
2653instance FromJSON IndexAliasCreate where
2654 parseJSON v = withObject "IndexAliasCreate" parse v
2655 where parse o = IndexAliasCreate <$> optional (parseJSON v)
2658instance ToJSON SearchAliasRouting where
2659 toJSON (SearchAliasRouting rvs) = toJSON (T.intercalate "," (routingValue <$> toList rvs))
2661instance FromJSON SearchAliasRouting where
2662 parseJSON = withText "SearchAliasRouting" parse
2663 where parse t = SearchAliasRouting <$> parseNEJSON (String <$> T.splitOn "," t)
2665instance ToJSON Search where
2666 toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
2667 omitNulls [ "query" .= query
2668 , "filter" .= sFilter
2670 , "aggregations" .= searchAggs
2671 , "highlight" .= highlight
2674 , "track_scores" .= sTrackSortScores
2675 , "fields" .= sFields
2676 , "_source" .= sSource]
2679instance ToJSON Source where
2680 toJSON NoSource = toJSON False
2681 toJSON (SourcePatterns patterns) = toJSON patterns
2682 toJSON (SourceIncludeExclude incl excl) = object [ "include" .= incl, "exclude" .= excl ]
2684instance ToJSON PatternOrPatterns where
2685 toJSON (PopPattern pattern) = toJSON pattern
2686 toJSON (PopPatterns patterns) = toJSON patterns
2688instance ToJSON Include where
2689 toJSON (Include patterns) = toJSON patterns
2691instance ToJSON Exclude where
2692 toJSON (Exclude patterns) = toJSON patterns
2694instance ToJSON Pattern where
2695 toJSON (Pattern pattern) = toJSON pattern
2698instance ToJSON FieldHighlight where
2699 toJSON (FieldHighlight (FieldName fName) (Just fSettings)) =
2700 object [ fName .= fSettings ]
2701 toJSON (FieldHighlight (FieldName fName) Nothing) =
2702 object [ fName .= emptyObject ]
2704instance ToJSON Highlights where
2705 toJSON (Highlights global fields) =
2706 omitNulls (("fields" .= fields)
2707 : highlightSettingsPairs global)
2709instance ToJSON HighlightSettings where
2710 toJSON hs = omitNulls (highlightSettingsPairs (Just hs))
2712highlightSettingsPairs :: Maybe HighlightSettings -> [Pair]
2713highlightSettingsPairs Nothing = []
2714highlightSettingsPairs (Just (Plain plh)) = plainHighPairs (Just plh)
2715highlightSettingsPairs (Just (Postings ph)) = postHighPairs (Just ph)
2716highlightSettingsPairs (Just (FastVector fvh)) = fastVectorHighPairs (Just fvh)
2719plainHighPairs :: Maybe PlainHighlight -> [Pair]
2720plainHighPairs Nothing = []
2721plainHighPairs (Just (PlainHighlight plCom plNonPost)) =
2722 [ "type" .= String "plain"]
2723 ++ commonHighlightPairs plCom
2724 ++ nonPostingsToPairs plNonPost
2726postHighPairs :: Maybe PostingsHighlight -> [Pair]
2727postHighPairs Nothing = []
2728postHighPairs (Just (PostingsHighlight pCom)) =
2729 ("type" .= String "postings")
2730 : commonHighlightPairs pCom
2732fastVectorHighPairs :: Maybe FastVectorHighlight -> [Pair]
2733fastVectorHighPairs Nothing = []
2734fastVectorHighPairs (Just
2735 (FastVectorHighlight fvCom fvNonPostSettings fvBoundChars
2736 fvBoundMaxScan fvFragOff fvMatchedFields
2738 [ "type" .= String "fvh"
2739 , "boundary_chars" .= fvBoundChars
2740 , "boundary_max_scan" .= fvBoundMaxScan
2741 , "fragment_offset" .= fvFragOff
2742 , "matched_fields" .= fvMatchedFields
2743 , "phraseLimit" .= fvPhraseLim]
2744 ++ commonHighlightPairs fvCom
2745 ++ nonPostingsToPairs fvNonPostSettings
2747deleteSeveral :: (Eq k, Hashable k) => [k] -> HM.HashMap k v -> HM.HashMap k v
2748deleteSeveral ks hm = foldr HM.delete hm ks
2750commonHighlightPairs :: Maybe CommonHighlight -> [Pair]
2751commonHighlightPairs Nothing = []
2752commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder
2753 chNoMatchSize chHighlightQuery
2754 chRequireFieldMatch)) =
2755 [ "order" .= chScore
2756 , "force_source" .= chForceSource
2757 , "encoder" .= chEncoder
2758 , "no_match_size" .= chNoMatchSize
2759 , "highlight_query" .= chHighlightQuery
2760 , "require_fieldMatch" .= chRequireFieldMatch]
2761 ++ highlightTagToPairs chTag
2764nonPostingsToPairs :: Maybe NonPostings -> [Pair]
2765nonPostingsToPairs Nothing = []
2766nonPostingsToPairs (Just (NonPostings npFragSize npNumOfFrags)) =
2767 [ "fragment_size" .= npFragSize
2768 , "number_of_fragments" .= npNumOfFrags]
2770parseNEJSON :: (FromJSON a) => [Value] -> Parser (NonEmpty a)
2771parseNEJSON [] = fail "Expected non-empty list"
2772parseNEJSON (x:xs) = DT.mapM parseJSON (x :| xs)
2775instance ToJSON HighlightEncoder where
2776 toJSON DefaultEncoder = String "default"
2777 toJSON HTMLEncoder = String "html"
2779highlightTagToPairs :: Maybe HighlightTag -> [Pair]
2780highlightTagToPairs (Just (TagSchema _)) = [ "scheme" .= String "default"]
2781highlightTagToPairs (Just (CustomTags (pre, post))) = [ "pre_tags" .= pre
2782 , "post_tags" .= post]
2783highlightTagToPairs Nothing = []
2785instance ToJSON SortSpec where
2786 toJSON (DefaultSortSpec
2787 (DefaultSort (FieldName dsSortFieldName) dsSortOrder dsIgnoreUnmapped
2788 dsSortMode dsMissingSort dsNestedFilter)) =
2789 object [dsSortFieldName .= omitNulls base] where
2790 base = [ "order" .= dsSortOrder
2791 , "ignore_unmapped" .= dsIgnoreUnmapped
2792 , "mode" .= dsSortMode
2793 , "missing" .= dsMissingSort
2794 , "nested_filter" .= dsNestedFilter ]
2796 toJSON (GeoDistanceSortSpec gdsSortOrder (GeoPoint (FieldName field) gdsLatLon) units) =
2797 object [ "unit" .= units
2798 , field .= gdsLatLon
2799 , "order" .= gdsSortOrder ]
2802instance ToJSON SortOrder where
2803 toJSON Ascending = String "asc"
2804 toJSON Descending = String "desc"
2807instance ToJSON SortMode where
2808 toJSON SortMin = String "min"
2809 toJSON SortMax = String "max"
2810 toJSON SortSum = String "sum"
2811 toJSON SortAvg = String "avg"
2814instance ToJSON Missing where
2815 toJSON LastMissing = String "_last"
2816 toJSON FirstMissing = String "_first"
2817 toJSON (CustomMissing txt) = String txt
2820instance ToJSON ScoreType where
2821 toJSON ScoreTypeMax = "max"
2822 toJSON ScoreTypeAvg = "avg"
2823 toJSON ScoreTypeSum = "sum"
2824 toJSON ScoreTypeNone = "none"
2826instance FromJSON ScoreType where
2827 parseJSON = withText "ScoreType" parse
2828 where parse "max" = pure ScoreTypeMax
2829 parse "avg" = pure ScoreTypeAvg
2830 parse "sum" = pure ScoreTypeSum
2831 parse "none" = pure ScoreTypeNone
2832 parse t = fail ("Unexpected ScoreType: " <> show t)
2834instance ToJSON Distance where
2835 toJSON (Distance dCoefficient dUnit) =
2836 String boltedTogether where
2837 coefText = showText dCoefficient
2838 (String unitText) = toJSON dUnit
2839 boltedTogether = mappend coefText unitText
2841instance FromJSON Distance where
2842 parseJSON = withText "Distance" parse
2843 where parse t = Distance <$> parseCoeff nT
2844 <*> parseJSON (String unitT)
2845 where (nT, unitT) = T.span validForNumber t
2846 -- may be a better way to do this
2847 validForNumber '-' = True
2848 validForNumber '.' = True
2849 validForNumber 'e' = True
2850 validForNumber c = isNumber c
2851 parseCoeff "" = fail "Empty string cannot be parsed as number"
2852 parseCoeff s = return (read (T.unpack s))
2854instance ToJSON DistanceUnit where
2855 toJSON Miles = String "mi"
2856 toJSON Yards = String "yd"
2857 toJSON Feet = String "ft"
2858 toJSON Inches = String "in"
2859 toJSON Kilometers = String "km"
2860 toJSON Meters = String "m"
2861 toJSON Centimeters = String "cm"
2862 toJSON Millimeters = String "mm"
2863 toJSON NauticalMiles = String "nmi"
2866instance FromJSON DistanceUnit where
2867 parseJSON = withText "DistanceUnit" parse
2868 where parse "mi" = pure Miles
2869 parse "yd" = pure Yards
2870 parse "ft" = pure Feet
2871 parse "in" = pure Inches
2872 parse "km" = pure Kilometers
2873 parse "m" = pure Meters
2874 parse "cm" = pure Centimeters
2875 parse "mm" = pure Millimeters
2876 parse "nmi" = pure NauticalMiles
2877 parse u = fail ("Unrecognized DistanceUnit: " <> show u)
2879instance ToJSON DistanceType where
2880 toJSON Arc = String "arc"
2881 toJSON SloppyArc = String "sloppy_arc"
2882 toJSON Plane = String "plane"
2884instance FromJSON DistanceType where
2885 parseJSON = withText "DistanceType" parse
2886 where parse "arc" = pure Arc
2887 parse "sloppy_arc" = pure SloppyArc
2888 parse "plane" = pure Plane
2889 parse t = fail ("Unrecognized DistanceType: " <> show t)
2892instance ToJSON OptimizeBbox where
2893 toJSON NoOptimizeBbox = String "none"
2894 toJSON (OptimizeGeoFilterType gft) = toJSON gft
2896instance FromJSON OptimizeBbox where
2897 parseJSON v = withText "NoOptimizeBbox" parseNoOptimize v
2899 where parseNoOptimize "none" = pure NoOptimizeBbox
2900 parseNoOptimize _ = mzero
2901 parseOptimize = fmap OptimizeGeoFilterType . parseJSON
2903instance ToJSON GeoBoundingBoxConstraint where
2904 toJSON (GeoBoundingBoxConstraint
2905 (FieldName gbbcGeoBBField) gbbcConstraintBox cache type') =
2906 object [gbbcGeoBBField .= gbbcConstraintBox
2910instance FromJSON GeoBoundingBoxConstraint where
2911 parseJSON = withObject "GeoBoundingBoxConstraint" parse
2912 where parse o = case HM.toList (deleteSeveral ["type", "_cache"] o) of
2913 [(fn, v)] -> GeoBoundingBoxConstraint (FieldName fn)
2915 <*> o .:? "_cache" .!= defaultCache
2917 _ -> fail "Could not find field name for GeoBoundingBoxConstraint"
2919instance ToJSON GeoFilterType where
2920 toJSON GeoFilterMemory = String "memory"
2921 toJSON GeoFilterIndexed = String "indexed"
2923instance FromJSON GeoFilterType where
2924 parseJSON = withText "GeoFilterType" parse
2925 where parse "memory" = pure GeoFilterMemory
2926 parse "indexed" = pure GeoFilterIndexed
2927 parse t = fail ("Unrecognized GeoFilterType: " <> show t)
2929instance ToJSON GeoBoundingBox where
2930 toJSON (GeoBoundingBox gbbTopLeft gbbBottomRight) =
2931 object ["top_left" .= gbbTopLeft
2932 , "bottom_right" .= gbbBottomRight]
2934instance FromJSON GeoBoundingBox where
2935 parseJSON = withObject "GeoBoundingBox" parse
2936 where parse o = GeoBoundingBox
2938 <*> o .: "bottom_right"
2940instance ToJSON LatLon where
2941 toJSON (LatLon lLat lLon) =
2942 object ["lat" .= lLat
2945instance FromJSON LatLon where
2946 parseJSON = withObject "LatLon" parse
2947 where parse o = LatLon <$> o .: "lat"
2950-- index for smaller ranges, fielddata for longer ranges
2951instance ToJSON RangeExecution where
2952 toJSON RangeExecutionIndex = "index"
2953 toJSON RangeExecutionFielddata = "fielddata"
2956instance FromJSON RangeExecution where
2957 parseJSON = withText "RangeExecution" parse
2958 where parse "index" = pure RangeExecutionIndex
2959 parse "fielddata" = pure RangeExecutionFielddata
2960 parse t = error ("Unrecognized RangeExecution " <> show t)
2962instance ToJSON RegexpFlags where
2963 toJSON AllRegexpFlags = String "ALL"
2964 toJSON NoRegexpFlags = String "NONE"
2965 toJSON (SomeRegexpFlags (h :| fs)) = String $ T.intercalate "|" flagStrs
2966 where flagStrs = map flagStr . nub $ h:fs
2967 flagStr AnyString = "ANYSTRING"
2968 flagStr Automaton = "AUTOMATON"
2969 flagStr Complement = "COMPLEMENT"
2970 flagStr Empty = "EMPTY"
2971 flagStr Intersection = "INTERSECTION"
2972 flagStr Interval = "INTERVAL"
2974instance FromJSON RegexpFlags where
2975 parseJSON = withText "RegexpFlags" parse
2976 where parse "ALL" = pure AllRegexpFlags
2977 parse "NONE" = pure NoRegexpFlags
2978 parse t = SomeRegexpFlags <$> parseNEJSON (String <$> T.splitOn "|" t)
2980instance FromJSON RegexpFlag where
2981 parseJSON = withText "RegexpFlag" parse
2982 where parse "ANYSTRING" = pure AnyString
2983 parse "AUTOMATON" = pure Automaton
2984 parse "COMPLEMENT" = pure Complement
2985 parse "EMPTY" = pure Empty
2986 parse "INTERSECTION" = pure Intersection
2987 parse "INTERVAL" = pure Interval
2988 parse f = fail ("Unknown RegexpFlag: " <> show f)
2990instance ToJSON Term where
2991 toJSON (Term field value) = object ["term" .= object
2994instance FromJSON Term where
2995 parseJSON = withObject "Term" parse
2996 where parse o = do termObj <- o .: "term"
2997 case HM.toList termObj of
2998 [(fn, v)] -> Term fn <$> parseJSON v
2999 _ -> fail "Expected object with 1 field-named key"
3001instance ToJSON BoolMatch where
3002 toJSON (MustMatch term cache) = object ["must" .= term,
3004 toJSON (MustNotMatch term cache) = object ["must_not" .= term,
3006 toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
3009instance FromJSON BoolMatch where
3010 parseJSON = withObject "BoolMatch" parse
3011 where parse o = mustMatch `taggedWith` "must"
3012 <|> mustNotMatch `taggedWith` "must_not"
3013 <|> shouldMatch `taggedWith` "should"
3014 where taggedWith parser k = parser =<< o .: k
3015 mustMatch t = MustMatch t <$> o .:? "_cache" .!= defaultCache
3016 mustNotMatch t = MustNotMatch t <$> o .:? "_cache" .!= defaultCache
3017 shouldMatch t = ShouldMatch t <$> o .:? "_cache" .!= defaultCache
3019instance (FromJSON a) => FromJSON (SearchResult a) where
3020 parseJSON (Object v) = SearchResult <$>
3022 v .: "timed_out" <*>
3025 v .:? "aggregations" <*>
3029instance (FromJSON a) => FromJSON (SearchHits a) where
3030 parseJSON (Object v) = SearchHits <$>
3032 v .: "max_score" <*>
3036instance (FromJSON a) => FromJSON (Hit a) where
3037 parseJSON (Object v) = Hit <$>
3046instance FromJSON ShardResult where
3047 parseJSON (Object v) = ShardResult <$>
3049 v .: "successful" <*>
3054instance FromJSON DocVersion where
3057 maybe (fail "DocVersion out of range") return $ mkDocVersion i
3059instance Bounded DocVersion where
3060 minBound = DocVersion 1
3061 maxBound = DocVersion 9200000000000000000 -- 9.2e+18
3063instance Enum DocVersion where
3065 | x /= maxBound = DocVersion (succ $ docVersionNumber x)
3066 | otherwise = succError "DocVersion"
3068 | x /= minBound = DocVersion (pred $ docVersionNumber x)
3069 | otherwise = predError "DocVersion"
3071 fromMaybe (error $ show i ++ " out of DocVersion range") $ mkDocVersion i
3072 fromEnum = docVersionNumber
3073 enumFrom = boundedEnumFrom
3074 enumFromThen = boundedEnumFromThen
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list