git.iko.soy/typeable/bloodhound
on master help sign in
cleanup, passing test for match queries
069704aChris Allen
.gitignore+2
@@ -1,3 +1,5 @@
1cabal.sandbox.config
1cabal.sandbox.config
2.cabal-sandbox/
2.cabal-sandbox/
3dist/
3dist/
4+.project
5+.dist-buildwrapper/
Database/Bloodhound.hs+2−77
@@ -1,81 +1,6 @@
1module Database.Bloodhound
1module Database.Bloodhound
2− ( createIndex
2+ ( module Database.Bloodhound.Client
3− , deleteIndex
3+ , module Database.Bloodhound.Types
4− , defaultIndexSettings
5− , createMapping
6− , deleteMapping
7− , indexDocument
8− , getDocument
9− , documentExists
10− , deleteDocument
11− , searchAll
12− , searchByIndex
13− , searchByType
14− , refreshIndex
15− , mkSearch
16− , bulk
17− , defaultCache
18− , halfRangeToKV
19− , maybeJson
20− , maybeJsonF
21− , rangeToKV
22− , showText
23− , unpackId
24− , mkSort
25− , Version(..)
26− , Status(..)
27− , Existence(..)
28− , NullValue(..)
29− , IndexSettings(..)
30− , Server(..)
31− , Reply(..)
32− , EsResult(..)
33− , Query(..)
34− , Search(..)
35− , SearchResult(..)
36− , SearchHits(..)
37− , ShardResult(..)
38− , Hit(..)
39− , Filter(..)
40− , Seminearring(..)
41− , BoolMatch(..)
42− , Term(..)
43− , GeoPoint(..)
44− , GeoBoundingBoxConstraint(..)
45− , GeoBoundingBox(..)
46− , GeoFilterType(..)
47− , Distance(..)
48− , DistanceUnit(..)
49− , DistanceType(..)
50− , DistanceRange(..)
51− , OptimizeBbox(..)
52− , LatLon(..)
53− , Range(..)
54− , HalfRange(..)
55− , RangeExecution(..)
56− , LessThan(..)
57− , LessThanEq(..)
58− , GreaterThan(..)
59− , GreaterThanEq(..)
60− , Regexp(..)
61− , RegexpFlags(..)
62− , FieldName(..)
63− , IndexName(..)
64− , MappingName(..)
65− , DocId(..)
66− , CacheName(..)
67− , CacheKey(..)
68− , BulkOperation(..)
69− , ReplicaCount(..)
70− , ShardCount(..)
71− , Sort(..)
72− , SortMode(..)
73− , SortOrder(..)
74− , SortSpec(..)
75− , DefaultSort(..)
76− , Missing(..)
77− , OpenCloseIndex(..)
78− , Method(..)
79 ) where
4 ) where
80
5
81import Database.Bloodhound.Client
6import Database.Bloodhound.Client
Database/Bloodhound/Types.hs+246−58
@@ -10,6 +10,7 @@ module Database.Bloodhound.Types
10 , rangeToKV
10 , rangeToKV
11 , showText
11 , showText
12 , unpackId
12 , unpackId
13+ , mkMatchQuery
13 , Version(..)
14 , Version(..)
14 , Status(..)
15 , Status(..)
15 , Existence(..)
16 , Existence(..)
@@ -64,6 +65,36 @@ module Database.Bloodhound.Types
64 , Missing(..)
65 , Missing(..)
65 , OpenCloseIndex(..)
66 , OpenCloseIndex(..)
66 , Method(..)
67 , Method(..)
68+ , Boost(..)
69+ , MatchQuery(..)
70+ , MultiMatchQuery(..)
71+ , BoolQuery(..)
72+ , BoostingQuery(..)
73+ , CommonTermsQuery(..)
74+ , DisMaxQuery(..)
75+ , FilteredQuery(..)
76+ , FuzzyLikeThisQuery(..)
77+ , FuzzyLikeFieldQuery(..)
78+ , FuzzyQuery(..)
79+ , HasChildQuery(..)
80+ , HasParentQuery(..)
81+ , AnIndicesQuery(..)
82+ , MoreLikeThisQuery(..)
83+ , MoreLikeThisFieldQuery(..)
84+ , NestedQuery(..)
85+ , PrefixQuery(..)
86+ , QueryStringQuery(..)
87+ , SimpleQueryStringQuery(..)
88+ , RangeQuery(..)
89+ , RegexpQuery(..)
90+ , QueryString(..)
91+ , BooleanOperator(..)
92+ , ZeroTermsQuery(..)
93+ , CutoffFrequency(..)
94+ , Analyzer(..)
95+ , MaxExpansions(..)
96+ , Lenient(..)
97+ , MatchQueryType(..)
67 ) where
98 ) where
68
99
69import Data.Aeson
100import Data.Aeson
@@ -82,15 +113,11 @@ data Version = Version { number :: Text
82 , build_snapshot :: Bool
113 , build_snapshot :: Bool
83 , lucene_version :: Text } deriving (Show, Generic)
114 , lucene_version :: Text } deriving (Show, Generic)
84
115
85−data (FromJSON a, ToJSON a) => Status a =
86− Status { ok :: Bool
116+data Status a = Status { ok :: Bool
87− , status :: Int
117+ , status :: Int
88− , name :: Text
118+ , name :: Text
89− , version :: a
119+ , version :: a
90− , tagline :: Text } deriving (Eq, Show)
120+ , tagline :: Text } deriving (Eq, Show)
91−
92−newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic)
93−newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic)
94
121
95data IndexSettings =
122data IndexSettings =
96 IndexSettings { indexShards :: ShardCount
123 IndexSettings { indexShards :: ShardCount
@@ -100,7 +127,6 @@ defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
100
127
101data Strategy = RoundRobinStrat | RandomStrat | HeadStrat deriving (Eq, Show)
128data Strategy = RoundRobinStrat | RandomStrat | HeadStrat deriving (Eq, Show)
102
129
103−newtype Server = Server String deriving (Eq, Show)
104
130
105type Reply = Network.HTTP.Conduit.Response L.ByteString
131type Reply = Network.HTTP.Conduit.Response L.ByteString
106type Method = NHTM.Method
132type Method = NHTM.Method
@@ -120,9 +146,9 @@ data FieldDefinition =
120
146
121data MappingField =
147data MappingField =
122 MappingField { mappingFieldName :: FieldName
148 MappingField { mappingFieldName :: FieldName
123− , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
149+ , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
124
150
125−data Mapping = Mapping { typeName :: Text
151+data Mapping = Mapping { typeName :: TypeName
126 , fields :: [MappingField] } deriving (Eq, Show)
152 , fields :: [MappingField] } deriving (Eq, Show)
127
153
128data BulkOperation =
154data BulkOperation =
@@ -174,28 +200,48 @@ type PrefixValue = Text
174
200
175data BooleanOperator = And | Or deriving (Eq, Show)
201data BooleanOperator = And | Or deriving (Eq, Show)
176
202
203+newtype ShardCount = ShardCount Int deriving (Eq, Show, Generic)
204+newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic)
205+newtype Server = Server String deriving (Eq, Show)
177−newtype IndexName = IndexName String deriving (Eq, Generic, Show)
206+newtype IndexName = IndexName String deriving (Eq, Generic, Show)
178−newtype MappingName = MappingName String deriving (Eq, Generic, Show)
207+newtype MappingName = MappingName String deriving (Eq, Generic, Show)
179−newtype DocId = DocId String deriving (Eq, Generic, Show)
208+newtype DocId = DocId String deriving (Eq, Generic, Show)
180−newtype QueryString = QueryString Text deriving (Eq, Show)
209+newtype QueryString = QueryString Text deriving (Eq, Show)
181−newtype FieldName = FieldName Text deriving (Eq, Show)
210+newtype FieldName = FieldName Text deriving (Eq, Show)
182−newtype CacheName = CacheName Text deriving (Eq, Show)
211+newtype CacheName = CacheName Text deriving (Eq, Show)
183−newtype CacheKey = CacheKey Text deriving (Eq, Show)
212+newtype CacheKey = CacheKey Text deriving (Eq, Show)
184−newtype Existence = Existence Bool deriving (Eq, Show)
213+newtype Existence = Existence Bool deriving (Eq, Show)
185−newtype NullValue = NullValue Bool deriving (Eq, Show)
214+newtype NullValue = NullValue Bool deriving (Eq, Show)
186−newtype CutoffFrequency = CutoffFrequency Double deriving (Eq, Show)
215+newtype CutoffFrequency = CutoffFrequency Double deriving (Eq, Show, Generic)
187−newtype Analyzer = Analyzer Text deriving (Eq, Show)
216+newtype Analyzer = Analyzer Text deriving (Eq, Show, Generic)
188−newtype MaxExpansions = MaxExpansions Int deriving (Eq, Show)
217+newtype MaxExpansions = MaxExpansions Int deriving (Eq, Show, Generic)
189−newtype Lenient = Lenient Bool deriving (Eq, Show)
218+newtype Lenient = Lenient Bool deriving (Eq, Show, Generic)
190−newtype Tiebreaker = Tiebreaker Double deriving (Eq, Show)
219+newtype Tiebreaker = Tiebreaker Double deriving (Eq, Show)
191−newtype Boost = Boost Double deriving (Eq, Show)
220+newtype Boost = Boost Double deriving (Eq, Show, Generic)
221+newtype BoostTerms = BoostTerms Double deriving (Eq, Show)
192−newtype MinimumMatch = MinimumMatch Int deriving (Eq, Show)
222+newtype MinimumMatch = MinimumMatch Int deriving (Eq, Show)
193−newtype MinimumMatchText = MinimumMatchText Text deriving (Eq, Show)
223+newtype MinimumMatchText = MinimumMatchText Text deriving (Eq, Show)
224+newtype DisableCoord = DisableCoord Bool deriving (Eq, Show)
225+newtype IgnoreTermFrequency = IgnoreTermFrequency Bool deriving (Eq, Show)
226+newtype MinimumTermFrequency = MinimumTermFrequency Int deriving (Eq, Show)
227+newtype MaxQueryTerms = MaxQueryTerms Int deriving (Eq, Show)
228+newtype Fuzziness = Fuzziness Double deriving (Eq, Show)
229+newtype PrefixLength = PrefixLength Int deriving (Eq, Show)
230+newtype TypeName = TypeName Text deriving (Eq, Show)
231+newtype PercentMatch = PercentMatch Double deriving (Eq, Show)
232+newtype StopWord = StopWord Text deriving (Eq, Show)
233+newtype QueryPath = QueryPath Text deriving (Eq, Show)
234+newtype AllowLeadingWildcard = AllowLeadingWildcard Bool deriving (Eq, Show)
235+newtype LowercaseExpanded = LowercaseExpanded Bool deriving (Eq, Show)
236+newtype EnablePositionIncrements = EnablePositionIncrements Bool deriving (Eq, Show)
237+newtype AnalyzeWildcard = AnalyzeWildcard Bool deriving (Eq, Show)
238+newtype GeneratePhraseQueries = GeneratePhraseQueries Bool deriving (Eq, Show)
194−newtype DisableCoord = DisableCoord Bool deriving (Eq, Show)
239+newtype Locale = Locale Text deriving (Eq, Show)
195−newtype IgnoreTermFrequency = IgnoreTermFrequency Bool deriving (Eq, Show)
240+newtype MaxWordLength = MaxWordLength Int deriving (Eq, Show)
241+newtype MinWordLength = MinWordLength Int deriving (Eq, Show)
196−newtype MaxQueryTerms = MaxQueryTerms Int deriving (Eq, Show)
242+newtype PhraseSlop = PhraseSlop Int deriving (Eq, Show)
197−newtype Fuzziness = Fuzziness Double deriving (Eq, Show)
243+newtype MinDocFrequency = MinDocFrequency Int deriving (Eq, Show)
198−newtype PrefixLength = PrefixLength Int deriving (Eq, Show)
244+newtype MaxDocFrequency = MaxDocFrequency Int deriving (Eq, Show)
199
245
200unpackId :: DocId -> String
246unpackId :: DocId -> String
201unpackId (DocId docId) = docId
247unpackId (DocId docId) = docId
@@ -212,21 +258,173 @@ data Search = Search { queryBody :: Maybe Query
212 , from :: From
258 , from :: From
213 , size :: Size } deriving (Eq, Show)
259 , size :: Size } deriving (Eq, Show)
214
260
215−data Query = TermQuery Term (Maybe Boost)
261+data Query = TermQuery Term (Maybe Boost)
262+ | TermsQuery [Term] MinimumMatch
216− | QueryMatchQuery MatchQuery
263+ | QueryMatchQuery MatchQuery
217− | QueryMultiMatchQuery MultiMatchQuery
264+ | QueryMultiMatchQuery MultiMatchQuery
218− | QueryBoolQuery BoolQuery
265+ | QueryBoolQuery BoolQuery
219− | QueryBoostingQuery BoostingQuery
266+ | QueryBoostingQuery BoostingQuery
220− | QueryCommonTermsQuery CommonTermsQuery
267+ | QueryCommonTermsQuery CommonTermsQuery
221− | ConstantScoreFilter Filter Boost
268+ | ConstantScoreFilter Filter Boost
222− | ConstantScoreQuery Query Boost
269+ | ConstantScoreQuery Query Boost
223− | QueryDisMaxQuery DisMaxQuery
270+ | QueryDisMaxQuery DisMaxQuery
224− | QueryFilteredQuery FilteredQuery
271+ | QueryFilteredQuery FilteredQuery
225− | QueryFuzzyLikeThisQuery FuzzyLikeThisQuery
272+ | QueryFuzzyLikeThisQuery FuzzyLikeThisQuery
226− | QueryFuzzyLikeFieldQuery FuzzyLikeFieldQuery
273+ | QueryFuzzyLikeFieldQuery FuzzyLikeFieldQuery
227− | QueryFuzzyQuery FuzzyQuery
274+ | QueryFuzzyQuery FuzzyQuery
275+ | QueryHasChildQuery HasChildQuery
276+ | QueryHasParentQuery HasParentQuery
277+ | IdsQuery MappingName [DocId]
278+ | QueryIndicesQuery AnIndicesQuery
279+ | MatchAllQuery (Maybe Boost)
280+ | QueryMoreLikeThisQuery MoreLikeThisQuery
281+ | QueryMoreLikeThisFieldQuery MoreLikeThisFieldQuery
282+ | QueryNestedQuery NestedQuery
283+ | QueryPrefixQuery PrefixQuery
284+ | QueryQueryStringQuery QueryStringQuery
285+ | QuerySimpleQueryStringQuery SimpleQueryStringQuery
286+ | QueryRangeQuery RangeQuery
287+ | QueryRegexpQuery RegexpQuery
228 deriving (Eq, Show)
288 deriving (Eq, Show)
229
289
290+-- Possible flags are ALL, ANYSTRING, AUTOMATON, COMPLEMENT,
291+-- EMPTY, INTERSECTION, INTERVAL, or NONE. huh?
292+
293+data RegexpQuery =
294+ RegexpQuery { regexpQueryField :: FieldName
295+ , regexpQuery :: Regexp
296+ , regexpQueryFlags :: RegexpFlags
297+ , regexpQueryCacheName :: CacheName
298+ , regexpQueryCache :: Cache
299+ , regexpQueryCacheKey :: CacheKey } deriving (Eq, Show)
300+
301+data RangeQuery =
302+ RangeQuery { rangeQueryField :: FieldName
303+ , rangeQueryRange :: Either HalfRange Range
304+ , rangeQueryBoost :: Boost } deriving (Eq, Show)
305+
306+data SimpleQueryStringQuery =
307+ SimpleQueryStringQuery { simpleQueryStringQuery :: QueryString
308+ , simpleQueryStringField :: Maybe FieldOrFields
309+ , simpleQueryStringOperator :: Maybe BooleanOperator
310+ , simpleQueryStringAnalyzer :: Maybe Analyzer
311+ , simpleQueryStringFlags :: Maybe [SimpleQueryFlag]
312+ , simpleQueryStringLowercaseExpanded :: Maybe LowercaseExpanded
313+ , simpleQueryStringLocale :: Maybe Locale
314+ } deriving (Eq, Show)
315+
316+data SimpleQueryFlag = SimpleQueryAll
317+ | SimpleQueryNone
318+ | SimpleQueryAnd
319+ | SimpleQueryOr
320+ | SimpleQueryPrefix
321+ | SimpleQueryPhrase
322+ | SimpleQueryPrecedence
323+ | SimpleQueryEscape
324+ | SimpleQueryWhitespace
325+ | SimpleQueryFuzzy
326+ | SimpleQueryNear
327+ | SimpleQuerySlop deriving (Eq, Show)
328+
329+-- use_dis_max and tie_breaker when fields are plural?
330+data QueryStringQuery =
331+ QueryStringQuery { queryStringQuery :: QueryString
332+ , queryStringDefaultField :: Maybe FieldOrFields
333+ , queryStringOperator :: Maybe BooleanOperator
334+ , queryStringAnalyzer :: Maybe Analyzer
335+ , queryStringAllowLeadingWildcard :: Maybe AllowLeadingWildcard
336+ , queryStringLowercaseExpanded :: Maybe LowercaseExpanded
337+ , queryStringEnablePositionIncrements :: Maybe EnablePositionIncrements
338+ , queryStringFuzzyMaxExpansions :: Maybe MaxExpansions
339+ , queryStringFuzziness :: Maybe Fuzziness
340+ , queryStringFuzzyPrefixLength :: Maybe PrefixLength
341+ , queryStringPhraseSlop :: Maybe PhraseSlop
342+ , queryStringBoost :: Maybe Boost
343+ , queryStringAnalyzeWildcard :: Maybe AnalyzeWildcard
344+ , queryStringGeneratePhraseQueries :: Maybe GeneratePhraseQueries
345+ , queryStringMinimumShouldMatch :: Maybe MinimumMatch
346+ , queryStringLenient :: Maybe Lenient
347+ , queryStringLocale :: Maybe Locale
348+ } deriving (Eq, Show)
349+
350+data FieldOrFields = FofField FieldName
351+ | FofFields [FieldName] deriving (Eq, Show)
352+
353+data PrefixQuery =
354+ PrefixQuery { prefixQueryField :: FieldName
355+ , prefixQueryPrefixValue :: Text
356+ , prefixQueryBoost :: Maybe Boost } deriving (Eq, Show)
357+
358+data NestedQuery =
359+ NestedQuery { nestedQueryPath :: QueryPath
360+ , nestedQueryScoreType :: ScoreType
361+ , nestedQuery :: Query } deriving (Eq, Show)
362+
363+data MoreLikeThisFieldQuery =
364+ MoreLikeThisFieldQuery { moreLikeThisFieldText :: Text
365+ , moreLikeThisFieldFields :: FieldName
366+ -- default 0.3 (30%)
367+ , moreLikeThisFieldPercentMatch :: Maybe PercentMatch
368+ , moreLikeThisFieldMinimumTermFreq :: Maybe MinimumTermFrequency
369+ , moreLikeThisFieldMaxQueryTerms :: Maybe MaxQueryTerms
370+ , moreLikeThisFieldStopWords :: Maybe [StopWord]
371+ , moreLikeThisFieldMinDocFrequency :: Maybe MinDocFrequency
372+ , moreLikeThisFieldMaxDocFrequency :: Maybe MaxDocFrequency
373+ , moreLikeThisFieldMinWordLength :: Maybe MinWordLength
374+ , moreLikeThisFieldMaxWordLength :: Maybe MaxWordLength
375+ , moreLikeThisFieldBoostTerms :: Maybe BoostTerms
376+ , moreLikeThisFieldBoost :: Maybe Boost
377+ , moreLikeThisFieldAnalyzer :: Maybe Analyzer
378+ } deriving (Eq, Show)
379+
380+data MoreLikeThisQuery =
381+ MoreLikeThisQuery { moreLikeThisText :: Text
382+ , moreLikeThisFields :: Maybe [FieldName]
383+ -- default 0.3 (30%)
384+ , moreLikeThisPercentMatch :: Maybe PercentMatch
385+ , moreLikeThisMinimumTermFreq :: Maybe MinimumTermFrequency
386+ , moreLikeThisMaxQueryTerms :: Maybe MaxQueryTerms
387+ , moreLikeThisStopWords :: Maybe [StopWord]
388+ , moreLikeThisMinDocFrequency :: Maybe MinDocFrequency
389+ , moreLikeThisMaxDocFrequency :: Maybe MaxDocFrequency
390+ , moreLikeThisMinWordLength :: Maybe MinWordLength
391+ , moreLikeThisMaxWordLength :: Maybe MaxWordLength
392+ , moreLikeThisBoostTerms :: Maybe BoostTerms
393+ , moreLikeThisBoost :: Maybe Boost
394+ , moreLikeThisAnalyzer :: Maybe Analyzer
395+ } deriving (Eq, Show)
396+
397+data AnIndicesQuery = AnIndexQuery IndexQuery
398+ | AnIndicesQuery IndicesQuery deriving (Eq, Show)
399+
400+
401+data IndicesQuery =
402+ IndicesQuery { indicesQueryIndexName :: IndexName
403+ , indicesQuery :: Query
404+ -- default "all"
405+ , indicesQueryNoMatch :: Maybe Query } deriving (Eq, Show)
406+
407+data IndexQuery =
408+ IndexQuery { indexQueryIndexName :: IndexName
409+ , indexQuery :: Query
410+ -- default "all"
411+ , indexQueryNoMatch :: Maybe Query } deriving (Eq, Show)
412+
413+data HasParentQuery =
414+ HasParentQuery { hasParentQueryType :: TypeName
415+ , hasParentQuery :: Query
416+ , hasParentQueryScoreType :: Maybe ScoreType } deriving (Eq, Show)
417+
418+data HasChildQuery =
419+ HasChildQuery { hasChildQueryType :: TypeName
420+ , hasChildQuery :: Query
421+ , hasChildQueryScoreType :: Maybe ScoreType } deriving (Eq, Show)
422+
423+data ScoreType = ScoreTypeMax
424+ | ScoreTypeSum
425+ | ScoreTypeAvg
426+ | ScoreTypeNone deriving (Eq, Show)
427+
230data FuzzyQuery = FuzzyQuery { fuzzyQueryField :: FieldName
428data FuzzyQuery = FuzzyQuery { fuzzyQueryField :: FieldName
231 , fuzzyQueryValue :: Text
429 , fuzzyQueryValue :: Text
232 , fuzzyQueryPrefixLength :: PrefixLength
430 , fuzzyQueryPrefixLength :: PrefixLength
@@ -373,17 +571,7 @@ data RangeExecution = RangeExecutionIndex
373 | RangeExecutionFielddata deriving (Eq, Show)
571 | RangeExecutionFielddata deriving (Eq, Show)
374
572
375newtype Regexp = Regexp Text deriving (Eq, Show)
573newtype Regexp = Regexp Text deriving (Eq, Show)
376−data RegexpFlags = RegexpAll
574+newtype RegexpFlags = RegexpFlags Text deriving (Eq, Show)
377− | Complement
378− | Interval
379− | Intersection
380− | AnyString
381− | CompInterval
382− | CompIntersection
383− | CompAnyString
384− | IntervalIntersection
385− | IntervalAnyString
386− | IntersectionAnyString deriving (Eq, Show)
387
575
388halfRangeToKV :: HalfRange -> (Text, Double)
576halfRangeToKV :: HalfRange -> (Text, Double)
389halfRangeToKV (HalfRangeLt (LessThan n)) = ("lt", n)
577halfRangeToKV (HalfRangeLt (LessThan n)) = ("lt", n)
Database/Bloodhound/Types/Instances.hs+73−21
@@ -1,3 +1,5 @@
1+{-# LANGUAGE DeriveGeneric #-}
2+
1module Database.Bloodhound.Types.Instances
3module Database.Bloodhound.Types.Instances
2 ( Monoid(..)
4 ( Monoid(..)
3 , Seminearring(..)
5 , Seminearring(..)
@@ -6,6 +8,7 @@ module Database.Bloodhound.Types.Instances
6
8
7import Control.Applicative
9import Control.Applicative
8import Data.Aeson
10import Data.Aeson
11+import Data.Maybe (catMaybes)
9import Data.Monoid
12import Data.Monoid
10import qualified Data.Text as T
13import qualified Data.Text as T
11import Database.Bloodhound.Types
14import Database.Bloodhound.Types
@@ -119,6 +122,7 @@ instance ToJSON GeoPoint where
119 toJSON (GeoPoint (FieldName geoField) latLon) =
122 toJSON (GeoPoint (FieldName geoField) latLon) =
120 object [geoField .= toJSON latLon]
123 object [geoField .= toJSON latLon]
121
124
125+
122instance ToJSON Query where
126instance ToJSON Query where
123 toJSON (TermQuery (Term termField termValue) boost) =
127 toJSON (TermQuery (Term termField termValue) boost) =
124 object ["term" .=
128 object ["term" .=
@@ -130,10 +134,55 @@ instance ToJSON Query where
130 Nothing -> []
134 Nothing -> []
131 merged = mappend base boosted
135 merged = mappend base boosted
132
136
137+ toJSON (QueryMatchQuery matchQuery) =
138+ object ["match" .= toJSON matchQuery]
139+
140+
141+instance ToJSON MatchQuery where
142+ toJSON (MatchQuery (FieldName fieldName)
143+ (QueryString queryString) booleanOperator
144+ zeroTermsQuery cutoffFrequency matchQueryType
145+ analyzer maxExpansions lenient) =
146+ object [ fieldName .= object conjoined ]
147+ where conjoined = [ "query" .= queryString
148+ , "operator" .= toJSON booleanOperator
149+ , "zero_terms_query" .= toJSON zeroTermsQuery]
150+ ++ maybeAdd
151+ f field = fmap ((field .=) . toJSON)
152+ maybeAdd = catMaybes [ f "cutoff_frequency" cutoffFrequency
153+ , f "type" matchQueryType
154+ , f "analyzer" analyzer
155+ , f "max_expansions" maxExpansions
156+ , f "lenient" lenient ]
157+
158+
159+instance ToJSON BooleanOperator where
160+ toJSON And = String "and"
161+ toJSON Or = String "or"
162+
163+instance ToJSON ZeroTermsQuery where
164+ toJSON ZeroTermsNone = String "none"
165+ toJSON ZeroTermsAll = String "all"
166+
167+instance ToJSON MatchQueryType where
168+ toJSON MatchPhrase = "phrase"
169+ toJSON MatchPhrasePrefix = "phrase_prefix"
170+
171+instance ToJSON ReplicaCount
172+instance ToJSON ShardCount
173+instance ToJSON CutoffFrequency
174+instance ToJSON Analyzer
175+instance ToJSON MaxExpansions
176+instance ToJSON Lenient
177+instance ToJSON Boost
133instance ToJSON Version
178instance ToJSON Version
134instance FromJSON Version
179instance FromJSON Version
180+instance FromJSON IndexName
181+instance FromJSON MappingName
182+instance FromJSON DocId
183+
135
184
136−instance (FromJSON a, ToJSON a) => FromJSON (Status a) where
185+instance (FromJSON a) => FromJSON (Status a) where
137 parseJSON (Object v) = Status <$>
186 parseJSON (Object v) = Status <$>
138 v .: "ok" <*>
187 v .: "ok" <*>
139 v .: "status" <*>
188 v .: "status" <*>
@@ -142,13 +191,12 @@ instance (FromJSON a, ToJSON a) => FromJSON (Status a) where
142 v .: "tagline"
191 v .: "tagline"
143 parseJSON _ = empty
192 parseJSON _ = empty
144
193
194+
145instance ToJSON IndexSettings where
195instance ToJSON IndexSettings where
146 toJSON (IndexSettings s r) = object ["settings" .= object ["shards" .= s, "replicas" .= r]]
196 toJSON (IndexSettings s r) = object ["settings" .= object ["shards" .= s, "replicas" .= r]]
147
197
148−instance ToJSON ReplicaCount
149−instance ToJSON ShardCount
150
198
151−instance (FromJSON a, ToJSON a) => FromJSON (EsResult a) where
199+instance (FromJSON a) => FromJSON (EsResult a) where
152 parseJSON (Object v) = EsResult <$>
200 parseJSON (Object v) = EsResult <$>
153 v .: "_index" <*>
201 v .: "_index" <*>
154 v .: "_type" <*>
202 v .: "_type" <*>
@@ -158,6 +206,7 @@ instance (FromJSON a, ToJSON a) => FromJSON (EsResult a) where
158 v .: "_source"
206 v .: "_source"
159 parseJSON _ = empty
207 parseJSON _ = empty
160
208
209+
161instance ToJSON Search where
210instance ToJSON Search where
162 toJSON (Search query filter sort trackSortScores from size) =
211 toJSON (Search query filter sort trackSortScores from size) =
163 object merged where
212 object merged where
@@ -171,6 +220,7 @@ instance ToJSON Search where
171 , lFilter
220 , lFilter
172 , lSort]
221 , lSort]
173
222
223+
174instance ToJSON SortSpec where
224instance ToJSON SortSpec where
175 toJSON (DefaultSortSpec
225 toJSON (DefaultSortSpec
176 (DefaultSort (FieldName sortFieldName) sortOrder ignoreUnmapped
226 (DefaultSort (FieldName sortFieldName) sortOrder ignoreUnmapped
@@ -183,24 +233,24 @@ instance ToJSON SortSpec where
183 lNestedFilter = maybeJson "nested_filter" nestedFilter
233 lNestedFilter = maybeJson "nested_filter" nestedFilter
184 merged = mconcat [base, lSortMode, lMissingSort, lNestedFilter]
234 merged = mconcat [base, lSortMode, lMissingSort, lNestedFilter]
185
235
236+
186instance ToJSON SortOrder where
237instance ToJSON SortOrder where
187 toJSON Ascending = String "asc"
238 toJSON Ascending = String "asc"
188 toJSON Descending = String "desc"
239 toJSON Descending = String "desc"
189
240
241+
190instance ToJSON SortMode where
242instance ToJSON SortMode where
191 toJSON SortMin = String "min"
243 toJSON SortMin = String "min"
192 toJSON SortMax = String "max"
244 toJSON SortMax = String "max"
193 toJSON SortSum = String "sum"
245 toJSON SortSum = String "sum"
194 toJSON SortAvg = String "avg"
246 toJSON SortAvg = String "avg"
195
247
248+
196instance ToJSON Missing where
249instance ToJSON Missing where
197 toJSON LastMissing = String "_last"
250 toJSON LastMissing = String "_last"
198 toJSON FirstMissing = String "_first"
251 toJSON FirstMissing = String "_first"
199 toJSON (CustomMissing txt) = String txt
252 toJSON (CustomMissing txt) = String txt
200
253
201−instance FromJSON IndexName
202−instance FromJSON MappingName
203−instance FromJSON DocId
204
254
205instance ToJSON Distance where
255instance ToJSON Distance where
206 toJSON (Distance coefficient unit) =
256 toJSON (Distance coefficient unit) =
@@ -209,6 +259,7 @@ instance ToJSON Distance where
209 (String unitText) = (toJSON unit)
259 (String unitText) = (toJSON unit)
210 boltedTogether = mappend coefText unitText
260 boltedTogether = mappend coefText unitText
211
261
262+
212instance ToJSON DistanceUnit where
263instance ToJSON DistanceUnit where
213 toJSON Miles = String "mi"
264 toJSON Miles = String "mi"
214 toJSON Yards = String "yd"
265 toJSON Yards = String "yd"
@@ -220,56 +271,56 @@ instance ToJSON DistanceUnit where
220 toJSON Millimeters = String "mm"
271 toJSON Millimeters = String "mm"
221 toJSON NauticalMiles = String "nmi"
272 toJSON NauticalMiles = String "nmi"
222
273
274+
223instance ToJSON DistanceType where
275instance ToJSON DistanceType where
224 toJSON Arc = String "arc"
276 toJSON Arc = String "arc"
225 toJSON SloppyArc = String "sloppy_arc"
277 toJSON SloppyArc = String "sloppy_arc"
226 toJSON Plane = String "plane"
278 toJSON Plane = String "plane"
227
279
280+
228instance ToJSON OptimizeBbox where
281instance ToJSON OptimizeBbox where
229 toJSON NoOptimizeBbox = String "none"
282 toJSON NoOptimizeBbox = String "none"
230 toJSON (OptimizeGeoFilterType gft) = toJSON gft
283 toJSON (OptimizeGeoFilterType gft) = toJSON gft
231
284
285+
232instance ToJSON GeoBoundingBoxConstraint where
286instance ToJSON GeoBoundingBoxConstraint where
233 toJSON (GeoBoundingBoxConstraint (FieldName geoBBField) constraintBox cache) =
287 toJSON (GeoBoundingBoxConstraint (FieldName geoBBField) constraintBox cache) =
234 object [geoBBField .= toJSON constraintBox
288 object [geoBBField .= toJSON constraintBox
235 , "_cache" .= cache]
289 , "_cache" .= cache]
236
290
291+
237instance ToJSON GeoFilterType where
292instance ToJSON GeoFilterType where
238 toJSON GeoFilterMemory = String "memory"
293 toJSON GeoFilterMemory = String "memory"
239 toJSON GeoFilterIndexed = String "indexed"
294 toJSON GeoFilterIndexed = String "indexed"
240
295
296+
241instance ToJSON GeoBoundingBox where
297instance ToJSON GeoBoundingBox where
242 toJSON (GeoBoundingBox topLeft bottomRight) =
298 toJSON (GeoBoundingBox topLeft bottomRight) =
243 object ["top_left" .= toJSON topLeft
299 object ["top_left" .= toJSON topLeft
244 , "bottom_right" .= toJSON bottomRight]
300 , "bottom_right" .= toJSON bottomRight]
245
301
302+
246instance ToJSON LatLon where
303instance ToJSON LatLon where
247 toJSON (LatLon lat lon) =
304 toJSON (LatLon lat lon) =
248 object ["lat" .= lat
305 object ["lat" .= lat
249 , "lon" .= lon]
306 , "lon" .= lon]
250
307
308+
251-- index for smaller ranges, fielddata for longer ranges
309-- index for smaller ranges, fielddata for longer ranges
252instance ToJSON RangeExecution where
310instance ToJSON RangeExecution where
253 toJSON RangeExecutionIndex = "index"
311 toJSON RangeExecutionIndex = "index"
254 toJSON RangeExecutionFielddata = "fielddata"
312 toJSON RangeExecutionFielddata = "fielddata"
255
313
314+
256instance ToJSON RegexpFlags where
315instance ToJSON RegexpFlags where
257− toJSON RegexpAll = String "ALL"
316+ toJSON (RegexpFlags txt) = String txt
258− toJSON Complement = String "COMPLEMENT"
317+
259− toJSON Interval = String "INTERVAL"
260− toJSON Intersection = String "INTERSECTION"
261− toJSON AnyString = String "ANYSTRING"
262− toJSON CompInterval = String "COMPLEMENT|INTERVAL"
263− toJSON CompIntersection = String "COMPLEMENT|INTERSECTION"
264− toJSON CompAnyString = String "COMPLEMENT|ANYSTRING"
265− toJSON IntervalIntersection = String "INTERVAL|INTERSECTION"
266− toJSON IntervalAnyString = String "INTERVAL|ANYSTRING"
267− toJSON IntersectionAnyString = String "INTERSECTION|ANYSTRING"
268
318
269instance ToJSON Term where
319instance ToJSON Term where
270 toJSON (Term field value) = object ["term" .= object
320 toJSON (Term field value) = object ["term" .= object
271 [field .= value]]
321 [field .= value]]
272
322
323+
273instance ToJSON BoolMatch where
324instance ToJSON BoolMatch where
274 toJSON (MustMatch term cache) = object ["must" .= toJSON term,
325 toJSON (MustMatch term cache) = object ["must" .= toJSON term,
275 "_cache" .= cache]
326 "_cache" .= cache]
@@ -278,7 +329,8 @@ instance ToJSON BoolMatch where
278 toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
329 toJSON (ShouldMatch terms cache) = object ["should" .= fmap toJSON terms,
279 "_cache" .= cache]
330 "_cache" .= cache]
280
331
332+
281−instance (FromJSON a, ToJSON a) => FromJSON (SearchResult a) where
333+instance (FromJSON a) => FromJSON (SearchResult a) where
282 parseJSON (Object v) = SearchResult <$>
334 parseJSON (Object v) = SearchResult <$>
283 v .: "took" <*>
335 v .: "took" <*>
284 v .: "timed_out" <*>
336 v .: "timed_out" <*>
@@ -286,14 +338,14 @@ instance (FromJSON a, ToJSON a) => FromJSON (SearchResult a) where
286 v .: "hits"
338 v .: "hits"
287 parseJSON _ = empty
339 parseJSON _ = empty
288
340
289−instance (FromJSON a, ToJSON a) => FromJSON (SearchHits a) where
341+instance (FromJSON a) => FromJSON (SearchHits a) where
290 parseJSON (Object v) = SearchHits <$>
342 parseJSON (Object v) = SearchHits <$>
291 v .: "total" <*>
343 v .: "total" <*>
292 v .: "max_score" <*>
344 v .: "max_score" <*>
293 v .: "hits"
345 v .: "hits"
294 parseJSON _ = empty
346 parseJSON _ = empty
295
347
296−instance (FromJSON a, ToJSON a) => FromJSON (Hit a) where
348+instance (FromJSON a) => FromJSON (Hit a) where
297 parseJSON (Object v) = Hit <$>
349 parseJSON (Object v) = Hit <$>
298 v .: "_index" <*>
350 v .: "_index" <*>
299 v .: "_type" <*>
351 v .: "_type" <*>
Makefile+1−1
@@ -1,6 +1,6 @@
1
1
2test:
2test:
3− cabal install --enable-tests
3+ cabal test
4
4
5build:
5build:
6 cabal build
6 cabal build
README.org+8
@@ -509,6 +509,10 @@ let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
509
509
510* Possible future functionality
510* Possible future functionality
511
511
512+** Span Queries
513+
514+Beginning here: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-span-first-query.html
515+
512** Function Score Query
516** Function Score Query
513
517
514http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
518http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
@@ -525,6 +529,10 @@ Pretend to be a transport client?
525
529
526Might require making a lucene index on disk with the appropriate format.
530Might require making a lucene index on disk with the appropriate format.
527
531
532+** GeoShapeQuery
533+
534+http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-query.html
535+
528** GeoShapeFilter
536** GeoShapeFilter
529
537
530http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-filter.html
538http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-filter.html
bloodhound.cabal+5
@@ -16,6 +16,7 @@ build-type: Simple
16cabal-version: >=1.10
16cabal-version: >=1.10
17
17
18library
18library
19+ ghc-options: -Wall
19 default-extensions: OverloadedStrings
20 default-extensions: OverloadedStrings
20 exposed-modules: Database.Bloodhound
21 exposed-modules: Database.Bloodhound
21 Database.Bloodhound.Client
22 Database.Bloodhound.Client
@@ -28,6 +29,7 @@ library
28 free >= 4.5,
29 free >= 4.5,
29 lens >= 4,
30 lens >= 4,
30 aeson >= 0.7,
31 aeson >= 0.7,
32+ aeson-pretty >= 0.7,
31 conduit >= 1.0,
33 conduit >= 1.0,
32 http-conduit >= 2.0,
34 http-conduit >= 2.0,
33 io-streams >= 1.1,
35 io-streams >= 1.1,
@@ -42,6 +44,7 @@ library
42 default-language: Haskell2010
44 default-language: Haskell2010
43
45
44test-suite tests
46test-suite tests
47+ ghc-options: -Wall
45 default-extensions: OverloadedStrings
48 default-extensions: OverloadedStrings
46 type: exitcode-stdio-1.0
49 type: exitcode-stdio-1.0
47 main-is: tests.hs
50 main-is: tests.hs
@@ -51,12 +54,14 @@ test-suite tests
51 bloodhound,
54 bloodhound,
52 http-conduit,
55 http-conduit,
53 http-types,
56 http-types,
57+ bytestring >= 0.10,
54 hspec >= 1.8,
58 hspec >= 1.8,
55 QuickCheck >= 2.5,
59 QuickCheck >= 2.5,
56 derive >= 2.5,
60 derive >= 2.5,
57 text >= 0.11,
61 text >= 0.11,
58 time >= 1.4,
62 time >= 1.4,
59 aeson >= 0.7,
63 aeson >= 0.7,
64+ aeson-pretty >= 0.7,
60 random >= 1.0,
65 random >= 1.0,
61 quickcheck-instances >= 0.3
66 quickcheck-instances >= 0.3
62 default-language: Haskell2010
67 default-language: Haskell2010
tests/tests.hs+29−10
@@ -4,25 +4,32 @@ module Main where
4
4
5import Database.Bloodhound
5import Database.Bloodhound
6import Data.Aeson
6import Data.Aeson
7−import Data.Either (Either(..))
7+-- import Data.Aeson.Encode.Pretty
8−import Data.Maybe (fromJust)
8+-- import Data.ByteString.Lazy.Char8 (putStrLn)
9import Data.Time.Calendar (Day(..))
9import Data.Time.Calendar (Day(..))
10import Data.Time.Clock (secondsToDiffTime, UTCTime(..))
10import Data.Time.Clock (secondsToDiffTime, UTCTime(..))
11import Data.Text (Text)
11import Data.Text (Text)
12import GHC.Generics (Generic)
12import GHC.Generics (Generic)
13import Network.HTTP.Conduit
13import Network.HTTP.Conduit
14import qualified Network.HTTP.Types.Status as NHTS
14import qualified Network.HTTP.Types.Status as NHTS
15+import Prelude hiding (filter, putStrLn)
15import Test.Hspec
16import Test.Hspec
16
17
18+testServer :: Server
17testServer = Server "http://localhost:9200"
19testServer = Server "http://localhost:9200"
20+testIndex :: IndexName
18testIndex = IndexName "twitter"
21testIndex = IndexName "twitter"
22+testMapping :: MappingName
19testMapping = MappingName "tweet"
23testMapping = MappingName "tweet"
20
24
25+validateStatus :: Response body -> Int -> Expectation
21validateStatus resp expected =
26validateStatus resp expected =
22 (NHTS.statusCode $ responseStatus resp)
27 (NHTS.statusCode $ responseStatus resp)
23 `shouldBe` (expected :: Int)
28 `shouldBe` (expected :: Int)
24
29
30+createExampleIndex :: IO Reply
25createExampleIndex = createIndex testServer defaultIndexSettings testIndex
31createExampleIndex = createIndex testServer defaultIndexSettings testIndex
32+deleteExampleIndex :: IO Reply
26deleteExampleIndex = deleteIndex testServer testIndex
33deleteExampleIndex = deleteIndex testServer testIndex
27
34
28data Location = Location { lat :: Double
35data Location = Location { lat :: Double
@@ -48,6 +55,7 @@ instance ToJSON TweetMapping where
48 object ["properties" .=
55 object ["properties" .=
49 object ["location" .= object ["type" .= ("geo_point" :: Text)]]]]
56 object ["location" .= object ["type" .= ("geo_point" :: Text)]]]]
50
57
58+exampleTweet :: Tweet
51exampleTweet = Tweet { user = "bitemyapp"
59exampleTweet = Tweet { user = "bitemyapp"
52 , postDate = UTCTime
60 , postDate = UTCTime
53 (ModifiedJulianDay 55000)
61 (ModifiedJulianDay 55000)
@@ -56,6 +64,7 @@ exampleTweet = Tweet { user = "bitemyapp"
56 , age = 10000
64 , age = 10000
57 , location = Location 40.12 (-71.34) }
65 , location = Location 40.12 (-71.34) }
58
66
67+otherTweet :: Tweet
59otherTweet = Tweet { user = "notmyapp"
68otherTweet = Tweet { user = "notmyapp"
60 , postDate = UTCTime
69 , postDate = UTCTime
61 (ModifiedJulianDay 55000)
70 (ModifiedJulianDay 55000)
@@ -66,17 +75,16 @@ otherTweet = Tweet { user = "notmyapp"
66
75
67insertData :: IO ()
76insertData :: IO ()
68insertData = do
77insertData = do
69− let encoded = encode exampleTweet
70 _ <- deleteExampleIndex
78 _ <- deleteExampleIndex
71− created <- createExampleIndex
79+ _ <- createExampleIndex
72− mappingCreated <- createMapping testServer testIndex testMapping TweetMapping
80+ _ <- createMapping testServer testIndex testMapping TweetMapping
73− docCreated <- indexDocument testServer testIndex testMapping exampleTweet (DocId "1")
81+ _ <- indexDocument testServer testIndex testMapping exampleTweet (DocId "1")
74 _ <- refreshIndex testServer testIndex
82 _ <- refreshIndex testServer testIndex
75 return ()
83 return ()
76
84
77insertOther :: IO ()
85insertOther :: IO ()
78insertOther = do
86insertOther = do
79− docCreated <- indexDocument testServer testIndex testMapping otherTweet (DocId "2")
87+ _ <- indexDocument testServer testIndex testMapping otherTweet (DocId "2")
80 _ <- refreshIndex testServer testIndex
88 _ <- refreshIndex testServer testIndex
81 return ()
89 return ()
82
90
@@ -110,6 +118,7 @@ main = hspec $ do
110 validateStatus resp 200
118 validateStatus resp 200
111 validateStatus deleteResp 200
119 validateStatus deleteResp 200
112
120
121+
113 describe "document API" $ do
122 describe "document API" $ do
114 it "indexes, gets, and then deletes the generated document" $ do
123 it "indexes, gets, and then deletes the generated document" $ do
115 _ <- insertData
124 _ <- insertData
@@ -118,6 +127,7 @@ main = hspec $ do
118 (responseBody docInserted) :: Either String (EsResult Tweet)
127 (responseBody docInserted) :: Either String (EsResult Tweet)
119 fmap _source newTweet `shouldBe` Right exampleTweet
128 fmap _source newTweet `shouldBe` Right exampleTweet
120
129
130+
121 describe "bulk API" $ do
131 describe "bulk API" $ do
122 it "inserts all documents we request" $ do
132 it "inserts all documents we request" $ do
123 _ <- insertData
133 _ <- insertData
@@ -128,7 +138,7 @@ main = hspec $ do
128 let secondDoc = BulkCreate (IndexName "twitter")
138 let secondDoc = BulkCreate (IndexName "twitter")
129 (MappingName "tweet") (DocId "3") (object ["name" .= String "bloo"])
139 (MappingName "tweet") (DocId "3") (object ["name" .= String "bloo"])
130 let stream = [firstDoc, secondDoc]
140 let stream = [firstDoc, secondDoc]
131− response <- bulk testServer stream
141+ _ <- bulk testServer stream
132 _ <- refreshIndex testServer testIndex
142 _ <- refreshIndex testServer testIndex
133 fDoc <- getDocument testServer testIndex testMapping (DocId "2")
143 fDoc <- getDocument testServer testIndex testMapping (DocId "2")
134 sDoc <- getDocument testServer testIndex testMapping (DocId "3")
144 sDoc <- getDocument testServer testIndex testMapping (DocId "3")
@@ -137,6 +147,7 @@ main = hspec $ do
137 fmap _source maybeFirst `shouldBe` Right firstTest
147 fmap _source maybeFirst `shouldBe` Right firstTest
138 fmap _source maybeSecond `shouldBe` Right secondTest
148 fmap _source maybeSecond `shouldBe` Right secondTest
139
149
150+
140 describe "query API" $ do
151 describe "query API" $ do
141 it "returns document for term query and identity filter" $ do
152 it "returns document for term query and identity filter" $ do
142 _ <- insertData
153 _ <- insertData
@@ -146,6 +157,13 @@ main = hspec $ do
146 myTweet <- searchTweet search
157 myTweet <- searchTweet search
147 myTweet `shouldBe` Right exampleTweet
158 myTweet `shouldBe` Right exampleTweet
148
159
160+ it "returns document for match query" $ do
161+ _ <- insertData
162+ let query = QueryMatchQuery $ mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
163+ let search = mkSearch (Just query) Nothing
164+ myTweet <- searchTweet search
165+ myTweet `shouldBe` Right exampleTweet
166+
149 describe "sorting" $ do
167 describe "sorting" $ do
150 it "returns documents in the right order" $ do
168 it "returns documents in the right order" $ do
151 _ <- insertData
169 _ <- insertData
@@ -159,6 +177,7 @@ main = hspec $ do
159 let myTweet = fmap (hitSource . head . hits . searchHits) result
177 let myTweet = fmap (hitSource . head . hits . searchHits) result
160 myTweet `shouldBe` Right otherTweet
178 myTweet `shouldBe` Right otherTweet
161
179
180+
162 describe "filtering API" $ do
181 describe "filtering API" $ do
163 it "returns document for composed boolmatch and identity" $ do
182 it "returns document for composed boolmatch and identity" $ do
164 _ <- insertData
183 _ <- insertData
@@ -258,7 +277,7 @@ main = hspec $ do
258 it "returns document for regexp filter" $ do
277 it "returns document for regexp filter" $ do
259 _ <- insertData
278 _ <- insertData
260 let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
279 let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
261− RegexpAll (CacheName "test") False (CacheKey "key")
280+ (RegexpFlags "ALL") (CacheName "test") False (CacheKey "key")
262 let search = mkSearch Nothing (Just filter)
281 let search = mkSearch Nothing (Just filter)
263 myTweet <- searchTweet search
282 myTweet <- searchTweet search
264 myTweet `shouldBe` Right exampleTweet
283 myTweet `shouldBe` Right exampleTweet
@@ -266,7 +285,7 @@ main = hspec $ do
266 it "doesn't return document for non-matching regexp filter" $ do
285 it "doesn't return document for non-matching regexp filter" $ do
267 _ <- insertData
286 _ <- insertData
268 let filter = RegexpFilter (FieldName "user")
287 let filter = RegexpFilter (FieldName "user")
269− (Regexp "boy") RegexpAll
288+ (Regexp "boy") (RegexpFlags "ALL")
270 (CacheName "test") False (CacheKey "key")
289 (CacheName "test") False (CacheKey "key")
271 let search = mkSearch Nothing (Just filter)
290 let search = mkSearch Nothing (Just filter)
272 searchExpectNoResults search
291 searchExpectNoResults search