git.iko.soy/typeable/bloodhound
on master help sign in
Fix bugs with constant score filter/queries
27e244eMichael Xavier
src/Database/Bloodhound/Client.hs+7−5
@@ -57,6 +57,7 @@ module Database.Bloodhound.Client
57 , isVersionConflict
57 , isVersionConflict
58 , isSuccess
58 , isSuccess
59 , isCreated
59 , isCreated
60+ , parseEsResponse
60 )
61 )
61 where
62 where
62
63
@@ -287,15 +288,16 @@ parseEsResponse :: (MonadBH m, MonadThrow m, FromJSON a) => Reply
287parseEsResponse reply
288parseEsResponse reply
288 | respIsTwoHunna reply = case eitherDecode body of
289 | respIsTwoHunna reply = case eitherDecode body of
289 Right a -> return (Right a)
290 Right a -> return (Right a)
290− Left _ -> case eitherDecode body of
291+ Left _ -> tryParseError
291− Right e -> return (Left e)
292− -- this case should not be possible
293− Left _ -> explode
294− | otherwise = explode
292+ | otherwise = tryParseError
295 where body = responseBody reply
293 where body = responseBody reply
296 stat = responseStatus reply
294 stat = responseStatus reply
297 hdrs = responseHeaders reply
295 hdrs = responseHeaders reply
298 cookies = responseCookieJar reply
296 cookies = responseCookieJar reply
297+ tryParseError = case eitherDecode body of
298+ Right e -> return (Left e)
299+ -- this case should not be possible
300+ Left _ -> explode
299 explode = throwM (StatusCodeException stat hdrs cookies)
301 explode = throwM (StatusCodeException stat hdrs cookies)
300
302
301-- | 'indexExists' enables you to check if an index exists. Returns 'Bool'
303-- | 'indexExists' enables you to check if an index exists. Returns 'Bool'
src/Database/Bloodhound/Types.hs+11−12
@@ -1825,12 +1825,12 @@ instance ToJSON Query where
1825 object [ "common" .= commonTermsQuery ]
1825 object [ "common" .= commonTermsQuery ]
1826
1826
1827 toJSON (ConstantScoreFilter csFilter boost) =
1827 toJSON (ConstantScoreFilter csFilter boost) =
1828− object ["filter" .= object ["constant_score" .= csFilter]
1828+ object ["constant_score" .= object ["filter" .= csFilter
1829− , "boost" .= boost]
1829+ , "boost" .= boost]]
1830
1830
1831 toJSON (ConstantScoreQuery query boost) =
1831 toJSON (ConstantScoreQuery query boost) =
1832− object ["query" .= object ["constant_score" .= query]
1832+ object ["constant_score" .= object ["query" .= query
1833− , "boost" .= boost]
1833+ , "boost" .= boost]]
1834
1834
1835 toJSON (QueryDisMaxQuery disMaxQuery) =
1835 toJSON (QueryDisMaxQuery disMaxQuery) =
1836 object [ "dis_max" .= disMaxQuery ]
1836 object [ "dis_max" .= disMaxQuery ]
@@ -1891,8 +1891,8 @@ instance FromJSON Query where
1891 <|> queryBoolQuery `taggedWith` "bool"
1891 <|> queryBoolQuery `taggedWith` "bool"
1892 <|> queryBoostingQuery `taggedWith` "boosting"
1892 <|> queryBoostingQuery `taggedWith` "boosting"
1893 <|> queryCommonTermsQuery `taggedWith` "common"
1893 <|> queryCommonTermsQuery `taggedWith` "common"
1894− <|> constantScoreFilter o
1894+ <|> constantScoreFilter `taggedWith` "constant_score"
1895− <|> constantScoreQuery o
1895+ <|> constantScoreQuery `taggedWith` "constant_score"
1896 <|> queryDisMaxQuery `taggedWith` "dis_max"
1896 <|> queryDisMaxQuery `taggedWith` "dis_max"
1897 <|> queryFilteredQuery `taggedWith` "filtered"
1897 <|> queryFilteredQuery `taggedWith` "filtered"
1898 <|> queryFuzzyLikeThisQuery `taggedWith` "fuzzy_like_this"
1898 <|> queryFuzzyLikeThisQuery `taggedWith` "fuzzy_like_this"
@@ -1926,15 +1926,14 @@ instance FromJSON Query where
1926 queryBoolQuery = pure . QueryBoolQuery
1926 queryBoolQuery = pure . QueryBoolQuery
1927 queryBoostingQuery = pure . QueryBoostingQuery
1927 queryBoostingQuery = pure . QueryBoostingQuery
1928 queryCommonTermsQuery = pure . QueryCommonTermsQuery
1928 queryCommonTermsQuery = pure . QueryCommonTermsQuery
1929− --FIXME: these are ambiguous
1930 constantScoreFilter o = case HM.lookup "filter" o of
1929 constantScoreFilter o = case HM.lookup "filter" o of
1931− Just (Object o') -> ConstantScoreFilter <$> o' .: "constant_score"
1930+ Just x -> ConstantScoreFilter <$> parseJSON x
1932− <*> o .: "boost"
1931+ <*> o .: "boost"
1933 _ -> fail "Does not appear to be a ConstantScoreFilter"
1932 _ -> fail "Does not appear to be a ConstantScoreFilter"
1934 constantScoreQuery o = case HM.lookup "query" o of
1933 constantScoreQuery o = case HM.lookup "query" o of
1935− Just (Object o') -> ConstantScoreQuery <$> o' .: "constant_score"
1934+ Just x -> ConstantScoreQuery <$> parseJSON x
1936− <*> o .: "boost"
1935+ <*> o .: "boost"
1937− _ -> fail "Does not appear to be a ConstantScoreFilter"
1936+ _ -> fail "Does not appear to be a ConstantScoreQuery"
1938 queryDisMaxQuery = pure . QueryDisMaxQuery
1937 queryDisMaxQuery = pure . QueryDisMaxQuery
1939 queryFilteredQuery = pure . QueryFilteredQuery
1938 queryFilteredQuery = pure . QueryFilteredQuery
1940 queryFuzzyLikeThisQuery = pure . QueryFuzzyLikeThisQuery
1939 queryFuzzyLikeThisQuery = pure . QueryFuzzyLikeThisQuery
tests/tests.hs+30−10
@@ -211,15 +211,15 @@ insertWithSpaceInId = do
211 _ <- refreshIndex testIndex
211 _ <- refreshIndex testIndex
212 return ()
212 return ()
213
213
214−searchTweet :: Search -> BH IO (Either String Tweet)
214+searchTweet :: Search -> BH IO (Either EsError Tweet)
215searchTweet search = do
215searchTweet search = do
216 result <- searchTweets search
216 result <- searchTweets search
217− let myTweet :: Either String Tweet
217+ let myTweet :: Either EsError Tweet
218 myTweet = grabFirst result
218 myTweet = grabFirst result
219 return myTweet
219 return myTweet
220
220
221−searchTweets :: Search -> BH IO (Either String (SearchResult Tweet))
221+searchTweets :: Search -> BH IO (Either EsError (SearchResult Tweet))
222−searchTweets search = eitherDecode . responseBody <$> searchByIndex testIndex search
222+searchTweets search = parseEsResponse =<< searchByIndex testIndex search
223
223
224searchExpectNoResults :: Search -> BH IO ()
224searchExpectNoResults :: Search -> BH IO ()
225searchExpectNoResults search = do
225searchExpectNoResults search = do
@@ -253,19 +253,19 @@ searchTermsAggHint hints = do
253 forM_ hints $ searchExpectAggs . search
253 forM_ hints $ searchExpectAggs . search
254 forM_ hints (\x -> searchValidBucketAgg (search x) "users" toTerms)
254 forM_ hints (\x -> searchValidBucketAgg (search x) "users" toTerms)
255
255
256−searchTweetHighlight :: Search -> BH IO (Either String (Maybe HitHighlight))
256+searchTweetHighlight :: Search -> BH IO (Either EsError (Maybe HitHighlight))
257searchTweetHighlight search = do
257searchTweetHighlight search = do
258 result <- searchTweets search
258 result <- searchTweets search
259 let myHighlight = fmap (hitHighlight . head . hits . searchHits) result
259 let myHighlight = fmap (hitHighlight . head . hits . searchHits) result
260 return myHighlight
260 return myHighlight
261
261
262−searchExpectSource :: Source -> Either String Value -> BH IO ()
262+searchExpectSource :: Source -> Either EsError Value -> BH IO ()
263searchExpectSource src expected = do
263searchExpectSource src expected = do
264 _ <- insertData
264 _ <- insertData
265 let query = QueryMatchQuery $ mkMatchQuery (FieldName "_all") (QueryString "haskell")
265 let query = QueryMatchQuery $ mkMatchQuery (FieldName "_all") (QueryString "haskell")
266 let search = (mkSearch (Just query) Nothing) { source = Just src }
266 let search = (mkSearch (Just query) Nothing) { source = Just src }
267 reply <- searchAll search
267 reply <- searchAll search
268− let result = eitherDecode (responseBody reply) :: Either String (SearchResult Value)
268+ result <- parseEsResponse reply-- :: Either EsError (SearchResult Value)
269 let value = grabFirst result
269 let value = grabFirst result
270 liftIO $
270 liftIO $
271 value `shouldBe` expected
271 value `shouldBe` expected
@@ -307,11 +307,11 @@ reduceSize f = sized $ \n -> resize (n `div` 2) f
307getSource :: EsResult a -> Maybe a
307getSource :: EsResult a -> Maybe a
308getSource = fmap _source . foundResult
308getSource = fmap _source . foundResult
309
309
310−grabFirst :: Either String (SearchResult a) -> Either String a
310+grabFirst :: Either EsError (SearchResult a) -> Either EsError a
311grabFirst r =
311grabFirst r =
312 case fmap (hitSource . head . hits . searchHits) r of
312 case fmap (hitSource . head . hits . searchHits) r of
313 (Left e) -> Left e
313 (Left e) -> Left e
314− (Right Nothing) -> Left "Source was missing"
314+ (Right Nothing) -> Left (EsError 500 "Source was missing")
315 (Right (Just x)) -> Right x
315 (Right (Just x)) -> Right x
316
316
317-------------------------------------------------------------------------------
317-------------------------------------------------------------------------------
@@ -611,6 +611,26 @@ main = hspec $ do
611 liftIO $
611 liftIO $
612 myTweet `shouldBe` Right exampleTweet
612 myTweet `shouldBe` Right exampleTweet
613
613
614+ it "handles constant score queries" $ withTestEnv $ do
615+ _ <- insertData
616+ let query = TermsQuery "user" ("bitemyapp" :| [])
617+ let cfQuery = ConstantScoreQuery query (Boost 1.0)
618+ let filter = IdentityFilter
619+ let search = mkSearch (Just cfQuery) (Just filter)
620+ myTweet <- searchTweet search
621+ liftIO $
622+ myTweet `shouldBe` Right exampleTweet
623+ it "handles constant score filters" $ withTestEnv $ do
624+ _ <- insertData
625+ let query = TermsQuery "user" ("bitemyapp" :| [])
626+ let cfFilter = ConstantScoreFilter IdentityFilter (Boost 1.0)
627+ let boolQuery = mkBoolQuery [query, cfFilter] [] []
628+ let search = mkSearch (Just (QueryBoolQuery boolQuery)) Nothing
629+ myTweet <- searchTweet search
630+ liftIO $
631+ myTweet `shouldBe` Right exampleTweet
632+
633+
614 it "returns document for terms query and identity filter" $ withTestEnv $ do
634 it "returns document for terms query and identity filter" $ withTestEnv $ do
615 _ <- insertData
635 _ <- insertData
616 let query = TermsQuery "user" ("bitemyapp" :| [])
636 let query = TermsQuery "user" ("bitemyapp" :| [])
@@ -946,7 +966,7 @@ main = hspec $ do
946 it "doesn't include source when sources are disabled" $ withTestEnv $ do
966 it "doesn't include source when sources are disabled" $ withTestEnv $ do
947 searchExpectSource
967 searchExpectSource
948 NoSource
968 NoSource
949− (Left "Source was missing")
969+ (Left (EsError 500 "Source was missing"))
950
970
951 it "includes a source" $ withTestEnv $ do
971 it "includes a source" $ withTestEnv $ do
952 searchExpectSource
972 searchExpectSource