mirror of
https://github.com/typeable/bloodhound.git
synced 2025-01-07 15:22:21 +03:00
Merge pull request #25 from unthingable/moar-range
add Double/Text typed ranges
This commit is contained in:
commit
20ed65b52e
32
README.md
32
README.md
@ -321,7 +321,7 @@ let sndOp = BulkIndex testIndex
|
||||
-- Some explanation, the final "Value" type that BulkIndex,
|
||||
-- BulkCreate, and BulkUpdate accept is the actual document
|
||||
-- data that your operation applies to. BulkDelete doesn't
|
||||
-- take a value because it's just deleting whatever DocId
|
||||
-- take a value because it's just deleting whatever DocId
|
||||
-- you pass.
|
||||
|
||||
-- list of bulk operations
|
||||
@ -636,31 +636,46 @@ IdsFilter (MappingName "tweet") [DocId "1"]
|
||||
|
||||
#### Range Filter
|
||||
|
||||
##### Full Range
|
||||
|
||||
``` {.haskell}
|
||||
|
||||
-- RangeFilter :: FieldName
|
||||
-- -> Either HalfRange Range
|
||||
-- -> RangeValue
|
||||
-- -> RangeExecution
|
||||
-- -> Cache -> Filter
|
||||
|
||||
let filter = RangeFilter (FieldName "age")
|
||||
(Right (RangeLtGt (LessThan 100000.0) (GreaterThan 1000.0)))
|
||||
(RangeGtLt (GreaterThan 1000.0) (LessThan 100000.0))
|
||||
RangeExecutionIndex False
|
||||
|
||||
```
|
||||
|
||||
##### Half Range
|
||||
|
||||
``` {.haskell}
|
||||
|
||||
let filter = RangeFilter (FieldName "age")
|
||||
(Left (HalfRangeLt (LessThan 100000.0)))
|
||||
(RangeLte (LessThanEq 100000.0))
|
||||
RangeExecutionIndex False
|
||||
|
||||
```
|
||||
|
||||
##### Date Ranges
|
||||
|
||||
Date ranges are expressed in UTCTime. Date ranges use the same range bound constructors as numerics, except that they end in "D".
|
||||
|
||||
Note that compatibility with ES is tested only down to seconds.
|
||||
|
||||
``` {.haskell}
|
||||
|
||||
let filter = RangeFilter (FieldName "postDate")
|
||||
(RangeDateGtLte
|
||||
(GreaterThanD (UTCTime
|
||||
(ModifiedJulianDay 55000)
|
||||
(secondsToDiffTime 9)))
|
||||
(LessThanEqD (UTCTime
|
||||
(ModifiedJulianDay 55000)
|
||||
(secondsToDiffTime 11))))
|
||||
RangeExecutionIndex False
|
||||
```
|
||||
|
||||
#### Regexp Filter
|
||||
|
||||
``` {.haskell}
|
||||
@ -928,4 +943,3 @@ Photo Origin
|
||||
============
|
||||
|
||||
Photo from HA! Designs: <https://www.flickr.com/photos/hadesigns/>
|
||||
|
||||
|
@ -24,9 +24,7 @@
|
||||
module Database.Bloodhound.Types
|
||||
( defaultCache
|
||||
, defaultIndexSettings
|
||||
, halfRangeToKV
|
||||
, mkSort
|
||||
, rangeToKV
|
||||
, showText
|
||||
, unpackId
|
||||
, mkMatchQuery
|
||||
@ -69,13 +67,16 @@ module Database.Bloodhound.Types
|
||||
, DistanceRange(..)
|
||||
, OptimizeBbox(..)
|
||||
, LatLon(..)
|
||||
, Range(..)
|
||||
, HalfRange(..)
|
||||
, RangeValue(..)
|
||||
, RangeExecution(..)
|
||||
, LessThan(..)
|
||||
, LessThanEq(..)
|
||||
, GreaterThan(..)
|
||||
, GreaterThanEq(..)
|
||||
, LessThanD(..)
|
||||
, LessThanEqD(..)
|
||||
, GreaterThanD(..)
|
||||
, GreaterThanEqD(..)
|
||||
, Regexp(..)
|
||||
, RegexpFlags(..)
|
||||
, RegexpFlag(..)
|
||||
@ -636,10 +637,10 @@ data RegexpQuery =
|
||||
|
||||
data RangeQuery =
|
||||
RangeQuery { rangeQueryField :: FieldName
|
||||
, rangeQueryRange :: Either HalfRange Range
|
||||
, rangeQueryRange :: RangeValue
|
||||
, rangeQueryBoost :: Boost } deriving (Eq, Show)
|
||||
|
||||
mkRangeQuery :: FieldName -> Either HalfRange Range -> RangeQuery
|
||||
mkRangeQuery :: FieldName -> RangeValue -> RangeQuery
|
||||
mkRangeQuery f r = RangeQuery f r (Boost 1.0)
|
||||
|
||||
data SimpleQueryStringQuery =
|
||||
@ -922,7 +923,7 @@ data Filter = AndFilter [Filter] Cache
|
||||
| LimitFilter Int
|
||||
| MissingFilter FieldName Existence NullValue
|
||||
| PrefixFilter FieldName PrefixValue Cache
|
||||
| RangeFilter FieldName (Either HalfRange Range) RangeExecution Cache
|
||||
| RangeFilter FieldName RangeValue RangeExecution Cache
|
||||
| RegexpFilter FieldName Regexp RegexpFlags CacheName Cache CacheKey
|
||||
| TermFilter Term Cache
|
||||
deriving (Eq, Show)
|
||||
@ -930,22 +931,6 @@ data Filter = AndFilter [Filter] Cache
|
||||
data ZeroTermsQuery = ZeroTermsNone
|
||||
| ZeroTermsAll deriving (Eq, Show)
|
||||
|
||||
-- lt, lte | gt, gte
|
||||
newtype LessThan = LessThan Double deriving (Eq, Show)
|
||||
newtype LessThanEq = LessThanEq Double deriving (Eq, Show)
|
||||
newtype GreaterThan = GreaterThan Double deriving (Eq, Show)
|
||||
newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show)
|
||||
|
||||
data HalfRange = HalfRangeLt LessThan
|
||||
| HalfRangeLte LessThanEq
|
||||
| HalfRangeGt GreaterThan
|
||||
| HalfRangeGte GreaterThanEq deriving (Eq, Show)
|
||||
|
||||
data Range = RangeLtGt LessThan GreaterThan
|
||||
| RangeLtGte LessThan GreaterThanEq
|
||||
| RangeLteGt LessThanEq GreaterThan
|
||||
| RangeLteGte LessThanEq GreaterThanEq deriving (Eq, Show)
|
||||
|
||||
data RangeExecution = RangeExecutionIndex
|
||||
| RangeExecutionFielddata deriving (Eq, Show)
|
||||
|
||||
@ -962,19 +947,52 @@ data RegexpFlag = AnyString
|
||||
| Intersection
|
||||
| Interval deriving (Eq, Show)
|
||||
|
||||
halfRangeToKV :: HalfRange -> (Text, Double)
|
||||
halfRangeToKV (HalfRangeLt (LessThan n)) = ("lt", n)
|
||||
halfRangeToKV (HalfRangeLte (LessThanEq n)) = ("lte", n)
|
||||
halfRangeToKV (HalfRangeGt (GreaterThan n)) = ("gt", n)
|
||||
halfRangeToKV (HalfRangeGte (GreaterThanEq n)) = ("gte", n)
|
||||
newtype LessThan = LessThan Double deriving (Eq, Show)
|
||||
newtype LessThanEq = LessThanEq Double deriving (Eq, Show)
|
||||
newtype GreaterThan = GreaterThan Double deriving (Eq, Show)
|
||||
newtype GreaterThanEq = GreaterThanEq Double deriving (Eq, Show)
|
||||
|
||||
rangeToKV :: Range -> (Text, Double, Text, Double)
|
||||
rangeToKV (RangeLtGt (LessThan m) (GreaterThan n)) = ("lt", m, "gt", n)
|
||||
rangeToKV (RangeLtGte (LessThan m) (GreaterThanEq n)) = ("lt", m, "gte", n)
|
||||
rangeToKV (RangeLteGt (LessThanEq m) (GreaterThan n)) = ("lte", m, "gt", n)
|
||||
rangeToKV (RangeLteGte (LessThanEq m) (GreaterThanEq n)) = ("lte", m, "gte", n)
|
||||
newtype LessThanD = LessThanD UTCTime deriving (Eq, Show)
|
||||
newtype LessThanEqD = LessThanEqD UTCTime deriving (Eq, Show)
|
||||
newtype GreaterThanD = GreaterThanD UTCTime deriving (Eq, Show)
|
||||
newtype GreaterThanEqD = GreaterThanEqD UTCTime deriving (Eq, Show)
|
||||
|
||||
-- phew. Coulda used Agda style case breaking there but, you know, whatever. :)
|
||||
data RangeValue = RangeDateLte LessThanEqD
|
||||
| RangeDateLt LessThanD
|
||||
| RangeDateGte GreaterThanEqD
|
||||
| RangeDateGt GreaterThanD
|
||||
| RangeDateGtLt GreaterThanD LessThanD
|
||||
| RangeDateGteLte GreaterThanEqD LessThanEqD
|
||||
| RangeDateGteLt GreaterThanEqD LessThanD
|
||||
| RangeDateGtLte GreaterThanD LessThanEqD
|
||||
| RangeDoubleLte LessThanEq
|
||||
| RangeDoubleLt LessThan
|
||||
| RangeDoubleGte GreaterThanEq
|
||||
| RangeDoubleGt GreaterThan
|
||||
| RangeDoubleGtLt GreaterThan LessThan
|
||||
| RangeDoubleGteLte GreaterThanEq LessThanEq
|
||||
| RangeDoubleGteLt GreaterThanEq LessThan
|
||||
| RangeDoubleGtLte GreaterThan LessThanEq
|
||||
deriving (Eq, Show)
|
||||
|
||||
rangeValueToPair :: RangeValue -> [Pair]
|
||||
rangeValueToPair rv = case rv of
|
||||
RangeDateLte (LessThanEqD t) -> ["lte" .= t]
|
||||
RangeDateGte (GreaterThanEqD t) -> ["gte" .= t]
|
||||
RangeDateLt (LessThanD t) -> ["lt" .= t]
|
||||
RangeDateGt (GreaterThanD t) -> ["gt" .= t]
|
||||
RangeDateGteLte (GreaterThanEqD l) (LessThanEqD g) -> ["gte" .= l, "lte" .= g]
|
||||
RangeDateGtLte (GreaterThanD l) (LessThanEqD g) -> ["gt" .= l, "lte" .= g]
|
||||
RangeDateGteLt (GreaterThanEqD l) (LessThanD g) -> ["gte" .= l, "lt" .= g]
|
||||
RangeDateGtLt (GreaterThanD l) (LessThanD g) -> ["gt" .= l, "lt" .= g]
|
||||
RangeDoubleLte (LessThanEq t) -> ["lte" .= t]
|
||||
RangeDoubleGte (GreaterThanEq t) -> ["gte" .= t]
|
||||
RangeDoubleLt (LessThan t) -> ["lt" .= t]
|
||||
RangeDoubleGt (GreaterThan t) -> ["gt" .= t]
|
||||
RangeDoubleGteLte (GreaterThanEq l) (LessThanEq g) -> ["gte" .= l, "lte" .= g]
|
||||
RangeDoubleGtLte (GreaterThan l) (LessThanEq g) -> ["gt" .= l, "lte" .= g]
|
||||
RangeDoubleGteLt (GreaterThanEq l) (LessThan g) -> ["gte" .= l, "lt" .= g]
|
||||
RangeDoubleGtLt (GreaterThan l) (LessThan g) -> ["gt" .= l, "lt" .= g]
|
||||
|
||||
data Term = Term { termField :: Text
|
||||
, termValue :: Text } deriving (Eq, Show)
|
||||
@ -1338,24 +1356,11 @@ instance ToJSON Filter where
|
||||
object [fieldName .= fieldValue
|
||||
, "_cache" .= cache]]
|
||||
|
||||
toJSON (RangeFilter (FieldName fieldName) (Left halfRange) rangeExecution cache) =
|
||||
toJSON (RangeFilter (FieldName fieldName) rangeValue rangeExecution cache) =
|
||||
object ["range" .=
|
||||
object [fieldName .=
|
||||
object [rqFKey .= rqFVal]
|
||||
object [ fieldName .= object (rangeValueToPair rangeValue)
|
||||
, "execution" .= toJSON rangeExecution
|
||||
, "_cache" .= cache]]
|
||||
where
|
||||
(rqFKey, rqFVal) = halfRangeToKV halfRange
|
||||
|
||||
toJSON (RangeFilter (FieldName fieldName) (Right range) rangeExecution cache) =
|
||||
object ["range" .=
|
||||
object [fieldName .=
|
||||
object [lessKey .= lessVal
|
||||
, greaterKey .= greaterVal]
|
||||
, "execution" .= toJSON rangeExecution
|
||||
, "_cache" .= cache]]
|
||||
where
|
||||
(lessKey, lessVal, greaterKey, greaterVal) = rangeToKV range
|
||||
|
||||
toJSON (RegexpFilter (FieldName fieldName)
|
||||
(Regexp regexText) flags (CacheName cacheName) cache (CacheKey cacheKey)) =
|
||||
@ -1549,18 +1554,9 @@ instance ToJSON QueryStringQuery where
|
||||
|
||||
|
||||
instance ToJSON RangeQuery where
|
||||
toJSON (RangeQuery (FieldName fieldName) (Right range) boost) =
|
||||
toJSON (RangeQuery (FieldName fieldName) range boost) =
|
||||
object [ fieldName .= conjoined ]
|
||||
where conjoined = [ "boost" .= toJSON boost
|
||||
, lessKey .= lessVal
|
||||
, greaterKey .= greaterVal ]
|
||||
(lessKey, lessVal, greaterKey, greaterVal) = rangeToKV range
|
||||
|
||||
toJSON (RangeQuery (FieldName fieldName) (Left halfRange) boost) =
|
||||
object [ fieldName .= conjoined ]
|
||||
where conjoined = [ "boost" .= toJSON boost
|
||||
, rqKey .= rqVal ]
|
||||
(rqKey, rqVal) = halfRangeToKV halfRange
|
||||
where conjoined = [ "boost" .= toJSON boost ] ++ (rangeValueToPair range)
|
||||
|
||||
|
||||
instance ToJSON PrefixQuery where
|
||||
|
@ -432,15 +432,31 @@ main = hspec $ do
|
||||
myTweet <- searchTweet search
|
||||
myTweet `shouldBe` Right exampleTweet
|
||||
|
||||
it "returns document for range filter" $ do
|
||||
it "returns document for Double range filter" $ do
|
||||
_ <- insertData
|
||||
let filter = RangeFilter (FieldName "age")
|
||||
(Right (RangeLtGt (LessThan 100000.0) (GreaterThan 1000.0)))
|
||||
(RangeDoubleGtLt (GreaterThan 1000.0) (LessThan 100000.0))
|
||||
RangeExecutionIndex False
|
||||
let search = mkSearch Nothing (Just filter)
|
||||
myTweet <- searchTweet search
|
||||
myTweet `shouldBe` Right exampleTweet
|
||||
|
||||
it "returns document for UTCTime date filter" $ do
|
||||
_ <- insertData
|
||||
let filter = RangeFilter (FieldName "postDate")
|
||||
(RangeDateGtLt
|
||||
(GreaterThanD (UTCTime
|
||||
(ModifiedJulianDay 55000)
|
||||
(secondsToDiffTime 9)))
|
||||
(LessThanD (UTCTime
|
||||
(ModifiedJulianDay 55000)
|
||||
(secondsToDiffTime 11))))
|
||||
RangeExecutionIndex False
|
||||
let search = mkSearch Nothing (Just filter)
|
||||
myTweet <- searchTweet search
|
||||
myTweet `shouldBe` Right exampleTweet
|
||||
|
||||
|
||||
it "returns document for regexp filter" $ do
|
||||
_ <- insertData
|
||||
let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
|
||||
|
Loading…
Reference in New Issue
Block a user