git.iko.soy/typeable/bloodhound
on master help sign in
Elastic 5.0 compatibility

This commit moves bloodhound library to use elastic 5.0. The filter type was changes to be a wrapper for queries, and some new APIs are met. It is *not* feture-complete, however, all tests pass.

commit437bc3d16f00bb2de339a682e3df866d0518e94d authorJosh Berman <berman.josh@gmail.com> dateTue 29 Nov 2016, 13:18 (10 years ago) parent0027a45
6 files changed+262−727
bloodhound.cabal → bloodhound5.cabal+4−4 src/Database/Bloodhound/Client.hs+66−63 src/Database/Bloodhound/Types.hs+142−385 stack-8.0.yaml−15 stack.yaml+15−1 tests/tests.hs+35−259
bloodhound.cabal → bloodhound5.cabalrenamed+4−4
@@ -1,4 +1,4 @@
1−name: bloodhound
1+name: bloodhound5
22version: 0.12.0.0
33synopsis: ElasticSearch client library for Haskell
44description: ElasticSearch made awesome for Haskell hackers
@@ -57,7 +57,7 @@ test-suite tests
5757 main-is: tests.hs
5858 hs-source-dirs: tests
5959 build-depends: base,
60− bloodhound,
60+ bloodhound5,
6161 bytestring,
6262 http-client,
6363 http-types,
@@ -76,7 +76,7 @@ test-suite tests
7676 errors,
7777 exceptions,
7878 temporary,
79− unix,
79+ unix-compat,
8080 network-uri
8181 default-language: Haskell2010
8282
@@ -89,7 +89,7 @@ test-suite doctests
8989 if impl(ghc >= 7.8)
9090 build-depends: base,
9191 aeson,
92− bloodhound,
92+ bloodhound5,
9393 directory,
9494 doctest >= 0.10.1,
9595 filepath
src/Database/Bloodhound/Client.hs+66−63
@@ -28,7 +28,7 @@ module Database.Bloodhound.Client
2828 , deleteIndex
2929 , updateIndexSettings
3030 , getIndexSettings
31− , optimizeIndex
31+ , forceMergeIndex
3232 , indexExists
3333 , openIndex
3434 , closeIndex
@@ -43,7 +43,6 @@ module Database.Bloodhound.Client
4343 , deleteTemplate
4444 -- ** Mapping
4545 , putMapping
46− , deleteMapping
4746 -- ** Documents
4847 , indexDocument
4948 , updateDocument
@@ -133,7 +132,8 @@ import Database.Bloodhound.Types
133132-- >>> let testMapping = MappingName "tweet"
134133-- >>> let defaultIndexSettings = IndexSettings (ShardCount 1) (ReplicaCount 0)
135134-- >>> data TweetMapping = TweetMapping deriving (Eq, Show)
136−-- >>> _ <- runBH' $ deleteIndex testIndex >> deleteMapping testIndex testMapping
135+-- >>> _ <- runBH' $ deleteIndex testIndex
136+-- >>> _ <- runBH' $ deleteIndex (IndexName "didimakeanindex")
137137-- >>> import GHC.Generics
138138-- >>> import Data.Time.Calendar (Day (..))
139139-- >>> import Data.Time.Clock (UTCTime (..), secondsToDiffTime)
@@ -224,12 +224,8 @@ appendSearchTypeParam originalUrl st = addQuery params originalUrl
224224 where stText = "search_type"
225225 params
226226 | st == SearchTypeDfsQueryThenFetch = [(stText, Just "dfs_query_then_fetch")]
227− | st == SearchTypeCount = [(stText, Just "count")]
228− | st == SearchTypeScan = [(stText, Just "scan"), ("scroll", Just "1m")]
229− | st == SearchTypeQueryAndFetch = [(stText, Just "query_and_fetch")]
230− | st == SearchTypeDfsQueryAndFetch = [(stText, Just "dfs_query_and_fetch")]
231227 -- used to catch 'SearchTypeQueryThenFetch', which is also the default
232− | otherwise = [(stText, Just "query_then_fetch")]
228+ | otherwise = []
233229
234230-- | Severely dumbed down query renderer. Assumes your data doesn't
235231-- need any encoding
@@ -273,8 +269,8 @@ post = dispatch NHTM.methodPost
273269-- | 'getStatus' fetches the 'Status' of a 'Server'
274270--
275271-- >>> serverStatus <- runBH' getStatus
276−-- >>> fmap status (serverStatus)
277−-- Just 200
272+-- >>> fmap tagline (serverStatus)
273+-- Just "You Know, for Search"
278274getStatus :: MonadBH m => m (Maybe Status)
279275getStatus = do
280276 response <- get =<< url
@@ -513,7 +509,7 @@ createIndex indexSettings (IndexName indexName) =
513509-- >>> response <- runBH' $ deleteIndex (IndexName "didimakeanindex")
514510-- >>> respIsTwoHunna response
515511-- True
516−-- >>> runBH' $ indexExists testIndex
512+-- >>> runBH' $ indexExists (IndexName "didimakeanindex")
517513-- False
518514deleteIndex :: MonadBH m => IndexName -> m Reply
519515deleteIndex (IndexName indexName) =
@@ -540,33 +536,36 @@ getIndexSettings (IndexName indexName) = do
540536 where url = joinPath [indexName, "_settings"]
541537
542538
543−-- | 'optimizeIndex' will optimize a single index, list of indexes or
544−-- all indexes. Note that this call will block until finishing but
545−-- will continue even if the request times out. Concurrent requests to
546−-- optimize an index while another is performing will block until the
547−-- previous one finishes. For more information see
548−-- <https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-optimize.html>. Nothing
539+-- | 'forceMergeIndex'
540+--
541+-- The force merge API allows to force merging of one or more indices through
542+-- an API. The merge relates to the number of segments a Lucene index holds
543+-- within each shard. The force merge operation allows to reduce the number of
544+-- segments by merging them.
545+--
546+-- This call will block until the merge is complete. If the http connection is
547+-- lost, the request will continue in the background, and any new requests will
548+-- block until the previous force merge is complete.
549+
550+-- For more information see
551+-- <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html#indices-forcemerge>.
552+-- Nothing
549553-- worthwhile comes back in the reply body, so matching on the status
550554-- should suffice.
551555--
552−-- 'optimizeIndex' with a maxNumSegments of 1 and onlyExpungeDeletes
556+-- 'forceMergeIndex' with a maxNumSegments of 1 and onlyExpungeDeletes
553557-- to True is the main way to release disk space back to the OS being
554558-- held by deleted documents.
555559--
556−-- Note that this API was deprecated in ElasticSearch 2.1 for the
557−-- almost completely identical forcemerge API. Adding support to that
558−-- API would be trivial but due to the significant breaking changes,
559−-- this library cannot currently be used with >= 2.0, so that feature was omitted.
560−--
561560-- >>> let ixn = IndexName "unoptimizedindex"
562561-- >>> _ <- runBH' $ deleteIndex ixn >> createIndex defaultIndexSettings ixn
563−-- >>> response <- runBH' $ optimizeIndex (IndexList (ixn :| [])) (defaultIndexOptimizationSettings { maxNumSegments = Just 1, onlyExpungeDeletes = True })
562+-- >>> response <- runBH' $ forceMergeIndex (IndexList (ixn :| [])) (defaultIndexOptimizationSettings { maxNumSegments = Just 1, onlyExpungeDeletes = True })
564563-- >>> respIsTwoHunna response
565564-- True
566−optimizeIndex :: MonadBH m => IndexSelection -> IndexOptimizationSettings -> m Reply
567−optimizeIndex ixs IndexOptimizationSettings {..} =
565+forceMergeIndex :: MonadBH m => IndexSelection -> ForceMergeIndexSettings -> m Reply
566+forceMergeIndex ixs ForceMergeIndexSettings {..} =
568567 bindM2 post url (return body)
569− where url = addQuery params <$> joinPath [indexName, "_optimize"]
568+ where url = addQuery params <$> joinPath [indexName, "_forcemerge"]
570569 params = catMaybes [ ("max_num_segments",) . Just . showText <$> maxNumSegments
571570 , Just ("only_expunge_deletes", Just (boolQP onlyExpungeDeletes))
572571 , Just ("flush", Just (boolQP flushAfterOptimize))
@@ -745,7 +744,7 @@ deleteTemplate (TemplateName templateName) =
745744-- >>> _ <- runBH' $ createIndex defaultIndexSettings testIndex
746745-- >>> resp <- runBH' $ putMapping testIndex testMapping TweetMapping
747746-- >>> print resp
748−-- Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Content-Type","application/json; charset=UTF-8"),("Content-Length","21")], responseBody = "{\"acknowledged\":true}", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
747+-- Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("content-type","application/json; charset=UTF-8"),("content-encoding","gzip"),("transfer-encoding","chunked")], responseBody = "{\"acknowledged\":true}", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
749748putMapping :: (MonadBH m, ToJSON a) => IndexName
750749 -> MappingName -> a -> m Reply
751750putMapping (IndexName indexName) (MappingName mappingName) mapping =
@@ -755,21 +754,6 @@ putMapping (IndexName indexName) (MappingName mappingName) mapping =
755754 -- erroneously. The correct API call is: "/INDEX/_mapping/MAPPING_NAME"
756755 body = Just $ encode mapping
757756
758−-- | 'deleteMapping' is an HTTP DELETE and deletes a mapping for a given index.
759−-- Mappings are schemas for documents in indexes.
760−--
761−-- >>> _ <- runBH' $ createIndex defaultIndexSettings testIndex
762−-- >>> _ <- runBH' $ putMapping testIndex testMapping TweetMapping
763−-- >>> resp <- runBH' $ deleteMapping testIndex testMapping
764−-- >>> print resp
765−-- Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}, responseVersion = HTTP/1.1, responseHeaders = [("Content-Type","application/json; charset=UTF-8"),("Content-Length","21")], responseBody = "{\"acknowledged\":true}", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
766−deleteMapping :: MonadBH m => IndexName -> MappingName -> m Reply
767−deleteMapping (IndexName indexName)
768− (MappingName mappingName) =
769− -- "_mapping" and mappingName below were originally transposed
770− -- erroneously. The correct API call is: "/INDEX/_mapping/MAPPING_NAME"
771− delete =<< joinPath [indexName, "_mapping", mappingName]
772−
773757versionCtlParams :: IndexDocumentSettings -> [(Text, Maybe Text)]
774758versionCtlParams cfg =
775759 case idsVersionControl cfg of
@@ -791,7 +775,7 @@ versionCtlParams cfg =
791775--
792776-- >>> resp <- runBH' $ indexDocument testIndex testMapping defaultIndexDocumentSettings exampleTweet (DocId "1")
793777-- >>> print resp
794−-- Response {responseStatus = Status {statusCode = 201, statusMessage = "Created"}, responseVersion = HTTP/1.1, responseHeaders = [("Content-Type","application/json; charset=UTF-8"),("Content-Length","74")], responseBody = "{\"_index\":\"twitter\",\"_type\":\"tweet\",\"_id\":\"1\",\"_version\":1,\"created\":true}", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
778+-- Response {responseStatus = Status {statusCode = 201, statusMessage = "Created"}, responseVersion = HTTP/1.1, responseHeaders = [("Location","/twitter/tweet/1"),("content-type","application/json; charset=UTF-8"),("content-encoding","gzip"),("transfer-encoding","chunked")], responseBody = "{\"_index\":\"twitter\",\"_type\":\"tweet\",\"_id\":\"1\",\"_version\":1,\"result\":\"created\",\"_shards\":{\"total\":2,\"successful\":1,\"failed\":0},\"created\":true}", responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
795779indexDocument :: (ToJSON doc, MonadBH m) => IndexName -> MappingName
796780 -> IndexDocumentSettings -> doc -> DocId -> m Reply
797781indexDocument (IndexName indexName)
@@ -958,16 +942,21 @@ searchByType (IndexName indexName)
958942-- search results. Note that the search is put into 'SearchTypeScan'
959943-- mode and thus results will not be sorted. Combine this with
960944-- 'advanceScroll' to efficiently stream through the full result set
961−getInitialScroll :: MonadBH m => IndexName -> MappingName -> Search -> m (Maybe ScrollId)
962−getInitialScroll (IndexName indexName) (MappingName mappingName) search = do
963− let url = joinPath [indexName, mappingName, "_search"]
964− search' = search { searchType = SearchTypeScan }
965− resp' <- bindM2 dispatchSearch url (return search')
966− let msr = decode' $ responseBody resp' :: Maybe (SearchResult ())
967− msid = maybe Nothing scrollId msr
968− return msid
969−
970−scroll' :: (FromJSON a, MonadBH m, MonadThrow m) => Maybe ScrollId -> m ([Hit a], Maybe ScrollId)
945+getInitialScroll ::
946+ (FromJSON a, MonadThrow m, MonadBH m) => IndexName ->
947+ MappingName ->
948+ Search ->
949+ m (Either EsError (SearchResult a))
950+getInitialScroll (IndexName indexName) (MappingName mappingName) search' = do
951+ let url = addQuery params <$> joinPath [indexName, mappingName, "_search"]
952+ params = [("scroll", Just "1m")]
953+ sorting = Just [DefaultSortSpec $ mkSort (FieldName "_doc") Descending]
954+ search = search' { sortBody = sorting }
955+ resp' <- bindM2 dispatchSearch url (return search)
956+ parseEsResponse resp'
957+
958+scroll' :: (FromJSON a, MonadBH m, MonadThrow m) => Maybe ScrollId ->
959+ m ([Hit a], Maybe ScrollId)
971960scroll' Nothing = return ([], Nothing)
972961scroll' (Just sid) = do
973962 res <- advanceScroll sid 60
@@ -987,20 +976,29 @@ advanceScroll
987976 -- ^ How long should the snapshot of data be kept around? This timeout is updated every time 'advanceScroll' is used, so don't feel the need to set it to the entire duration of your search processing. Note that durations < 1s will be rounded up. Also note that 'NominalDiffTime' is an instance of Num so literals like 60 will be interpreted as seconds. 60s is a reasonable default.
988977 -> m (Either EsError (SearchResult a))
989978advanceScroll (ScrollId sid) scroll = do
990− url <- joinPath ["_search/scroll?scroll=" <> scrollTime]
991− parseEsResponse =<< post url (Just . L.fromStrict $ T.encodeUtf8 sid)
979+ url <- joinPath ["_search", "scroll"]
980+ resp <- post url (Just $ encode scrollObject)
981+ parseEsResponse resp
992982 where scrollTime = showText secs <> "s"
993983 secs :: Integer
994984 secs = round scroll
995−
996−simpleAccumulator :: (FromJSON a, MonadBH m, MonadThrow m) => [Hit a] -> ([Hit a], Maybe ScrollId) -> m ([Hit a], Maybe ScrollId)
985+
986+ scrollObject = object [ "scroll" .= scrollTime
987+ , "scroll_id" .= sid
988+ ]
989+
990+simpleAccumulator ::
991+ (FromJSON a, MonadBH m, MonadThrow m) =>
992+ [Hit a] ->
993+ ([Hit a], Maybe ScrollId) ->
994+ m ([Hit a], Maybe ScrollId)
997995simpleAccumulator oldHits (newHits, Nothing) = return (oldHits ++ newHits, Nothing)
998996simpleAccumulator oldHits ([], _) = return (oldHits, Nothing)
999997simpleAccumulator oldHits (newHits, msid) = do
1000998 (newHits', msid') <- scroll' msid
1001999 simpleAccumulator (oldHits ++ newHits) (newHits', msid')
10021000
1003−-- | 'scanSearch' uses the 'scan&scroll' API of elastic,
1001+-- | 'scanSearch' uses the 'scroll' API of elastic,
10041002-- for a given 'IndexName' and 'MappingName'. Note that this will
10051003-- consume the entire search result set and will be doing O(n) list
10061004-- appends so this may not be suitable for large result sets. In that
@@ -1009,11 +1007,16 @@ simpleAccumulator oldHits (newHits, msid) = do
10091007-- pipes, or your favorite streaming IO abstraction of choice. Note
10101008-- that ordering on the search would destroy performance and thus is
10111009-- ignored.
1012−scanSearch :: (FromJSON a, MonadBH m, MonadThrow m) => IndexName -> MappingName -> Search -> m [Hit a]
1010+scanSearch :: (FromJSON a, MonadBH m, MonadThrow m) => IndexName
1011+ -> MappingName
1012+ -> Search
1013+ -> m [Hit a]
10131014scanSearch indexName mappingName search = do
1014− msid <- getInitialScroll indexName mappingName search
1015− (hits, msid') <- scroll' msid
1016− (totalHits, _) <- simpleAccumulator [] (hits, msid')
1015+ initialSearchResult <- getInitialScroll indexName mappingName search
1016+ let (hits', josh) = case initialSearchResult of
1017+ Right SearchResult {..} -> (hits searchHits, scrollId)
1018+ Left _ -> ([], Nothing)
1019+ (totalHits, _) <- simpleAccumulator [] (hits', josh)
10171020 return totalHits
10181021
10191022-- | 'mkSearch' is a helper function for defaulting additional fields of a 'Search'
src/Database/Bloodhound/Types.hs+142−385
@@ -152,8 +152,8 @@ module Database.Bloodhound.Types
152152 , IndexSelection(..)
153153 , NodeSelection(..)
154154 , NodeSelector(..)
155− , IndexOptimizationSettings(..)
156− , defaultIndexOptimizationSettings
155+ , ForceMergeIndexSettings(..)
156+ , defaultForceMergeIndexSettings
157157 , TemplateName(..)
158158 , TemplatePattern(..)
159159 , MappingName(..)
@@ -178,7 +178,6 @@ module Database.Bloodhound.Types
178178 , BoostingQuery(..)
179179 , CommonTermsQuery(..)
180180 , DisMaxQuery(..)
181− , FilteredQuery(..)
182181 , FuzzyLikeThisQuery(..)
183182 , FuzzyLikeFieldQuery(..)
184183 , FuzzyQuery(..)
@@ -452,7 +451,7 @@ runBH e f = runReaderT (unBH f) e
452451{-| 'Version' is embedded in 'Status' -}
453452data Version = Version { number :: VersionNumber
454453 , build_hash :: BuildHash
455− , build_timestamp :: UTCTime
454+ , build_date :: UTCTime
456455 , build_snapshot :: Bool
457456 , lucene_version :: VersionNumber } deriving (Eq, Read, Show, Generic, Typeable)
458457
@@ -466,11 +465,11 @@ newtype VersionNumber = VersionNumber { versionNumber :: Vers.Version
466465 <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-status.html#indices-status>
467466-}
468467
469−data Status = Status { ok :: Maybe Bool
470− , status :: Int
471− , name :: Text
472− , version :: Version
473− , tagline :: Text } deriving (Eq, Read, Show, Generic)
468+data Status = Status { name :: Text
469+ , cluster_name :: Text
470+ , cluster_uuid :: Text
471+ , version :: Version
472+ , tagline :: Text } deriving (Eq, Read, Show, Generic)
474473
475474{-| 'IndexSettings' is used to configure the shards and replicas when you create
476475 an Elasticsearch Index.
@@ -487,12 +486,12 @@ defaultIndexSettings :: IndexSettings
487486defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
488487
489488
490−{-| 'IndexOptimizationSettings' is used to configure index optimization. See
491− <https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-optimize.html>
489+{-| 'ForceMergeIndexSettings' is used to configure index optimization. See
490+ <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html>
492491 for more info.
493492-}
494−data IndexOptimizationSettings =
495− IndexOptimizationSettings { maxNumSegments :: Maybe Int
493+data ForceMergeIndexSettings =
494+ ForceMergeIndexSettings { maxNumSegments :: Maybe Int
496495 -- ^ Number of segments to optimize to. 1 will fully optimize the index. If omitted, the default behavior is to only optimize if the server deems it necessary.
497496 , onlyExpungeDeletes :: Bool
498497 -- ^ Should the optimize process only expunge segments with deletes in them? If the purpose of the optimization is to free disk space, this should be set to True.
@@ -501,12 +500,12 @@ data IndexOptimizationSettings =
501500 } deriving (Eq, Show, Generic, Typeable)
502501
503502
504−{-| 'defaultIndexOptimizationSettings' implements the default settings that
503+{-| 'defaultForceMergeIndexSettings' implements the default settings that
505504 ElasticSearch uses for index optimization. 'maxNumSegments' is Nothing,
506505 'onlyExpungeDeletes' is False, and flushAfterOptimize is True.
507506-}
508−defaultIndexOptimizationSettings :: IndexOptimizationSettings
509−defaultIndexOptimizationSettings = IndexOptimizationSettings Nothing False True
507+defaultForceMergeIndexSettings :: ForceMergeIndexSettings
508+defaultForceMergeIndexSettings = ForceMergeIndexSettings Nothing False True
510509
511510{-| 'UpdatableIndexSetting' are settings which may be updated after an index is created.
512511
@@ -845,6 +844,8 @@ data SortSpec = DefaultSortSpec DefaultSort
845844{-| 'DefaultSort' is usually the kind of 'SortSpec' you'll want. There's a
846845 'mkSort' convenience function for when you want to specify only the most
847846 common parameters.
847+
848+ The `ignoreUnmapped`, when `Just` field is used to set the elastic 'unmapped_type'
848849
849850<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#search-request-sort>
850851-}
@@ -852,7 +853,7 @@ data DefaultSort =
852853 DefaultSort { sortFieldName :: FieldName
853854 , sortOrder :: SortOrder
854855 -- default False
855− , ignoreUnmapped :: Bool
856+ , ignoreUnmapped :: Maybe Text
856857 , sortMode :: Maybe SortMode
857858 , missingSort :: Maybe Missing
858859 , nestedFilter :: Maybe Filter } deriving (Eq, Read, Show, Generic, Typeable)
@@ -887,7 +888,7 @@ data SortMode = SortMin
887888 that you can concisely describe the usual kind of 'SortSpec's you want.
888889-}
889890mkSort :: FieldName -> SortOrder -> DefaultSort
890−mkSort fieldName sOrder = DefaultSort fieldName sOrder False Nothing Nothing Nothing
891+mkSort fieldName sOrder = DefaultSort fieldName sOrder Nothing Nothing Nothing Nothing
891892
892893{-| 'Cache' is for telling ES whether it should cache a 'Filter' not.
893894 'Query's cannot be cached.
@@ -1100,10 +1101,6 @@ data Search = Search { queryBody :: Maybe Query
11001101
11011102data SearchType = SearchTypeQueryThenFetch
11021103 | SearchTypeDfsQueryThenFetch
1103− | SearchTypeCount
1104− | SearchTypeScan
1105− | SearchTypeQueryAndFetch
1106− | SearchTypeDfsQueryAndFetch
11071104 deriving (Eq, Read, Show, Generic, Typeable)
11081105
11091106data Source =
@@ -1183,10 +1180,8 @@ data Query =
11831180 | QueryBoolQuery BoolQuery
11841181 | QueryBoostingQuery BoostingQuery
11851182 | QueryCommonTermsQuery CommonTermsQuery
1186− | ConstantScoreFilter Filter Boost
11871183 | ConstantScoreQuery Query Boost
11881184 | QueryDisMaxQuery DisMaxQuery
1189− | QueryFilteredQuery FilteredQuery
11901185 | QueryFuzzyLikeThisQuery FuzzyLikeThisQuery
11911186 | QueryFuzzyLikeFieldQuery FuzzyLikeFieldQuery
11921187 | QueryFuzzyQuery FuzzyQuery
@@ -1203,8 +1198,21 @@ data Query =
12031198 | QuerySimpleQueryStringQuery SimpleQueryStringQuery
12041199 | QueryRangeQuery RangeQuery
12051200 | QueryRegexpQuery RegexpQuery
1201+ | QueryExistsQuery FieldName
1202+ | QueryMatchNoneQuery
12061203 deriving (Eq, Read, Show, Generic, Typeable)
12071204
1205+-- | As of Elastic 2.0, 'Filters' are just 'Queries' housed in a Bool Query, and
1206+-- flagged in a different context.
1207+newtype Filter = Filter { unFilter :: Query }
1208+ deriving (Eq, Read, Show, Generic, Typeable)
1209+
1210+instance ToJSON Filter where
1211+ toJSON = toJSON . unFilter
1212+
1213+instance FromJSON Filter where
1214+ parseJSON v = Filter <$> parseJSON v
1215+
12081216data RegexpQuery =
12091217 RegexpQuery { regexpQueryField :: FieldName
12101218 , regexpQuery :: Regexp
@@ -1385,11 +1393,6 @@ data FuzzyLikeThisQuery =
13851393 , fuzzyLikeAnalyzer :: Maybe Analyzer
13861394 } deriving (Eq, Read, Show, Generic, Typeable)
13871395
1388−data FilteredQuery =
1389− FilteredQuery
1390− { filteredQuery :: Query
1391− , filteredFilter :: Filter } deriving (Eq, Read, Show, Generic, Typeable)
1392−
13931396data DisMaxQuery =
13941397 DisMaxQuery { disMaxQueries :: [Query]
13951398 -- default 0.0
@@ -1450,6 +1453,7 @@ data MultiMatchQueryType =
14501453
14511454data BoolQuery =
14521455 BoolQuery { boolQueryMustMatch :: [Query]
1456+ , boolQueryFilter :: [Filter]
14531457 , boolQueryMustNotMatch :: [Query]
14541458 , boolQueryShouldMatch :: [Query]
14551459 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
@@ -1457,9 +1461,9 @@ data BoolQuery =
14571461 , boolQueryDisableCoord :: Maybe DisableCoord
14581462 } deriving (Eq, Read, Show, Generic, Typeable)
14591463
1460−mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
1461−mkBoolQuery must mustNot should =
1462− BoolQuery must mustNot should Nothing Nothing Nothing
1464+mkBoolQuery :: [Query] -> [Filter] -> [Query] -> [Query] -> BoolQuery
1465+mkBoolQuery must filter mustNot should =
1466+ BoolQuery must filter mustNot should Nothing Nothing Nothing
14631467
14641468data BoostingQuery =
14651469 BoostingQuery { positiveQuery :: Query
@@ -1487,26 +1491,6 @@ data MinimumMatchHighLow =
14871491 MinimumMatchHighLow { lowFreq :: MinimumMatch
14881492 , highFreq :: MinimumMatch } deriving (Eq, Read, Show, Generic, Typeable)
14891493
1490−data Filter = AndFilter [Filter] Cache
1491− | OrFilter [Filter] Cache
1492− | NotFilter Filter Cache
1493− | IdentityFilter
1494− | BoolFilter BoolMatch
1495− | ExistsFilter FieldName -- always cached
1496− | GeoBoundingBoxFilter GeoBoundingBoxConstraint
1497− | GeoDistanceFilter GeoPoint Distance DistanceType OptimizeBbox Cache
1498− | GeoDistanceRangeFilter GeoPoint DistanceRange
1499− | GeoPolygonFilter FieldName [LatLon]
1500− | IdsFilter MappingName [DocId]
1501− | LimitFilter Int
1502− | MissingFilter FieldName Existence NullValue
1503− | PrefixFilter FieldName PrefixValue Cache
1504− | QueryFilter Query Cache
1505− | RangeFilter FieldName RangeValue RangeExecution Cache
1506− | RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
1507− | TermFilter Term Cache
1508− deriving (Eq, Read, Show, Generic, Typeable)
1509−
15101494data ZeroTermsQuery = ZeroTermsNone
15111495 | ZeroTermsAll deriving (Eq, Read, Show, Generic, Typeable)
15121496
@@ -1713,8 +1697,7 @@ data Interval = Year
17131697 | Day
17141698 | Hour
17151699 | Minute
1716− | Second
1717− | FractionalInterval Float TimeInterval deriving (Eq, Read, Show, Generic, Typeable)
1700+ | Second deriving (Eq, Read, Show, Generic, Typeable)
17181701
17191702data Aggregation = TermsAgg TermsAggregation
17201703 | CardinalityAgg CardinalityAggregation
@@ -1808,7 +1791,7 @@ mkCardinalityAggregation t = CardinalityAggregation t Nothing
18081791instance ToJSON Version where
18091792 toJSON Version {..} = object ["number" .= number
18101793 ,"build_hash" .= build_hash
1811− ,"build_timestamp" .= build_timestamp
1794+ ,"build_date" .= build_date
18121795 ,"build_snapshot" .= build_snapshot
18131796 ,"lucene_version" .= lucene_version]
18141797
@@ -1817,7 +1800,7 @@ instance FromJSON Version where
18171800 where parse o = Version
18181801 <$> o .: "number"
18191802 <*> o .: "build_hash"
1820− <*> o .: "build_timestamp"
1803+ <*> o .: "build_date"
18211804 <*> o .: "build_snapshot"
18221805 <*> o .: "lucene_version"
18231806
@@ -1860,7 +1843,6 @@ instance ToJSON Interval where
18601843 toJSON Hour = "hour"
18611844 toJSON Minute = "minute"
18621845 toJSON Second = "second"
1863− toJSON (FractionalInterval fraction interval) = toJSON $ show fraction ++ show interval
18641846
18651847instance Show TimeInterval where
18661848 show Weeks = "w"
@@ -2058,193 +2040,6 @@ instance FromJSON POSIXMS where
20582040 where parse n = let n' = truncate n :: Integer
20592041 in POSIXMS (posixSecondsToUTCTime (fromInteger (n' `div` 1000)))
20602042
2061−instance Monoid Filter where
2062− mempty = IdentityFilter
2063− mappend a b = AndFilter [a, b] defaultCache
2064−
2065−instance Seminearring Filter where
2066− a <||> b = OrFilter [a, b] defaultCache
2067−
2068−instance ToJSON Filter where
2069− toJSON (AndFilter filters cache) =
2070− object ["and" .=
2071− object [ "filters" .= fmap toJSON filters
2072− , "_cache" .= cache]]
2073−
2074− toJSON (OrFilter filters cache) =
2075− object ["or" .=
2076− object [ "filters" .= fmap toJSON filters
2077− , "_cache" .= cache]]
2078−
2079− toJSON (NotFilter notFilter cache) =
2080− object ["not" .=
2081− object ["filter" .= notFilter
2082− , "_cache" .= cache]]
2083−
2084− toJSON (IdentityFilter) =
2085− object ["match_all" .= object []]
2086−
2087− toJSON (TermFilter (Term termFilterField termFilterValue) cache) =
2088− object ["term" .= object base]
2089− where base = [termFilterField .= termFilterValue,
2090− "_cache" .= cache]
2091−
2092− toJSON (ExistsFilter (FieldName fieldName)) =
2093− object ["exists" .= object
2094− ["field" .= fieldName]]
2095−
2096− toJSON (BoolFilter boolMatch) =
2097− object ["bool" .= boolMatch]
2098−
2099− toJSON (GeoBoundingBoxFilter bbConstraint) =
2100− object ["geo_bounding_box" .= bbConstraint]
2101−
2102− toJSON (GeoDistanceFilter (GeoPoint (FieldName distanceGeoField) geoDistLatLon)
2103− distance distanceType optimizeBbox cache) =
2104− object ["geo_distance" .=
2105− object ["distance" .= distance
2106− , "distance_type" .= distanceType
2107− , "optimize_bbox" .= optimizeBbox
2108− , distanceGeoField .= geoDistLatLon
2109− , "_cache" .= cache]]
2110−
2111− toJSON (GeoDistanceRangeFilter (GeoPoint (FieldName gddrField) drLatLon)
2112− (DistanceRange geoDistRangeDistFrom drDistanceTo)) =
2113− object ["geo_distance_range" .=
2114− object ["from" .= geoDistRangeDistFrom
2115− , "to" .= drDistanceTo
2116− , gddrField .= drLatLon]]
2117−
2118− toJSON (GeoPolygonFilter (FieldName geoPolygonFilterField) latLons) =
2119− object ["geo_polygon" .=
2120− object [geoPolygonFilterField .=
2121− object ["points" .= fmap toJSON latLons]]]
2122−
2123− toJSON (IdsFilter (MappingName mappingName) values) =
2124− object ["ids" .=
2125− object ["type" .= mappingName
2126− , "values" .= fmap unpackId values]]
2127−
2128− toJSON (LimitFilter limit) =
2129− object ["limit" .= object ["value" .= limit]]
2130−
2131− toJSON (MissingFilter (FieldName fieldName) (Existence existence) (NullValue nullValue)) =
2132− object ["missing" .=
2133− object ["field" .= fieldName
2134− , "existence" .= existence
2135− , "null_value" .= nullValue]]
2136−
2137− toJSON (PrefixFilter (FieldName fieldName) fieldValue cache) =
2138− object ["prefix" .=
2139− object [fieldName .= fieldValue
2140− , "_cache" .= cache]]
2141−
2142− toJSON (QueryFilter query False) =
2143− object ["query" .= toJSON query ]
2144− toJSON (QueryFilter query True) =
2145− object ["fquery" .=
2146− object [ "query" .= toJSON query
2147− , "_cache" .= True ]]
2148−
2149− toJSON (RangeFilter (FieldName fieldName) rangeValue rangeExecution cache) =
2150− object ["range" .=
2151− object [ fieldName .= object (rangeValueToPair rangeValue)
2152− , "execution" .= rangeExecution
2153− , "_cache" .= cache]]
2154−
2155− toJSON (RegexpFilter (FieldName fieldName)
2156− (Regexp regexText) flags (CacheName cacheName) cache (CacheKey cacheKey)) =
2157− object ["regexp" .=
2158− object [fieldName .=
2159− object ["value" .= regexText
2160− , "flags" .= flags]
2161− , "_name" .= cacheName
2162− , "_cache" .= cache
2163− , "_cache_key" .= cacheKey]]
2164−
2165−instance FromJSON Filter where
2166− parseJSON = withObject "Filter" parse
2167− where parse o = andFilter `taggedWith` "and"
2168− <|> orFilter `taggedWith` "or"
2169− <|> notFilter `taggedWith` "not"
2170− <|> identityFilter `taggedWith` "match_all"
2171− <|> boolFilter `taggedWith` "bool"
2172− <|> existsFilter `taggedWith` "exists"
2173− <|> geoBoundingBoxFilter `taggedWith` "geo_bounding_box"
2174− <|> geoDistanceFilter `taggedWith` "geo_distance"
2175− <|> geoDistanceRangeFilter `taggedWith` "geo_distance_range"
2176− <|> geoPolygonFilter `taggedWith` "geo_polygon"
2177− <|> idsFilter `taggedWith` "ids"
2178− <|> limitFilter `taggedWith` "limit"
2179− <|> missingFilter `taggedWith` "missing"
2180− <|> prefixFilter `taggedWith` "prefix"
2181− <|> queryFilter `taggedWith` "query"
2182− <|> fqueryFilter `taggedWith` "fquery"
2183− <|> rangeFilter `taggedWith` "range"
2184− <|> regexpFilter `taggedWith` "regexp"
2185− <|> termFilter `taggedWith` "term"
2186− where taggedWith parser k = parser =<< o .: k
2187− andFilter o = AndFilter <$> o .: "filters"
2188− <*> o .:? "_cache" .!= defaultCache
2189− orFilter o = OrFilter <$> o .: "filters"
2190− <*> o .:? "_cache" .!= defaultCache
2191− notFilter o = NotFilter <$> o .: "filter"
2192− <*> o .: "_cache" .!= defaultCache
2193− identityFilter :: Object -> Parser Filter
2194− identityFilter m
2195− | HM.null m = pure IdentityFilter
2196− | otherwise = fail ("Identityfilter expected empty object but got " <> show m)
2197− boolFilter = pure . BoolFilter
2198− existsFilter o = ExistsFilter <$> o .: "field"
2199− geoBoundingBoxFilter = pure . GeoBoundingBoxFilter
2200− geoDistanceFilter o = do
2201− case HM.toList (deleteSeveral ["distance", "distance_type", "optimize_bbox", "_cache"] o) of
2202− [(fn, v)] -> do
2203− gp <- GeoPoint (FieldName fn) <$> parseJSON v
2204− GeoDistanceFilter gp <$> o .: "distance"
2205− <*> o .: "distance_type"
2206− <*> o .: "optimize_bbox"
2207− <*> o .:? "_cache" .!= defaultCache
2208− _ -> fail "Could not find GeoDistanceFilter field name"
2209− geoDistanceRangeFilter o = do
2210− case HM.toList (deleteSeveral ["from", "to"] o) of
2211− [(fn, v)] -> do
2212− gp <- GeoPoint (FieldName fn) <$> parseJSON v
2213− rng <- DistanceRange <$> o .: "from" <*> o .: "to"
2214− return (GeoDistanceRangeFilter gp rng)
2215− _ -> fail "Could not find GeoDistanceRangeFilter field name"
2216− geoPolygonFilter = fieldTagged $ \fn o -> GeoPolygonFilter fn <$> o .: "points"
2217− idsFilter o = IdsFilter <$> o .: "type"
2218− <*> o .: "values"
2219− limitFilter o = LimitFilter <$> o .: "value"
2220− missingFilter o = MissingFilter <$> o .: "field"
2221− <*> o .: "existence"
2222− <*> o .: "null_value"
2223− prefixFilter o = case HM.toList (HM.delete "_cache" o) of
2224− [(fn, String v)] -> PrefixFilter (FieldName fn) v <$> o .:? "_cache" .!= defaultCache
2225− _ -> fail "Could not parse PrefixFilter"
2226−
2227− queryFilter q = pure (QueryFilter q False)
2228− fqueryFilter o = QueryFilter <$> o .: "query" <*> pure True
2229− rangeFilter o = case HM.toList (deleteSeveral ["execution", "_cache"] o) of
2230− [(fn, v)] -> RangeFilter (FieldName fn)
2231− <$> parseJSON v
2232− <*> o .: "execution"
2233− <*> o .:? "_cache" .!= defaultCache
2234− _ -> fail "Could not find field name for RangeFilter"
2235− regexpFilter o = case HM.toList (deleteSeveral ["_name", "_cache", "_cache_key"] o) of
2236− [(fn, Object o')] -> RegexpFilter (FieldName fn)
2237− <$> o' .: "value"
2238− <*> o' .: "flags"
2239− <*> o .: "_name"
2240− <*> o .:? "_cache" .!= defaultCache
2241− <*> o .: "_cache_key"
2242− _ -> fail "Could not find field name for RegexpFilter"
2243− termFilter o = case HM.toList (HM.delete "_cache" o) of
2244− [(termField, String termVal)] -> TermFilter (Term termField termVal)
2245− <$> o .:? "_cache" .!= defaultCache
2246− _ -> fail "Could not find term field for TermFilter"
2247−
22482043fieldTagged :: Monad m => (FieldName -> Object -> m a) -> Object -> m a
22492044fieldTagged f o = case HM.toList o of
22502045 [(k, Object o')] -> f (FieldName k) o'
@@ -2291,10 +2086,6 @@ instance ToJSON Query where
22912086 toJSON (QueryCommonTermsQuery commonTermsQuery) =
22922087 object [ "common" .= commonTermsQuery ]
22932088
2294− toJSON (ConstantScoreFilter csFilter boost) =
2295− object ["constant_score" .= object ["filter" .= csFilter
2296− , "boost" .= boost]]
2297−
22982089 toJSON (ConstantScoreQuery query boost) =
22992090 object ["constant_score" .= object ["query" .= query
23002091 , "boost" .= boost]]
@@ -2302,9 +2093,6 @@ instance ToJSON Query where
23022093 toJSON (QueryDisMaxQuery disMaxQuery) =
23032094 object [ "dis_max" .= disMaxQuery ]
23042095
2305− toJSON (QueryFilteredQuery qFilteredQuery) =
2306− object [ "filtered" .= qFilteredQuery ]
2307−
23082096 toJSON (QueryFuzzyLikeThisQuery fuzzyQuery) =
23092097 object [ "fuzzy_like_this" .= fuzzyQuery ]
23102098
@@ -2347,6 +2135,13 @@ instance ToJSON Query where
23472135 toJSON (QuerySimpleQueryStringQuery query) =
23482136 object [ "simple_query_string" .= query ]
23492137
2138+ toJSON (QueryExistsQuery (FieldName fieldName)) =
2139+ object ["exists" .= object
2140+ ["field" .= fieldName]
2141+ ]
2142+ toJSON QueryMatchNoneQuery =
2143+ object ["match_none" .= object []]
2144+
23502145instance FromJSON Query where
23512146 parseJSON v = withObject "Query" parse v
23522147 where parse o = termQuery `taggedWith` "term"
@@ -2358,10 +2153,8 @@ instance FromJSON Query where
23582153 <|> queryBoolQuery `taggedWith` "bool"
23592154 <|> queryBoostingQuery `taggedWith` "boosting"
23602155 <|> queryCommonTermsQuery `taggedWith` "common"
2361− <|> constantScoreFilter `taggedWith` "constant_score"
23622156 <|> constantScoreQuery `taggedWith` "constant_score"
23632157 <|> queryDisMaxQuery `taggedWith` "dis_max"
2364− <|> queryFilteredQuery `taggedWith` "filtered"
23652158 <|> queryFuzzyLikeThisQuery `taggedWith` "fuzzy_like_this"
23662159 <|> queryFuzzyLikeFieldQuery `taggedWith` "fuzzy_like_this_field"
23672160 <|> queryFuzzyQuery `taggedWith` "fuzzy"
@@ -2393,16 +2186,11 @@ instance FromJSON Query where
23932186 queryBoolQuery = pure . QueryBoolQuery
23942187 queryBoostingQuery = pure . QueryBoostingQuery
23952188 queryCommonTermsQuery = pure . QueryCommonTermsQuery
2396− constantScoreFilter o = case HM.lookup "filter" o of
2397− Just x -> ConstantScoreFilter <$> parseJSON x
2398− <*> o .: "boost"
2399− _ -> fail "Does not appear to be a ConstantScoreFilter"
24002189 constantScoreQuery o = case HM.lookup "query" o of
24012190 Just x -> ConstantScoreQuery <$> parseJSON x
24022191 <*> o .: "boost"
24032192 _ -> fail "Does not appear to be a ConstantScoreQuery"
24042193 queryDisMaxQuery = pure . QueryDisMaxQuery
2405− queryFilteredQuery = pure . QueryFilteredQuery
24062194 queryFuzzyLikeThisQuery = pure . QueryFuzzyLikeThisQuery
24072195 queryFuzzyLikeFieldQuery = pure . QueryFuzzyLikeFieldQuery
24082196 queryFuzzyQuery = pure . QueryFuzzyQuery
@@ -2417,6 +2205,7 @@ instance FromJSON Query where
24172205 queryRangeQuery = pure . QueryRangeQuery
24182206 queryRegexpQuery = pure . QueryRegexpQuery
24192207 querySimpleQueryStringQuery = pure . QuerySimpleQueryStringQuery
2208+ queryExistsQuery o = QueryExistsQuery <$> o .: "field"
24202209
24212210
24222211omitNulls :: [(Text, Value)] -> Value
@@ -2425,7 +2214,6 @@ omitNulls = object . filter notNull where
24252214 notNull (_, Array a) = (not . V.null) a
24262215 notNull _ = True
24272216
2428−
24292217instance ToJSON SimpleQueryStringQuery where
24302218 toJSON SimpleQueryStringQuery {..} =
24312219 omitNulls (base ++ maybeAdd)
@@ -2814,17 +2602,6 @@ instance FromJSON FuzzyLikeThisQuery where
28142602 <*> o .: "boost"
28152603 <*> o .:? "analyzer"
28162604
2817−instance ToJSON FilteredQuery where
2818− toJSON (FilteredQuery query fFilter) =
2819− object [ "query" .= query
2820− , "filter" .= fFilter ]
2821−
2822−instance FromJSON FilteredQuery where
2823− parseJSON = withObject "FilteredQuery" parse
2824− where parse o = FilteredQuery
2825− <$> o .: "query"
2826− <*> o .: "filter"
2827−
28282605instance ToJSON DisMaxQuery where
28292606 toJSON (DisMaxQuery queries tiebreaker boost) =
28302607 omitNulls base
@@ -2896,9 +2673,10 @@ instance FromJSON BoostingQuery where
28962673 <*> o .: "negative_boost"
28972674
28982675instance ToJSON BoolQuery where
2899− toJSON (BoolQuery mustM notM shouldM bqMin boost disableCoord) =
2676+ toJSON (BoolQuery mustM filterM notM shouldM bqMin boost disableCoord) =
29002677 omitNulls base
29012678 where base = [ "must" .= mustM
2679+ , "filter" .= filterM
29022680 , "must_not" .= notM
29032681 , "should" .= shouldM
29042682 , "minimum_should_match" .= bqMin
@@ -2909,6 +2687,7 @@ instance FromJSON BoolQuery where
29092687 parseJSON = withObject "BoolQuery" parse
29102688 where parse o = BoolQuery
29112689 <$> o .:? "must" .!= []
2690+ <*> o .:? "filter" .!= []
29122691 <*> o .:? "must_not" .!= []
29132692 <*> o .:? "should" .!= []
29142693 <*> o .:? "minimum_should_match"
@@ -3023,9 +2802,9 @@ instance FromJSON MatchQueryType where
30232802
30242803instance FromJSON Status where
30252804 parseJSON (Object v) = Status <$>
3026− v .:? "ok" <*>
3027− (v .:? "status" .!= 200) <*>
30282805 v .: "name" <*>
2806+ v .: "cluster_name" <*>
2807+ v .: "cluster_uuid" <*>
30292808 v .: "version" <*>
30302809 v .: "tagline"
30312810 parseJSON _ = empty
@@ -3355,9 +3134,8 @@ instance FromJSON SearchAliasRouting where
33553134 where parse t = SearchAliasRouting <$> parseNEJSON (String <$> T.splitOn "," t)
33563135
33573136instance ToJSON Search where
3358− toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
3359− omitNulls [ "query" .= query
3360− , "filter" .= sFilter
3137+ toJSON (Search mquery sFilter sort searchAggs highlight sTrackSortScores sFrom sSize _ sFields sSource) =
3138+ omitNulls [ "query" .= query'
33613139 , "sort" .= sort
33623140 , "aggregations" .= searchAggs
33633141 , "highlight" .= highlight
@@ -3366,12 +3144,15 @@ instance ToJSON Search where
33663144 , "track_scores" .= sTrackSortScores
33673145 , "fields" .= sFields
33683146 , "_source" .= sSource]
3369−
3147+
3148+ where query' = case sFilter of
3149+ Nothing -> mquery
3150+ Just x -> Just . QueryBoolQuery $ mkBoolQuery (maybeToList mquery) [x] [] []
33703151
33713152instance ToJSON Source where
33723153 toJSON NoSource = toJSON False
33733154 toJSON (SourcePatterns patterns) = toJSON patterns
3374− toJSON (SourceIncludeExclude incl excl) = object [ "include" .= incl, "exclude" .= excl ]
3155+ toJSON (SourceIncludeExclude incl excl) = object [ "includes" .= incl, "excludes" .= excl ]
33753156
33763157instance ToJSON PatternOrPatterns where
33773158 toJSON (PopPattern pattern) = toJSON pattern
@@ -3480,7 +3261,7 @@ instance ToJSON SortSpec where
34803261 dsSortMode dsMissingSort dsNestedFilter)) =
34813262 object [dsSortFieldName .= omitNulls base] where
34823263 base = [ "order" .= dsSortOrder
3483− , "ignore_unmapped" .= dsIgnoreUnmapped
3264+ , "unmapped_type" .= dsIgnoreUnmapped
34843265 , "mode" .= dsSortMode
34853266 , "missing" .= dsMissingSort
34863267 , "nested_filter" .= dsNestedFilter ]
@@ -3887,7 +3668,7 @@ data NodeStats = NodeStats {
38873668 , nodeStatsHTTP :: NodeHTTPStats
38883669 , nodeStatsTransport :: NodeTransportStats
38893670 , nodeStatsFS :: NodeFSStats
3890− , nodeStatsNetwork :: NodeNetworkStats
3671+ , nodeStatsNetwork :: Maybe NodeNetworkStats
38913672 , nodeStatsThreadPool :: NodeThreadPoolsStats
38923673 , nodeStatsJVM :: NodeJVMStats
38933674 , nodeStatsProcess :: NodeProcessStats
@@ -3940,7 +3721,7 @@ data NodeDataPathStats = NodeDataPathStats {
39403721 , nodeDataPathFree :: Bytes
39413722 , nodeDataPathTotal :: Bytes
39423723 , nodeDataPathType :: Maybe Text
3943− , nodeDataPathDevice :: Text
3724+ , nodeDataPathDevice :: Maybe Text
39443725 , nodeDataPathMount :: Text
39453726 , nodeDataPathPath :: Text
39463727 } deriving (Eq, Show, Generic, Typeable)
@@ -3979,17 +3760,17 @@ data NodeThreadPoolsStats = NodeThreadPoolsStats {
39793760 , nodeThreadPoolsStatsGet :: NodeThreadPoolStats
39803761 , nodeThreadPoolsStatsManagement :: NodeThreadPoolStats
39813762 , nodeThreadPoolsStatsFetchShardStore :: Maybe NodeThreadPoolStats
3982− , nodeThreadPoolsStatsOptimize :: NodeThreadPoolStats
3763+ , nodeThreadPoolsStatsOptimize :: Maybe NodeThreadPoolStats
39833764 , nodeThreadPoolsStatsFlush :: NodeThreadPoolStats
39843765 , nodeThreadPoolsStatsSearch :: NodeThreadPoolStats
39853766 , nodeThreadPoolsStatsWarmer :: NodeThreadPoolStats
39863767 , nodeThreadPoolsStatsGeneric :: NodeThreadPoolStats
3987− , nodeThreadPoolsStatsSuggest :: NodeThreadPoolStats
3768+ , nodeThreadPoolsStatsSuggest :: Maybe NodeThreadPoolStats
39883769 , nodeThreadPoolsStatsRefresh :: NodeThreadPoolStats
39893770 , nodeThreadPoolsStatsIndex :: NodeThreadPoolStats
39903771 , nodeThreadPoolsStatsListener :: Maybe NodeThreadPoolStats
39913772 , nodeThreadPoolsStatsFetchShardStarted :: Maybe NodeThreadPoolStats
3992− , nodeThreadPoolsStatsPercolate :: NodeThreadPoolStats
3773+ , nodeThreadPoolsStatsPercolate :: Maybe NodeThreadPoolStats
39933774 } deriving (Eq, Show, Generic, Typeable)
39943775
39953776data NodeThreadPoolStats = NodeThreadPoolStats {
@@ -4040,34 +3821,26 @@ data JVMPoolStats = JVMPoolStats {
40403821 } deriving (Eq, Show, Generic, Typeable)
40413822
40423823data NodeProcessStats = NodeProcessStats {
4043− nodeProcessMemTotalVirtual :: Bytes
4044− , nodeProcessMemShare :: Bytes
4045− , nodeProcessMemResident :: Bytes
4046− , nodeProcessCPUTotal :: NominalDiffTime
4047− , nodeProcessCPUUser :: NominalDiffTime
4048− , nodeProcessCPUSys :: NominalDiffTime
4049− , nodeProcessCPUPercent :: Int
3824+ nodeProcessTimestamp :: UTCTime
40503825 , nodeProcessOpenFDs :: Int
4051− , nodeProcessTimestamp :: UTCTime
3826+ , nodeProcessMaxFDs :: Int
3827+ , nodeProcessCPUPercent :: Int
3828+ , nodeProcessCPUTotal :: NominalDiffTime
3829+ , nodeProcessMemTotalVirtual :: Bytes
40523830 } deriving (Eq, Show, Generic, Typeable)
40533831
40543832data NodeOSStats = NodeOSStats {
4055− nodeOSSwapFree :: Bytes
4056− , nodeOSSwapUsed :: Bytes
4057− , nodeOSMemActualUsed :: Bytes
4058− , nodeOSMemActualFree :: Bytes
4059− , nodeOSMemUsedPercent :: Int
3833+ nodeOSTimestamp :: UTCTime
3834+ , nodeOSCPUPercent :: Int
3835+ , nodeOSLoad :: Maybe LoadAvgs
3836+ , nodeOSMemTotal :: Bytes
3837+ , nodeOSMemFree :: Bytes
40603838 , nodeOSMemFreePercent :: Int
40613839 , nodeOSMemUsed :: Bytes
4062− , nodeOSMemFree :: Bytes
4063− , nodeOSCPUStolen :: Int
4064− , nodeOSCPUUsage :: Int
4065− , nodeOSCPUIdle :: Int
4066− , nodeOSCPUUser :: Int
4067− , nodeOSCPUSys :: Int
4068− , nodeOSLoad :: Maybe LoadAvgs
4069− , nodeOSUptime :: NominalDiffTime
4070− , nodeOSTimestamp :: UTCTime
3840+ , nodeOSMemUsedPercent :: Int
3841+ , nodeOSSwapTotal :: Bytes
3842+ , nodeOSSwapFree :: Bytes
3843+ , nodeOSSwapUsed :: Bytes
40713844 } deriving (Eq, Show, Generic, Typeable)
40723845
40733846data LoadAvgs = LoadAvgs {
@@ -4084,9 +3857,9 @@ data NodeIndicesStats = NodeIndicesStats {
40843857 , nodeIndicesStatsQueryCacheHits :: Maybe Int
40853858 , nodeIndicesStatsQueryCacheEvictions :: Maybe Int
40863859 , nodeIndicesStatsQueryCacheSize :: Maybe Bytes
4087− , nodeIndicesStatsSuggestCurrent :: Int
4088− , nodeIndicesStatsSuggestTime :: NominalDiffTime
4089− , nodeIndicesStatsSuggestTotal :: Int
3860+ , nodeIndicesStatsSuggestCurrent :: Maybe Int
3861+ , nodeIndicesStatsSuggestTime :: Maybe NominalDiffTime
3862+ , nodeIndicesStatsSuggestTotal :: Maybe Int
40903863 , nodeIndicesStatsTranslogSize :: Bytes
40913864 , nodeIndicesStatsTranslogOps :: Int
40923865 , nodeIndicesStatsSegFixedBitSetMemory :: Maybe Bytes
@@ -4096,16 +3869,13 @@ data NodeIndicesStats = NodeIndicesStats {
40963869 , nodeIndicesStatsSegMemory :: Bytes
40973870 , nodeIndicesStatsSegCount :: Int
40983871 , nodeIndicesStatsCompletionSize :: Bytes
4099− , nodeIndicesStatsPercolateQueries :: Int
4100− , nodeIndicesStatsPercolateMemory :: Bytes
4101− , nodeIndicesStatsPercolateCurrent :: Int
4102− , nodeIndicesStatsPercolateTime :: NominalDiffTime
4103− , nodeIndicesStatsPercolateTotal :: Int
3872+ , nodeIndicesStatsPercolateQueries :: Maybe Int
3873+ , nodeIndicesStatsPercolateMemory :: Maybe Bytes
3874+ , nodeIndicesStatsPercolateCurrent :: Maybe Int
3875+ , nodeIndicesStatsPercolateTime :: Maybe NominalDiffTime
3876+ , nodeIndicesStatsPercolateTotal :: Maybe Int
41043877 , nodeIndicesStatsFieldDataEvictions :: Int
41053878 , nodeIndicesStatsFieldDataMemory :: Bytes
4106− , nodeIndicesStatsIDCacheMemory :: Bytes
4107− , nodeIndicesStatsFilterCacheEvictions :: Int
4108− , nodeIndicesStatsFilterCacheMemory :: Bytes
41093879 , nodeIndicesStatsWarmerTotalTime :: NominalDiffTime
41103880 , nodeIndicesStatsWarmerTotal :: Int
41113881 , nodeIndicesStatsWarmerCurrent :: Int
@@ -4163,7 +3933,7 @@ newtype PluginName = PluginName { pluginName :: Text }
41633933 deriving (Eq, Ord, Generic, Show, Typeable, FromJSON)
41643934
41653935data NodeInfo = NodeInfo {
4166− nodeInfoHTTPAddress :: EsAddress
3936+ nodeInfoHTTPAddress :: Maybe EsAddress
41673937 , nodeInfoBuild :: BuildHash
41683938 , nodeInfoESVersion :: VersionNumber
41693939 , nodeInfoIP :: Server
@@ -4174,7 +3944,7 @@ data NodeInfo = NodeInfo {
41743944 , nodeInfoPlugins :: [NodePluginInfo]
41753945 , nodeInfoHTTP :: NodeHTTPInfo
41763946 , nodeInfoTransport :: NodeTransportInfo
4177− , nodeInfoNetwork :: NodeNetworkInfo
3947+ , nodeInfoNetwork :: Maybe NodeNetworkInfo
41783948 , nodeInfoThreadPool :: NodeThreadPoolsInfo
41793949 , nodeInfoJVM :: NodeJVMInfo
41803950 , nodeInfoProcess :: NodeProcessInfo
@@ -4206,7 +3976,7 @@ data NodeTransportInfo = NodeTransportInfo {
42063976
42073977data BoundTransportAddress = BoundTransportAddress {
42083978 publishAddress :: EsAddress
4209− , boundAddress :: EsAddress
3979+ , boundAddress :: [EsAddress]
42103980 } deriving (Eq, Show, Generic, Typeable)
42113981
42123982data NodeNetworkInfo = NodeNetworkInfo {
@@ -4229,15 +3999,15 @@ data NodeNetworkInterface = NodeNetworkInterface {
42293999data NodeThreadPoolsInfo = NodeThreadPoolsInfo {
42304000 nodeThreadPoolsRefresh :: NodeThreadPoolInfo
42314001 , nodeThreadPoolsManagement :: NodeThreadPoolInfo
4232− , nodeThreadPoolsPercolate :: NodeThreadPoolInfo
4002+ , nodeThreadPoolsPercolate :: Maybe NodeThreadPoolInfo
42334003 , nodeThreadPoolsListener :: Maybe NodeThreadPoolInfo
42344004 , nodeThreadPoolsFetchShardStarted :: Maybe NodeThreadPoolInfo
42354005 , nodeThreadPoolsSearch :: NodeThreadPoolInfo
42364006 , nodeThreadPoolsFlush :: NodeThreadPoolInfo
42374007 , nodeThreadPoolsWarmer :: NodeThreadPoolInfo
4238− , nodeThreadPoolsOptimize :: NodeThreadPoolInfo
4008+ , nodeThreadPoolsOptimize :: Maybe NodeThreadPoolInfo
42394009 , nodeThreadPoolsBulk :: NodeThreadPoolInfo
4240− , nodeThreadPoolsSuggest :: NodeThreadPoolInfo
4010+ , nodeThreadPoolsSuggest :: Maybe NodeThreadPoolInfo
42414011 , nodeThreadPoolsMerge :: NodeThreadPoolInfo
42424012 , nodeThreadPoolsSnapshot :: NodeThreadPoolInfo
42434013 , nodeThreadPoolsGet :: NodeThreadPoolInfo
@@ -4300,11 +4070,12 @@ newtype PID = PID {
43004070 } deriving (Eq, Show, Generic, Typeable, FromJSON)
43014071
43024072data NodeOSInfo = NodeOSInfo {
4303− nodeOSSwap :: Bytes
4304− , nodeOSMem :: Bytes
4305− , nodeOSCPUInfo :: CPUInfo
4073+ nodeOSRefreshInterval :: NominalDiffTime
4074+ , nodeOSName :: Text
4075+ , nodeOSArch :: Text
4076+ , nodeOSVersion :: VersionNumber
43064077 , nodeOSAvailableProcessors :: Int
4307− , nodeOSRefreshInterval :: NominalDiffTime
4078+ , nodeOSAllocatedProcessors :: Int
43084079 } deriving (Eq, Show, Generic, Typeable)
43094080
43104081data CPUInfo = CPUInfo {
@@ -4320,7 +4091,7 @@ data CPUInfo = CPUInfo {
43204091data NodeProcessInfo = NodeProcessInfo {
43214092 nodeProcessMLockAll :: Bool
43224093 -- ^ See <https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration.html>
4323− , nodeProcessMaxFileDescriptors :: Int
4094+ , nodeProcessMaxFileDescriptors :: Maybe Int
43244095 , nodeProcessId :: PID
43254096 , nodeProcessRefreshInterval :: NominalDiffTime
43264097 } deriving (Eq, Show, Generic, Typeable)
@@ -4725,7 +4496,7 @@ instance FromJSON NodeDataPathStats where
47254496 <*> o .: "free_in_bytes"
47264497 <*> o .: "total_in_bytes"
47274498 <*> o .:? "type"
4728− <*> o .: "dev"
4499+ <*> o .:? "dev"
47294500 <*> o .: "mount"
47304501 <*> o .: "path"
47314502
@@ -4772,21 +4543,21 @@ instance FromJSON NodeThreadPoolsStats where
47724543 where
47734544 parse o = NodeThreadPoolsStats <$> o .: "snapshot"
47744545 <*> o .: "bulk"
4775− <*> o .: "merge"
4546+ <*> o .: "force_merge"
47764547 <*> o .: "get"
47774548 <*> o .: "management"
47784549 <*> o .:? "fetch_shard_store"
4779− <*> o .: "optimize"
4550+ <*> o .:? "optimize"
47804551 <*> o .: "flush"
47814552 <*> o .: "search"
47824553 <*> o .: "warmer"
47834554 <*> o .: "generic"
4784− <*> o .: "suggest"
4555+ <*> o .:? "suggest"
47854556 <*> o .: "refresh"
47864557 <*> o .: "index"
47874558 <*> o .:? "listener"
47884559 <*> o .:? "fetch_shard_started"
4789− <*> o .: "percolate"
4560+ <*> o .:? "percolate"
47904561instance FromJSON NodeThreadPoolStats where
47914562 parseJSON = withObject "NodeThreadPoolStats" parse
47924563 where
@@ -4859,15 +4630,12 @@ instance FromJSON NodeProcessStats where
48594630 parse o = do
48604631 mem <- o .: "mem"
48614632 cpu <- o .: "cpu"
4862− NodeProcessStats <$> mem .: "total_virtual_in_bytes"
4863− <*> mem .: "share_in_bytes"
4864− <*> mem .: "resident_in_bytes"
4865− <*> (unMS <$> cpu .: "total_in_millis")
4866− <*> (unMS <$> cpu .: "user_in_millis")
4867− <*> (unMS <$> cpu .: "sys_in_millis")
4868− <*> cpu .: "percent"
4633+ NodeProcessStats <$> (posixMS <$> o .: "timestamp")
48694634 <*> o .: "open_file_descriptors"
4870− <*> (posixMS <$> o .: "timestamp")
4635+ <*> o .: "max_file_descriptors"
4636+ <*> cpu .: "percent"
4637+ <*> (unMS <$> cpu .: "total_in_millis")
4638+ <*> mem .: "total_virtual_in_bytes"
48714639
48724640instance FromJSON NodeOSStats where
48734641 parseJSON = withObject "NodeOSStats" parse
@@ -4877,22 +4645,17 @@ instance FromJSON NodeOSStats where
48774645 mem <- o .: "mem"
48784646 cpu <- o .: "cpu"
48794647 load <- o .:? "load_average"
4880− NodeOSStats <$> swap .: "free_in_bytes"
4881− <*> swap .: "used_in_bytes"
4882− <*> mem .: "actual_used_in_bytes"
4883− <*> mem .: "actual_free_in_bytes"
4884− <*> mem .: "used_percent"
4648+ NodeOSStats <$> (posixMS <$> o .: "timestamp")
4649+ <*> cpu .: "percent"
4650+ <*> pure load
4651+ <*> mem .: "total_in_bytes"
4652+ <*> mem .: "free_in_bytes"
48854653 <*> mem .: "free_percent"
48864654 <*> mem .: "used_in_bytes"
4887− <*> mem .: "free_in_bytes"
4888− <*> cpu .: "stolen"
4889− <*> cpu .: "usage"
4890− <*> cpu .: "idle"
4891− <*> cpu .: "user"
4892− <*> cpu .: "sys"
4893− <*> pure load
4894− <*> (unMS <$> o .: "uptime_in_millis")
4895− <*> (posixMS <$> o .: "timestamp")
4655+ <*> mem .: "used_percent"
4656+ <*> swap .: "total_in_bytes"
4657+ <*> swap .: "free_in_bytes"
4658+ <*> swap .: "used_in_bytes"
48964659
48974660instance FromJSON LoadAvgs where
48984661 parseJSON = withArray "LoadAvgs" parse
@@ -4912,14 +4675,12 @@ instance FromJSON NodeIndicesStats where
49124675 Nothing -> pure Nothing
49134676 mRecovery <- o .:? "recovery"
49144677 mQueryCache <- o .:? "query_cache"
4915− suggest <- o .: "suggest"
4678+ mSuggest <- o .:? "suggest"
49164679 translog <- o .: "translog"
49174680 segments <- o .: "segments"
49184681 completion <- o .: "completion"
4919− percolate <- o .: "percolate"
4682+ mPercolate <- o .:? "percolate"
49204683 fielddata <- o .: "fielddata"
4921− idCache <- o .: "id_cache"
4922− filterCache <- o .: "filter_cache"
49234684 warmer <- o .: "warmer"
49244685 flush <- o .: "flush"
49254686 refresh <- o .: "refresh"
@@ -4936,9 +4697,9 @@ instance FromJSON NodeIndicesStats where
49364697 <*> mQueryCache .:: "hit_count"
49374698 <*> mQueryCache .:: "evictions"
49384699 <*> mQueryCache .:: "memory_size_in_bytes"
4939− <*> suggest .: "current"
4940− <*> (unMS <$> suggest .: "time_in_millis")
4941− <*> suggest .: "total"
4700+ <*> mSuggest .:: "current"
4701+ <*> (fmap unMS <$> mSuggest .:: "time_in_millis")
4702+ <*> mSuggest .:: "total"
49424703 <*> translog .: "size_in_bytes"
49434704 <*> translog .: "operations"
49444705 <*> segments .:? "fixed_bit_set_memory_in_bytes"
@@ -4948,16 +4709,13 @@ instance FromJSON NodeIndicesStats where
49484709 <*> segments .: "memory_in_bytes"
49494710 <*> segments .: "count"
49504711 <*> completion .: "size_in_bytes"
4951− <*> percolate .: "queries"
4952− <*> percolate .: "memory_size_in_bytes"
4953− <*> percolate .: "current"
4954− <*> (unMS <$> percolate .: "time_in_millis")
4955− <*> percolate .: "total"
4712+ <*> mPercolate .:: "queries"
4713+ <*> mPercolate .:: "memory_size_in_bytes"
4714+ <*> mPercolate .:: "current"
4715+ <*> (fmap unMS <$> mPercolate .:: "time_in_millis")
4716+ <*> mPercolate .:: "total"
49564717 <*> fielddata .: "evictions"
49574718 <*> fielddata .: "memory_size_in_bytes"
4958− <*> idCache .: "memory_size_in_bytes"
4959− <*> filterCache .: "evictions"
4960− <*> filterCache .: "memory_size_in_bytes"
49614719 <*> (unMS <$> warmer .: "total_time_in_millis")
49624720 <*> warmer .: "total"
49634721 <*> warmer .: "current"
@@ -5015,7 +4773,7 @@ parseNodeStats fnid o = do
50154773 <*> o .: "http"
50164774 <*> o .: "transport"
50174775 <*> o .: "fs"
5018− <*> o .: "network"
4776+ <*> o .:? "network"
50194777 <*> o .: "thread_pool"
50204778 <*> o .: "jvm"
50214779 <*> o .: "process"
@@ -5024,8 +4782,8 @@ parseNodeStats fnid o = do
50244782
50254783parseNodeInfo :: FullNodeId -> Object -> Parser NodeInfo
50264784parseNodeInfo nid o =
5027− NodeInfo <$> o .: "http_address"
5028− <*> o .: "build"
4785+ NodeInfo <$> o .:? "http_address"
4786+ <*> o .: "build_hash"
50294787 <*> o .: "version"
50304788 <*> o .: "ip"
50314789 <*> o .: "host"
@@ -5035,7 +4793,7 @@ parseNodeInfo nid o =
50354793 <*> o .: "plugins"
50364794 <*> o .: "http"
50374795 <*> o .: "transport"
5038− <*> o .: "network"
4796+ <*> o .:? "network"
50394797 <*> o .: "thread_pool"
50404798 <*> o .: "jvm"
50414799 <*> o .: "process"
@@ -5067,13 +4825,12 @@ instance FromJSON NodeOSInfo where
50674825 parseJSON = withObject "NodeOSInfo" parse
50684826 where
50694827 parse o = do
5070− swap <- o .: "swap"
5071− mem <- o .: "mem"
5072− NodeOSInfo <$> swap .: "total_in_bytes"
5073− <*> mem .: "total_in_bytes"
5074− <*> o .: "cpu"
4828+ NodeOSInfo <$> (unMS <$> o .: "refresh_interval_in_millis")
4829+ <*> o .: "name"
4830+ <*> o .: "arch"
4831+ <*> o .: "version"
50754832 <*> o .: "available_processors"
5076− <*> (unMS <$> o .: "refresh_interval_in_millis")
4833+ <*> o .: "allocated_processors"
50774834
50784835
50794836instance FromJSON CPUInfo where
@@ -5091,7 +4848,7 @@ instance FromJSON NodeProcessInfo where
50914848 parseJSON = withObject "NodeProcessInfo" parse
50924849 where
50934850 parse o = NodeProcessInfo <$> o .: "mlockall"
5094− <*> o .: "max_file_descriptors"
4851+ <*> o .:? "max_file_descriptors"
50954852 <*> o .: "id"
50964853 <*> (unMS <$> o .: "refresh_interval_in_millis")
50974854
@@ -5127,16 +4884,16 @@ instance FromJSON NodeThreadPoolsInfo where
51274884 where
51284885 parse o = NodeThreadPoolsInfo <$> o .: "refresh"
51294886 <*> o .: "management"
5130− <*> o .: "percolate"
4887+ <*> o .:? "percolate"
51314888 <*> o .:? "listener"
51324889 <*> o .:? "fetch_shard_started"
51334890 <*> o .: "search"
51344891 <*> o .: "flush"
51354892 <*> o .: "warmer"
5136− <*> o .: "optimize"
4893+ <*> o .:? "optimize"
51374894 <*> o .: "bulk"
5138− <*> o .: "suggest"
5139− <*> o .: "merge"
4895+ <*> o .:? "suggest"
4896+ <*> o .: "force_merge"
51404897 <*> o .: "snapshot"
51414898 <*> o .: "get"
51424899 <*> o .:? "fetch_shard_store"
stack-8.0.yamldeleted−15
@@ -1,15 +0,0 @@
1−flags: {}
2−packages:
3−- '.'
4−extra-deps:
5−- quickcheck-properties-0.1
6−
7−# - http-client-0.5.0
8−# - fail-4.9.0.0
9−# - http-types-0.9
10−# - attoparsec-0.13.0.1
11−# - doctest-0.10.1
12−# - semigroups-0.18.0.1
13−# - uri-bytestring-0.1.9
14−# - temporary-resourcet-0.1.0.0
15−resolver: nightly-2016-08-20
stack.yaml+15−1
@@ -1 +1,15 @@
1−stack-7.10.yaml
1+flags: {}
2+packages:
3+- '.'
4+extra-deps:
5+- quickcheck-properties-0.1
6+
7+# - http-client-0.5.0
8+# - fail-4.9.0.0
9+# - http-types-0.9
10+# - attoparsec-0.13.0.1
11+# - doctest-0.10.1
12+# - semigroups-0.18.0.1
13+# - uri-bytestring-0.1.9
14+# - temporary-resourcet-0.1.0.0
15+resolver: nightly-2016-08-20
tests/tests.hs+35−259
@@ -47,7 +47,7 @@ import qualified Network.HTTP.Types.Status as NHTS
4747import qualified Network.URI as URI
4848import Prelude hiding (filter)
4949import System.IO.Temp
50−import System.Posix.Files
50+import System.PosixCompat.Files
5151import Test.Hspec
5252import Test.QuickCheck.Property.Monoid (T (..), eq, prop_Monoid)
5353
@@ -100,6 +100,9 @@ es16 = Vers.Version [1, 6, 0] []
100100es20 :: Vers.Version
101101es20 = Vers.Version [2, 0, 0] []
102102
103+es50 :: Vers.Version
104+es50 = Vers.Version [5, 0, 0] []
105+
103106getServerVersion :: IO (Maybe Vers.Version)
104107getServerVersion = fmap extractVersion <$> withTestEnv getStatus
105108 where
@@ -179,13 +182,16 @@ data ParentMapping = ParentMapping deriving (Eq, Show)
179182instance ToJSON ParentMapping where
180183 toJSON ParentMapping =
181184 object ["properties" .=
182− object [ "user" .= object ["type" .= ("string" :: Text)]
185+ object [ "user" .= object ["type" .= ("string" :: Text)
186+ , "fielddata" .= True
187+ ]
183188 -- Serializing the date as a date is breaking other tests, mysteriously.
184189 -- , "postDate" .= object [ "type" .= ("date" :: Text)
185190 -- , "format" .= ("YYYY-MM-dd`T`HH:mm:ss.SSSZZ" :: Text)]
186191 , "message" .= object ["type" .= ("string" :: Text)]
187192 , "age" .= object ["type" .= ("integer" :: Text)]
188193 , "location" .= object ["type" .= ("geo_point" :: Text)]
194+ , "extra" .= object ["type" .= ("keyword" :: Text)]
189195 ]]
190196
191197data ChildMapping = ChildMapping deriving (Eq, Show)
@@ -194,28 +200,35 @@ instance ToJSON ChildMapping where
194200 toJSON ChildMapping =
195201 object ["_parent" .= object ["type" .= ("parent" :: Text)]
196202 , "properties" .=
197− object [ "user" .= object ["type" .= ("string" :: Text)]
203+ object [ "user" .= object ["type" .= ("string" :: Text)
204+ , "fielddata" .= True
205+ ]
198206 -- Serializing the date as a date is breaking other tests, mysteriously.
199207 -- , "postDate" .= object [ "type" .= ("date" :: Text)
200208 -- , "format" .= ("YYYY-MM-dd`T`HH:mm:ss.SSSZZ" :: Text)]
201209 , "message" .= object ["type" .= ("string" :: Text)]
202210 , "age" .= object ["type" .= ("integer" :: Text)]
203211 , "location" .= object ["type" .= ("geo_point" :: Text)]
212+ , "extra" .= object ["type" .= ("keyword" :: Text)]
204213 ]]
205214
206215data TweetMapping = TweetMapping deriving (Eq, Show)
207216
208217instance ToJSON TweetMapping where
209218 toJSON TweetMapping =
210− object ["properties" .=
211− object [ "user" .= object ["type" .= ("string" :: Text)]
212− -- Serializing the date as a date is breaking other tests, mysteriously.
213− -- , "postDate" .= object [ "type" .= ("date" :: Text)
214− -- , "format" .= ("YYYY-MM-dd`T`HH:mm:ss.SSSZZ" :: Text)]
215− , "message" .= object ["type" .= ("string" :: Text)]
216− , "age" .= object ["type" .= ("integer" :: Text)]
217− , "location" .= object ["type" .= ("geo_point" :: Text)]
218− ]]
219+ object ["tweet" .=
220+ object ["properties" .=
221+ object [ "user" .= object [ "type" .= ("string" :: Text)
222+ , "fielddata" .= True
223+ ]
224+ -- Serializing the date as a date is breaking other tests, mysteriously.
225+ -- , "postDate" .= object [ "type" .= ("date" :: Text)
226+ -- , "format" .= ("YYYY-MM-dd`T`HH:mm:ss.SSSZZ" :: Text)]
227+ , "message" .= object ["type" .= ("string" :: Text)]
228+ , "age" .= object ["type" .= ("integer" :: Text)]
229+ , "location" .= object ["type" .= ("geo_point" :: Text)]
230+ , "extra" .= object ["type" .= ("keyword" :: Text)]
231+ ]]]
219232
220233exampleTweet :: Tweet
221234exampleTweet = Tweet { user = "bitemyapp"
@@ -543,7 +556,6 @@ instance ApproxEq HasChildQuery
543556instance ApproxEq FuzzyQuery
544557instance ApproxEq FuzzyLikeFieldQuery
545558instance ApproxEq FuzzyLikeThisQuery
546−instance ApproxEq FilteredQuery
547559instance ApproxEq DisMaxQuery
548560instance ApproxEq CommonTermsQuery
549561instance ApproxEq CommonMinimumMatch
@@ -577,7 +589,7 @@ instance ApproxEq BoolMatch
577589instance ApproxEq MultiMatchQuery
578590instance ApproxEq IndexSettings
579591instance ApproxEq AllocationPolicy
580−instance ApproxEq Char
592+instance ApproxEq Char where (=~) = (==)
581593instance ApproxEq Vers.Version where
582594 (=~) = (==)
583595instance (ApproxEq a, Show a) => ApproxEq [a] where
@@ -722,10 +734,8 @@ instance Arbitrary Query where
722734 , QueryBoolQuery <$> arbitrary
723735 , QueryBoostingQuery <$> arbitrary
724736 , QueryCommonTermsQuery <$> arbitrary
725− , ConstantScoreFilter <$> arbitrary <*> arbitrary
726737 , ConstantScoreQuery <$> arbitrary <*> arbitrary
727738 , QueryDisMaxQuery <$> arbitrary
728− , QueryFilteredQuery <$> arbitrary
729739 , QueryFuzzyLikeThisQuery <$> arbitrary
730740 , QueryFuzzyLikeFieldQuery <$> arbitrary
731741 , QueryFuzzyQuery <$> arbitrary
@@ -746,24 +756,7 @@ instance Arbitrary Query where
746756 shrink = genericShrink
747757
748758instance Arbitrary Filter where
749− arbitrary = reduceSize $ oneof [ AndFilter <$> arbitrary <*> arbitrary
750− , OrFilter <$> arbitrary <*> arbitrary
751− , NotFilter <$> arbitrary <*> arbitrary
752− , pure IdentityFilter
753− , BoolFilter <$> arbitrary
754− , ExistsFilter <$> arbitrary
755− , GeoBoundingBoxFilter <$> arbitrary
756− , GeoDistanceFilter <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
757− , GeoDistanceRangeFilter <$> arbitrary <*> arbitrary
758− , GeoPolygonFilter <$> arbitrary <*> arbitrary
759− , IdsFilter <$> arbitrary <*> arbitrary
760− , LimitFilter <$> arbitrary
761− , MissingFilter <$> arbitrary <*> arbitrary <*> arbitrary
762− , PrefixFilter <$> arbitrary <*> arbitrary <*> arbitrary
763− , QueryFilter <$> arbitrary <*> arbitrary
764− , RangeFilter <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
765− , RegexpFilter <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
766− , TermFilter <$> arbitrary <*> arbitrary]
759+ arbitrary = Filter <$> arbitrary
767760 shrink = genericShrink
768761
769762instance Arbitrary ReplicaBounds where
@@ -855,7 +848,6 @@ $(derive makeArbitrary ''HasChildQuery)
855848$(derive makeArbitrary ''FuzzyQuery)
856849$(derive makeArbitrary ''FuzzyLikeFieldQuery)
857850$(derive makeArbitrary ''FuzzyLikeThisQuery)
858−$(derive makeArbitrary ''FilteredQuery)
859851$(derive makeArbitrary ''DisMaxQuery)
860852$(derive makeArbitrary ''CommonTermsQuery)
861853$(derive makeArbitrary ''DistanceRange)
@@ -1028,7 +1020,7 @@ main = hspec $ do
10281020 it "returns document for term query and identity filter" $ withTestEnv $ do
10291021 _ <- insertData
10301022 let query = TermQuery (Term "user" "bitemyapp") Nothing
1031− let filter = IdentityFilter <&&> IdentityFilter
1023+ let filter = Filter $ MatchAllQuery Nothing
10321024 let search = mkSearch (Just query) (Just filter)
10331025 myTweet <- searchTweet search
10341026 liftIO $
@@ -1038,26 +1030,16 @@ main = hspec $ do
10381030 _ <- insertData
10391031 let query = TermsQuery "user" ("bitemyapp" :| [])
10401032 let cfQuery = ConstantScoreQuery query (Boost 1.0)
1041− let filter = IdentityFilter
1033+ let filter = Filter $ MatchAllQuery Nothing
10421034 let search = mkSearch (Just cfQuery) (Just filter)
10431035 myTweet <- searchTweet search
10441036 liftIO $
10451037 myTweet `shouldBe` Right exampleTweet
1046− it "handles constant score filters" $ withTestEnv $ do
1047− _ <- insertData
1048− let query = TermsQuery "user" ("bitemyapp" :| [])
1049− let cfFilter = ConstantScoreFilter IdentityFilter (Boost 1.0)
1050− let boolQuery = mkBoolQuery [query, cfFilter] [] []
1051− let search = mkSearch (Just (QueryBoolQuery boolQuery)) Nothing
1052− myTweet <- searchTweet search
1053− liftIO $
1054− myTweet `shouldBe` Right exampleTweet
1055−
10561038
10571039 it "returns document for terms query and identity filter" $ withTestEnv $ do
10581040 _ <- insertData
10591041 let query = TermsQuery "user" ("bitemyapp" :| [])
1060− let filter = IdentityFilter <&&> IdentityFilter
1042+ let filter = Filter $ MatchAllQuery Nothing
10611043 let search = mkSearch (Just query) (Just filter)
10621044 myTweet <- searchTweet search
10631045 liftIO $
@@ -1085,7 +1067,7 @@ main = hspec $ do
10851067 let innerQuery = QueryMatchQuery $
10861068 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
10871069 let query = QueryBoolQuery $
1088− mkBoolQuery [innerQuery] [] []
1070+ mkBoolQuery [innerQuery] [] [] []
10891071 let search = mkSearch (Just query) Nothing
10901072 myTweet <- searchTweet search
10911073 liftIO $
@@ -1120,173 +1102,13 @@ main = hspec $ do
11201102 _ <- insertOther
11211103 let sortSpec = DefaultSortSpec $ mkSort (FieldName "age") Ascending
11221104 let search = Search Nothing
1123− (Just IdentityFilter) (Just [sortSpec]) Nothing Nothing
1105+ Nothing (Just [sortSpec]) Nothing Nothing
11241106 False (From 0) (Size 10) SearchTypeQueryThenFetch Nothing Nothing
11251107 result <- searchTweets search
11261108 let myTweet = grabFirst result
11271109 liftIO $
11281110 myTweet `shouldBe` Right otherTweet
11291111
1130−
1131− describe "filtering API" $ do
1132− it "returns document for composed boolmatch and identity" $ withTestEnv $ do
1133− _ <- insertData
1134− let queryFilter = BoolFilter (MustMatch (Term "user" "bitemyapp") False)
1135− <&&> IdentityFilter
1136− let search = mkSearch Nothing (Just queryFilter)
1137− myTweet <- searchTweet search
1138− liftIO $
1139− myTweet `shouldBe` Right exampleTweet
1140−
1141− it "returns document for term filter" $ withTestEnv $ do
1142− _ <- insertData
1143− let termFilter = TermFilter (Term "user" "bitemyapp") False
1144− let search = mkSearch Nothing (Just termFilter)
1145− myTweet <- searchTweet search
1146− liftIO $
1147− myTweet `shouldBe` Right exampleTweet
1148−
1149− it "returns document for existential filter" $ withTestEnv $ do
1150− _ <- insertData
1151− let search = mkSearch Nothing (Just (ExistsFilter (FieldName "user")))
1152− myTweet <- searchTweet search
1153− liftIO $
1154− myTweet `shouldBe` Right exampleTweet
1155−
1156− it "returns document for geo boundingbox filter" $ withTestEnv $ do
1157− _ <- insertData
1158− let box = GeoBoundingBox (LatLon 40.73 (-74.1)) (LatLon 40.10 (-71.12))
1159− let bbConstraint = GeoBoundingBoxConstraint (FieldName "tweet.location") box False GeoFilterMemory
1160− let geoFilter = GeoBoundingBoxFilter bbConstraint
1161− let search = mkSearch Nothing (Just geoFilter)
1162− myTweet <- searchTweet search
1163− liftIO $
1164− myTweet `shouldBe` Right exampleTweet
1165−
1166− it "doesn't return document for nonsensical boundingbox filter" $ withTestEnv $ do
1167− _ <- insertData
1168− let box = GeoBoundingBox (LatLon 0.73 (-4.1)) (LatLon 0.10 (-1.12))
1169− let bbConstraint = GeoBoundingBoxConstraint (FieldName "tweet.location") box False GeoFilterMemory
1170− let geoFilter = GeoBoundingBoxFilter bbConstraint
1171− let search = mkSearch Nothing (Just geoFilter)
1172− searchExpectNoResults search
1173−
1174− it "returns document for geo distance filter" $ withTestEnv $ do
1175− _ <- insertData
1176− let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
1177− let distance = Distance 10.0 Miles
1178− let optimizeBbox = OptimizeGeoFilterType GeoFilterMemory
1179− let geoFilter = GeoDistanceFilter geoPoint distance SloppyArc optimizeBbox False
1180− let search = mkSearch Nothing (Just geoFilter)
1181− myTweet <- searchTweet search
1182− liftIO $
1183− myTweet `shouldBe` Right exampleTweet
1184−
1185− it "returns document for geo distance range filter" $ withTestEnv $ do
1186− _ <- insertData
1187− let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
1188− let distanceRange = DistanceRange (Distance 0.0 Miles) (Distance 10.0 Miles)
1189− let geoFilter = GeoDistanceRangeFilter geoPoint distanceRange
1190− let search = mkSearch Nothing (Just geoFilter)
1191− myTweet <- searchTweet search
1192− liftIO $
1193− myTweet `shouldBe` Right exampleTweet
1194−
1195− it "doesn't return document for wild geo distance range filter" $ withTestEnv $ do
1196− _ <- insertData
1197− let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
1198− let distanceRange = DistanceRange (Distance 100.0 Miles) (Distance 1000.0 Miles)
1199− let geoFilter = GeoDistanceRangeFilter geoPoint distanceRange
1200− let search = mkSearch Nothing (Just geoFilter)
1201− searchExpectNoResults search
1202−
1203− it "returns document for geo polygon filter" $ withTestEnv $ do
1204− _ <- insertData
1205− let points = [LatLon 40.0 (-70.00),
1206− LatLon 40.0 (-72.00),
1207− LatLon 41.0 (-70.00),
1208− LatLon 41.0 (-72.00)]
1209− let geoFilter = GeoPolygonFilter (FieldName "tweet.location") points
1210− let search = mkSearch Nothing (Just geoFilter)
1211− myTweet <- searchTweet search
1212− liftIO $
1213− myTweet `shouldBe` Right exampleTweet
1214−
1215− it "doesn't return document for bad geo polygon filter" $ withTestEnv $ do
1216− _ <- insertData
1217− let points = [LatLon 40.0 (-70.00),
1218− LatLon 40.0 (-71.00),
1219− LatLon 41.0 (-70.00),
1220− LatLon 41.0 (-71.00)]
1221− let geoFilter = GeoPolygonFilter (FieldName "tweet.location") points
1222− let search = mkSearch Nothing (Just geoFilter)
1223− searchExpectNoResults search
1224−
1225− it "returns document for ids filter" $ withTestEnv $ do
1226− _ <- insertData
1227− let filter = IdsFilter (MappingName "tweet") [DocId "1"]
1228− let search = mkSearch Nothing (Just filter)
1229− myTweet <- searchTweet search
1230− liftIO $
1231− myTweet `shouldBe` Right exampleTweet
1232−
1233− it "returns document for Double range filter" $ withTestEnv $ do
1234− _ <- insertData
1235− let filter = RangeFilter (FieldName "age")
1236− (RangeDoubleGtLt (GreaterThan 1000.0) (LessThan 100000.0))
1237− RangeExecutionIndex False
1238− let search = mkSearch Nothing (Just filter)
1239− myTweet <- searchTweet search
1240− liftIO $
1241− myTweet `shouldBe` Right exampleTweet
1242−
1243− it "returns document for UTCTime date filter" $ withTestEnv $ do
1244− _ <- insertData
1245− let filter = RangeFilter (FieldName "postDate")
1246− (RangeDateGtLt
1247− (GreaterThanD (UTCTime
1248− (ModifiedJulianDay 54000)
1249− (secondsToDiffTime 0)))
1250− (LessThanD (UTCTime
1251− (ModifiedJulianDay 55000)
1252− (secondsToDiffTime 11))))
1253− RangeExecutionIndex False
1254− let search = mkSearch Nothing (Just filter)
1255− myTweet <- searchTweet search
1256− liftIO $
1257− myTweet `shouldBe` Right exampleTweet
1258−
1259− it "returns document for regexp filter" $ withTestEnv $ do
1260− _ <- insertData
1261− let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
1262− AllRegexpFlags (CacheName "test") False (CacheKey "key")
1263− let search = mkSearch Nothing (Just filter)
1264− myTweet <- searchTweet search
1265− liftIO $
1266− myTweet `shouldBe` Right exampleTweet
1267−
1268− it "doesn't return document for non-matching regexp filter" $ withTestEnv $ do
1269− _ <- insertData
1270− let filter = RegexpFilter (FieldName "user")
1271− (Regexp "boy") AllRegexpFlags
1272− (CacheName "test") False (CacheKey "key")
1273− let search = mkSearch Nothing (Just filter)
1274− searchExpectNoResults search
1275−
1276− it "returns document for query filter, uncached" $ withTestEnv $ do
1277− _ <- insertData
1278− let filter = QueryFilter (TermQuery (Term "user" "bitemyapp") Nothing) True
1279− search = mkSearch Nothing (Just filter)
1280− myTweet <- searchTweet search
1281− liftIO $ myTweet `shouldBe` Right exampleTweet
1282−
1283− it "returns document for query filter, cached" $ withTestEnv $ do
1284− _ <- insertData
1285− let filter = QueryFilter (TermQuery (Term "user" "bitemyapp") Nothing) False
1286− search = mkSearch Nothing (Just filter)
1287− myTweet <- searchTweet search
1288− liftIO $ myTweet `shouldBe` Right exampleTweet
1289−
12901112 describe "Aggregation API" $ do
12911113 it "returns term aggregation results" $ withTestEnv $ do
12921114 _ <- insertData
@@ -1340,18 +1162,6 @@ main = hspec $ do
13401162 , docCountPair "bogus_count" 0
13411163 ]))
13421164
1343− it "can execute filter aggregations" $ withTestEnv $ do
1344− _ <- insertData
1345− _ <- insertOther
1346− let ags = mkAggregations "bitemyapps" (FilterAgg (FilterAggregation (TermFilter (Term "user" "bitemyapp") defaultCache) Nothing)) <>
1347− mkAggregations "notmyapps" (FilterAgg (FilterAggregation (TermFilter (Term "user" "notmyapp") defaultCache) Nothing))
1348− let search = mkAggregateSearch Nothing ags
1349− let docCountPair k n = (k, object ["doc_count" .= Number n])
1350− res <- searchTweets search
1351− liftIO $
1352− fmap aggregations res `shouldBe` Right (Just (M.fromList [ docCountPair "bitemyapps" 1
1353− , docCountPair "notmyapps" 1
1354− ]))
13551165 it "can execute date_range aggregations" $ withTestEnv $ do
13561166 let now = fromGregorian 2015 3 14
13571167 let ltAMonthAgo = UTCTime (fromGregorian 2015 3 1) 0
@@ -1397,18 +1207,6 @@ main = hspec $ do
13971207 searchExpectAggs search
13981208 searchValidBucketAgg search "byDate" toDateHistogram
13991209
1400− it "returns date histogram using fractional date" $ withTestEnv $ do
1401− _ <- insertData
1402− let periods = [Year, Quarter, Month, Week, Day, Hour, Minute, Second]
1403− let fractionals = map (FractionalInterval 1.5) [Weeks, Days, Hours, Minutes, Seconds]
1404− let intervals = periods ++ fractionals
1405− let histogram = mkDateHistogram (FieldName "postDate")
1406− let search interval = mkAggregateSearch Nothing $ mkAggregations "byDate" $ DateHistogramAgg (histogram interval)
1407− let expect interval = searchExpectAggs (search interval)
1408− let valid interval = searchValidBucketAgg (search interval) "byDate" toDateHistogram
1409− forM_ intervals expect
1410− forM_ intervals valid
1411−
14121210 it "can execute missing aggregations" $ withTestEnv $ do
14131211 _ <- insertData
14141212 _ <- insertExtra
@@ -1424,7 +1222,7 @@ main = hspec $ do
14241222 it "returns highlight from query when there should be one" $ withTestEnv $ do
14251223 _ <- insertData
14261224 _ <- insertOther
1427− let query = QueryMatchQuery $ mkMatchQuery (FieldName "_all") (QueryString "haskell")
1225+ let query = QueryMatchQuery $ mkMatchQuery (FieldName "message") (QueryString "haskell")
14281226 let testHighlight = Highlights Nothing [FieldHighlight (FieldName "message") Nothing]
14291227
14301228 let search = mkHighlightSearch (Just query) testHighlight
@@ -1435,7 +1233,7 @@ main = hspec $ do
14351233 it "doesn't return highlight from a query when it shouldn't" $ withTestEnv $ do
14361234 _ <- insertData
14371235 _ <- insertOther
1438− let query = QueryMatchQuery $ mkMatchQuery (FieldName "_all") (QueryString "haskell")
1236+ let query = QueryMatchQuery $ mkMatchQuery (FieldName "message") (QueryString "haskell")
14391237 let testHighlight = Highlights Nothing [FieldHighlight (FieldName "user") Nothing]
14401238
14411239 let search = mkHighlightSearch (Just query) testHighlight
@@ -1691,27 +1489,6 @@ main = hspec $ do
16911489 L.find ((== alias) . indexAliasSummaryAlias) summs `shouldBe` Just expected
16921490 Left e -> expectationFailure ("Expected an IndexAliasesSummary but got " <> show e)) `finally` cleanup
16931491
1694− it "handles an alias with routing and a filter" $ do
1695− let alias = IndexAlias (testIndex) (IndexAliasName (IndexName "bloodhound-tests-twitter-1-alias"))
1696− let sar = SearchAliasRouting (RoutingValue "search val" :| [])
1697− let iar = IndexAliasRouting (RoutingValue "index val")
1698− let routing = GranularAliasRouting (Just sar) (Just iar)
1699− let filter = LimitFilter 42
1700− let create = IndexAliasCreate (Just routing) (Just filter)
1701− let action = AddAlias alias create
1702−
1703− withTestEnv $ do
1704− resetIndex
1705− resp <- updateIndexAliases (action :| [])
1706− liftIO $ validateStatus resp 200
1707− let cleanup = withTestEnv (updateIndexAliases (RemoveAlias alias :| []))
1708− (do aliases <- withTestEnv getIndexAliases
1709− let expected = IndexAliasSummary alias create
1710− case aliases of
1711− Right (IndexAliasesSummary summs) ->
1712− L.find ((== alias) . indexAliasSummaryAlias) summs `shouldBe` Just expected
1713− Left e -> expectationFailure ("Expected an IndexAliasesSummary but got " <> show e)) `finally` cleanup
1714−
17151492 describe "Index Listing" $ do
17161493 it "returns a list of index names" $ withTestEnv $ do
17171494 _ <- createExampleIndex
@@ -1735,7 +1512,7 @@ main = hspec $ do
17351512 describe "Index Optimization" $ do
17361513 it "returns a successful response upon completion" $ withTestEnv $ do
17371514 _ <- createExampleIndex
1738− resp <- optimizeIndex (IndexList (testIndex :| [])) defaultIndexOptimizationSettings
1515+ resp <- forceMergeIndex (IndexList (testIndex :| [])) defaultForceMergeIndexSettings
17391516 liftIO $ validateStatus resp 200
17401517
17411518 describe "JSON instances" $ do
@@ -1801,7 +1578,6 @@ main = hspec $ do
18011578 propJSON (Proxy :: Proxy FuzzyQuery)
18021579 propJSON (Proxy :: Proxy FuzzyLikeFieldQuery)
18031580 propJSON (Proxy :: Proxy FuzzyLikeThisQuery)
1804− propJSON (Proxy :: Proxy FilteredQuery)
18051581 propJSON (Proxy :: Proxy DisMaxQuery)
18061582 propJSON (Proxy :: Proxy CommonTermsQuery)
18071583 propJSON (Proxy :: Proxy CommonMinimumMatch)