git.iko.soy/typeable/bloodhound
on master help sign in
Merging with master
commit70f70e4e14aefd922bc1615237a8b23a09231f41 authorChristopher Guiney <chris@guiney.net> dateSat 11 Oct 2014, 12:36 (12 years ago) parent5792d97f4d0e10
6 files changed+116−71
.travis.yml+1−1 Database/Bloodhound/Types.hs+43−40 README.org+5−1 bloodhound.cabal+6−3 changelog → changelog.md+19−3 tests/tests.hs+42−23
.travis.yml+1−1
@@ -25,7 +25,7 @@ before_install:
2525 - sudo apt-get install happy-1.19.3
2626 - export PATH=/opt/ghc/$GHCVER/bin:/opt/happy/1.19.3/bin:$PATH
2727 - wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-$ESVER.deb
28− - sudo dpkg -i elasticsearch-$ESVER.deb
28+ - sudo dpkg --force-all -i elasticsearch-$ESVER.deb
2929 - sudo service elasticsearch start
3030
3131install:
Database/Bloodhound/Types.hs+43−40
@@ -1,4 +1,4 @@
1−{-# LANGUAGE DeriveGeneric #-}
1+{-# LANGUAGE DeriveGeneric #-}
22{-# LANGUAGE RecordWildCards #-}
33
44{-| Data types for describing actions and data structures performed to interact
@@ -28,6 +28,7 @@ module Database.Bloodhound.Types
2828 , mkDateHistogram
2929 , toTerms
3030 , toDateHistogram
31+ , omitNulls
3132 , Version(..)
3233 , Status(..)
3334 , Existence(..)
@@ -165,22 +166,23 @@ module Database.Bloodhound.Types
165166 , DateHistogramResult
166167 ) where
167168
168−import Control.Applicative
169−import Data.Aeson
170−import Data.Aeson.Types (parseMaybe)
171−import qualified Data.ByteString.Lazy.Char8 as L
172−import Data.List (nub)
173−import Data.List.NonEmpty (NonEmpty(..))
174−import Data.Monoid
175−import Data.Text (Text)
176−import qualified Data.Map.Strict as M
177−import qualified Data.Text as T
178−import Data.Time.Clock (UTCTime)
179−import GHC.Generics (Generic)
180−import Network.HTTP.Client
181−import qualified Network.HTTP.Types.Method as NHTM
182−
183−import Database.Bloodhound.Types.Class
169+import Control.Applicative
170+import Data.Aeson
171+import Data.Aeson.Types (parseMaybe)
172+import qualified Data.ByteString.Lazy.Char8 as L
173+import Data.List (nub)
174+import Data.List.NonEmpty (NonEmpty (..))
175+import Data.Monoid
176+import Data.Text (Text)
177+import qualified Data.Text as T
178+import qualified Data.Map.Strict as M
179+import Data.Time.Clock (UTCTime)
180+import qualified Data.Vector as V
181+import GHC.Generics (Generic)
182+import Network.HTTP.Client
183+import qualified Network.HTTP.Types.Method as NHTM
184+
185+import Database.Bloodhound.Types.Class
184186
185187
186188{-| 'Version' is embedded in 'Status' -}
@@ -238,8 +240,8 @@ data FieldDefinition =
238240 FieldDefinition { fieldType :: FieldType } deriving (Eq, Show)
239241
240242data MappingField =
241− MappingField { mappingFieldName :: FieldName
242− , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
243+ MappingField { mappingFieldName :: FieldName
244+ , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
243245
244246{-| Support for type reification of 'Mapping's is currently incomplete, for
245247 now the mapping API verbiage expects a 'ToJSON'able blob.
@@ -497,11 +499,11 @@ type Size = Int
497499data Search = Search { queryBody :: Maybe Query
498500 , filterBody :: Maybe Filter
499501 , sortBody :: Maybe Sort
500− , aggBody :: Maybe Aggregations
502+ , aggBody :: Maybe Aggregations
501503 -- default False
502504 , trackSortScores :: TrackSortScores
503− , from :: From
504− , size :: Size } deriving (Eq, Show)
505+ , from :: From
506+ , size :: Size } deriving (Eq, Show)
505507
506508data Query =
507509 TermQuery Term (Maybe Boost)
@@ -534,10 +536,10 @@ data Query =
534536 deriving (Eq, Show)
535537
536538data RegexpQuery =
537− RegexpQuery { regexpQueryField :: FieldName
538− , regexpQuery :: Regexp
539− , regexpQueryFlags :: RegexpFlags
540− , regexpQueryBoost :: Maybe Boost
539+ RegexpQuery { regexpQueryField :: FieldName
540+ , regexpQuery :: Regexp
541+ , regexpQueryFlags :: RegexpFlags
542+ , regexpQueryBoost :: Maybe Boost
541543 } deriving (Eq, Show)
542544
543545data RangeQuery =
@@ -657,9 +659,9 @@ data MoreLikeThisQuery =
657659data IndicesQuery =
658660 IndicesQuery
659661 { indicesQueryIndices :: [IndexName]
660− , indicesQuery :: Query
662+ , indicesQuery :: Query
661663 -- default "all"
662− , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show)
664+ , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show)
663665
664666data HasParentQuery =
665667 HasParentQuery
@@ -776,15 +778,15 @@ data MultiMatchQueryType =
776778 | MultiMatchPhrasePrefix deriving (Eq, Show)
777779
778780data BoolQuery =
779− BoolQuery { boolQueryMustMatch :: Maybe Query
780− , boolQueryMustNotMatch :: Maybe Query
781− , boolQueryShouldMatch :: Maybe [Query]
781+ BoolQuery { boolQueryMustMatch :: [Query]
782+ , boolQueryMustNotMatch :: [Query]
783+ , boolQueryShouldMatch :: [Query]
782784 , boolQueryMinimumShouldMatch :: Maybe MinimumMatch
783785 , boolQueryBoost :: Maybe Boost
784786 , boolQueryDisableCoord :: Maybe DisableCoord
785787 } deriving (Eq, Show)
786788
787−mkBoolQuery :: Maybe Query -> Maybe Query -> Maybe [Query] -> BoolQuery
789+mkBoolQuery :: [Query] -> [Query] -> [Query] -> BoolQuery
788790mkBoolQuery must mustNot should =
789791 BoolQuery must mustNot should Nothing Nothing Nothing
790792
@@ -811,7 +813,7 @@ data CommonMinimumMatch =
811813 deriving (Eq, Show)
812814
813815data MinimumMatchHighLow =
814− MinimumMatchHighLow { lowFreq :: MinimumMatch
816+ MinimumMatchHighLow { lowFreq :: MinimumMatch
815817 , highFreq :: MinimumMatch } deriving (Eq, Show)
816818
817819data Filter = AndFilter [Filter] Cache
@@ -951,11 +953,11 @@ data FromJSON a => SearchHits a =
951953 , hits :: [Hit a] } deriving (Eq, Show)
952954
953955data FromJSON a => Hit a =
954− Hit { hitIndex :: IndexName
955− , hitType :: MappingName
956− , hitDocId :: DocId
957− , hitScore :: Score
958− , hitSource :: a } deriving (Eq, Show)
956+ Hit { hitIndex :: IndexName
957+ , hitType :: MappingName
958+ , hitDocId :: DocId
959+ , hitScore :: Score
960+ , hitSource :: a } deriving (Eq, Show)
959961
960962data ShardResult =
961963 ShardResult { shardTotal :: Int
@@ -1370,8 +1372,9 @@ instance ToJSON Query where
13701372
13711373omitNulls :: [(Text, Value)] -> Value
13721374omitNulls = object . filter notNull where
1373− notNull (_, Null) = False
1374− notNull _ = True
1375+ notNull (_, Null) = False
1376+ notNull (_, (Array a)) = (not . V.null) a
1377+ notNull _ = True
13751378
13761379
13771380instance ToJSON SimpleQueryStringQuery where
README.org+5−1
@@ -13,6 +13,10 @@
1313
1414Search doesn't have to be hard. Let the dog do it.
1515
16+** Endorsements
17+
18+"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
19+
1620** Version compatibility
1721
1822Elasticsearch >= 1.0 is recommended. Bloodhound mostly works with 0.9.x, but I don't recommend it if you expect everything to work. As of Bloodhound 0.3 all >=1.0 versions of Elasticsearch work.
@@ -382,7 +386,7 @@ let search = mkSearch (Just query) Nothing
382386let innerQuery = QueryMatchQuery $
383387 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
384388let query = QueryBoolQuery $
385− mkBoolQuery (Just innerQuery) Nothing Nothing
389+ mkBoolQuery [innerQuery] [] []
386390let search = mkSearch (Just query) Nothing
387391
388392#+END_SRC
bloodhound.cabal+6−3
@@ -1,5 +1,5 @@
11name: bloodhound
2−version: 0.3.0.0
2+version: 0.4.0.0
33synopsis: ElasticSearch client library for Haskell
44description: ElasticSearch made awesome for Haskell hackers
55homepage: https://github.com/bitemyapp/bloodhound
@@ -32,7 +32,8 @@ library
3232 semigroups >= 0.15,
3333 time >= 1.4,
3434 text >= 0.11,
35− http-types >= 0.8
35+ http-types >= 0.8,
36+ vector >= 0.10.11
3637 default-language: Haskell2010
3738
3839test-suite tests
@@ -51,5 +52,7 @@ test-suite tests
5152 time >= 1.4,
5253 aeson >= 0.7,
5354 semigroups >= 0.15,
54− QuickCheck
55+ QuickCheck,
56+ vector >= 0.10.11,
57+ unordered-containers >=0.2.5.0
5558 default-language: Haskell2010
changelog → changelog.mdrenamed+19−3
@@ -1,6 +1,22 @@
1−** 0.2.x
1+0.4.0.0
2+===================
3+
4+* omitNulls changed to exclude empty lists and null values
5+
6+* BoolQuery must/mustNot/Should changed from Maybe (Query|[Query]) to [Query]
7+
8+* Added vector dependency so we can check for V.null/V.empty on JSON arrays
9+
10+0.3.0.0
11+===================
12+
13+* Status "ok" changed from Bool to Maybe Bool
14+
15+* Elasticsearch 1.3.x compatibility fixed with changes to geo bounding boxes
16+
17+* CI coverage expanded to 1.0.x -> 1.3.x
218
3−0.2.0.0 --> 0.2.0.1
19+0.2.0.1
420===================
521
622* Killed off maybeJson/mField/catMaybes in favor of omitNulls
@@ -11,7 +27,7 @@
1127
1228* Added note about current supported Elasticsearch version.
1329
14−0.1.0.2 --> 0.2.0.0
30+0.2.0.0
1531===================
1632
1733* Added TermFilter
tests/tests.hs+42−23
@@ -1,29 +1,29 @@
1−{-# LANGUAGE DeriveGeneric #-}
1+{-# LANGUAGE DeriveGeneric #-}
22{-# LANGUAGE ScopedTypeVariables #-}
33
44module Main where
55
6−import Control.Applicative
7−import Control.Monad
8−import Database.Bloodhound
9−import Data.Aeson
10−import Data.Aeson.Types (parseMaybe)
11−import Data.List (nub, elemIndex)
12−import Data.List.NonEmpty (NonEmpty(..))
13−import Data.Time.Calendar (Day(..))
14−import Data.Time.Clock (secondsToDiffTime, UTCTime(..))
15−import Data.Text (Text)
16−import qualified Data.Text as T
17−import GHC.Generics (Generic)
18−import Network.HTTP.Client
6+import Control.Applicative
7+import Control.Monad
8+import Data.Aeson
9+import Data.Aeson.Types (parseMaybe)
10+import Data.HashMap.Strict (fromList)
11+import Data.List (nub)
12+import Data.List.NonEmpty (NonEmpty (..))
13+import qualified Data.Map.Strict as M
14+import Data.Text (Text)
15+import qualified Data.Text as T
16+import Data.Time.Calendar (Day (..))
17+import Data.Time.Clock (UTCTime (..), secondsToDiffTime)
18+import qualified Data.Vector as V
19+import Database.Bloodhound
20+import GHC.Generics (Generic)
21+import Network.HTTP.Client
1922import qualified Network.HTTP.Types.Status as NHTS
20−import Prelude hiding (filter, putStrLn)
21−import Test.Hspec
22−import Test.Hspec.QuickCheck (prop)
23−import Test.QuickCheck
24−import qualified Data.Map.Strict as M
25−
26−import System.IO
23+import Prelude hiding (filter, putStrLn)
24+import Test.Hspec
25+import Test.Hspec.QuickCheck (prop)
26+import Test.QuickCheck
2727
2828testServer :: Server
2929testServer = Server "http://localhost:9200"
@@ -279,7 +279,7 @@ main = hspec $ do
279279 let innerQuery = QueryMatchQuery $
280280 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
281281 let query = QueryBoolQuery $
282− mkBoolQuery (Just innerQuery) Nothing Nothing
282+ mkBoolQuery [innerQuery] [] []
283283 let search = mkSearch (Just query) Nothing
284284 myTweet <- searchTweet search
285285 myTweet `shouldBe` Right exampleTweet
@@ -503,5 +503,24 @@ main = hspec $ do
503503 let String str = toJSON flags
504504 flagStrs = T.splitOn "|" str
505505 in noDuplicates flagStrs
506−
507506
507+ describe "omitNulls" $ do
508+ it "checks that omitNulls drops list elements when it should" $
509+ let dropped = omitNulls $ [ "test1" .= (toJSON ([] :: [Int]))
510+ , "test2" .= (toJSON ("some value" :: Text))]
511+ in dropped `shouldBe` Object (fromList [("test2", String "some value")])
512+
513+ it "checks that omitNulls doesn't drop list elements when it shouldn't" $
514+ let notDropped = omitNulls $ [ "test1" .= (toJSON ([1] :: [Int]))
515+ , "test2" .= (toJSON ("some value" :: Text))]
516+ in notDropped `shouldBe` Object (fromList [ ("test1", Array (V.fromList [Number 1.0]))
517+ , ("test2", String "some value")])
518+ it "checks that omitNulls drops non list elements when it should" $
519+ let dropped = omitNulls $ [ "test1" .= (toJSON Null)
520+ , "test2" .= (toJSON ("some value" :: Text))]
521+ in dropped `shouldBe` Object (fromList [("test2", String "some value")])
522+ it "checks that omitNulls doesn't drop non list elements when it shouldn't" $
523+ let notDropped = omitNulls $ [ "test1" .= (toJSON (1 :: Int))
524+ , "test2" .= (toJSON ("some value" :: Text))]
525+ in notDropped `shouldBe` Object (fromList [ ("test1", Number 1.0)
526+ , ("test2", String "some value")])