hedis-0.16.3: src/Database/Redis/ManualCommands/BF.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Database.Redis.ManualCommands.BF where
import Data.ByteString (ByteString)
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NE
import Database.Redis.Core
import Database.Redis.Types
import Database.Redis.Protocol
data BFInfo = BFInfo
{ bfInfoCapacity :: Integer
-- ^ Number of unique items that can be stored before scaling is required.
, bfInfoSize :: Integer
-- ^ Number of bytes allocated for the Bloom filter.
, bfInfoFilters :: Integer
-- ^ Number of sub-filters.
, bfInfoItems :: Integer
-- ^ Number of unique inserted items detected by the filter.
, bfInfoExpansion :: Integer
-- ^ Expansion rate used when a new sub-filter is created.
} deriving (Show, Eq)
instance RedisResult BFInfo where
decode r = do
fields <- decode r :: Either Reply [(ByteString, Integer)]
bfInfoCapacity <- decodeField "Capacity" fields
bfInfoSize <- decodeField "Size" fields
bfInfoFilters <- decodeField "Number of filters" fields
bfInfoItems <- decodeField "Number of items inserted" fields
bfInfoExpansion <- decodeField "Expansion rate" fields
pure BFInfo{..}
where
decodeField key fields = maybe (Left r) Right (lookup key fields)
data BFReserveOpts = BFReserveOpts
{ bfReserveExpansion :: Maybe Integer
-- ^ Expansion rate for newly created sub-filters once capacity is reached.
, bfReserveNonScaling :: Bool
-- ^ Prevent creation of additional sub-filters when initial capacity is reached.
} deriving (Show, Eq)
defaultBFReserveOpts :: BFReserveOpts
defaultBFReserveOpts = BFReserveOpts
{ bfReserveExpansion = Nothing
, bfReserveNonScaling = False
}
data BFInsertOpts = BFInsertOpts
{ bfInsertCapacity :: Maybe Integer
-- ^ Initial capacity to use if a new filter is created.
, bfInsertError :: Maybe Double
-- ^ Desired false positive probability to use if a new filter is created.
, bfInsertExpansion :: Maybe Integer
-- ^ Expansion rate for additional sub-filters.
, bfInsertNoCreate :: Bool
-- ^ Return an error instead of creating the filter when the key does not exist.
, bfInsertNonScaling :: Bool
-- ^ Prevent creation of additional sub-filters when capacity is reached.
} deriving (Show, Eq)
defaultBFInsertOpts :: BFInsertOpts
defaultBFInsertOpts = BFInsertOpts
{ bfInsertCapacity = Nothing
, bfInsertError = Nothing
, bfInsertExpansion = Nothing
, bfInsertNoCreate = False
, bfInsertNonScaling = False
}
bfReserveOptsToArgs :: BFReserveOpts -> [ByteString]
bfReserveOptsToArgs BFReserveOpts{..} =
expansionArg ++ nonScalingArg
where
expansionArg = maybe [] (\expansion -> ["EXPANSION", encode expansion]) bfReserveExpansion
nonScalingArg = ["NONSCALING" | bfReserveNonScaling]
bfInsertOptsToArgs :: BFInsertOpts -> [ByteString]
bfInsertOptsToArgs BFInsertOpts{..} =
capacityArg ++ errorArg ++ expansionArg ++ noCreateArg ++ nonScalingArg
where
capacityArg = maybe [] (\capacity -> ["CAPACITY", encode capacity]) bfInsertCapacity
errorArg = maybe [] (\err -> ["ERROR", encode err]) bfInsertError
expansionArg = maybe [] (\expansion -> ["EXPANSION", encode expansion]) bfInsertExpansion
noCreateArg = ["NOCREATE" | bfInsertNoCreate]
nonScalingArg = ["NONSCALING" | bfInsertNonScaling]
-- |Adds an item to a Bloom filter (<https://redis.io/commands/bf.add>).
--
-- A filter is created automatically if the key does not exist.
--
-- /O(k)/, where /k/ is the number of hash functions used by the last sub-filter.
--
-- Since RedisBloom 1.0.0
bfadd
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> ByteString -- ^ Item to add to the Bloom filter.
-> m (f Bool)
bfadd key item = sendRequest ["BF.ADD", key, item]
-- |Returns the cardinality of a Bloom filter (<https://redis.io/commands/bf.card>).
--
-- Returns @0@ when the key does not exist.
--
-- /O(1)/
--
-- Since RedisBloom 2.4.4
bfcard
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f Integer)
bfcard key = sendRequest ["BF.CARD", key]
-- |Determines whether an item was added to a Bloom filter (<https://redis.io/commands/bf.exists>).
--
-- Returns 'False' when the key does not exist or the item was definitely not added.
--
-- /O(k)/, where $k$ is the number of hash functions used by the last sub-filter.
--
-- Since RedisBloom 1.0.0
bfexists
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> ByteString -- ^ Item to check.
-> m (f Bool)
bfexists key item = sendRequest ["BF.EXISTS", key, item]
-- |Returns information about a Bloom filter (<https://redis.io/commands/bf.info>).
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfinfo
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f BFInfo)
bfinfo key = sendRequest ["BF.INFO", key]
-- |Returns the configured capacity of a Bloom filter (<https://redis.io/commands/bf.info>).
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfinfoCapacity
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f [Integer])
bfinfoCapacity key = sendRequest ["BF.INFO", key, "CAPACITY"]
-- |Returns the size in bytes of a Bloom filter (<https://redis.io/commands/bf.info>).
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfinfoSize
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f [Integer])
bfinfoSize key = sendRequest ["BF.INFO", key, "SIZE"]
-- |Returns the number of sub-filters in a Bloom filter (<https://redis.io/commands/bf.info>).
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfinfoFilters
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f [Integer])
bfinfoFilters key = sendRequest ["BF.INFO", key, "FILTERS"]
-- |Returns the number of unique inserted items detected by a Bloom filter (<https://redis.io/commands/bf.info>).
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfinfoItems
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f [Integer])
bfinfoItems key = sendRequest ["BF.INFO", key, "ITEMS"]
-- |Returns the expansion rate of a Bloom filter (<https://redis.io/commands/bf.info>).
--
-- /O(1)/
--
-- Returns Nothing for the non scaling filters.
--
-- Since RedisBloom 1.0.0
bfinfoExpansion
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> m (f [Maybe Integer])
bfinfoExpansion key = sendRequest ["BF.INFO", key, "EXPANSION"]
-- |Adds one or more items to a Bloom filter, creating it when needed (<https://redis.io/commands/bf.insert>).
--
-- This is equivalent to inserting with default options and automatic creation enabled.
--
-- /O(kn)/, where /k/ is the number of hash functions and /n/ is the number of items.
--
-- Since RedisBloom 1.0.0
bfinsert
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> NonEmpty ByteString -- ^ Items to add.
-> m (f [Bool])
bfinsert key items = bfinsertOpts key items defaultBFInsertOpts
-- |Adds one or more items to a Bloom filter, creating it when needed (<https://redis.io/commands/bf.insert>).
--
-- /O(kn)/, where /k/ is the number of hash functions and /n/ is the number of items.
--
-- Since RedisBloom 1.0.0
bfinsertOpts
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> NonEmpty ByteString -- ^ Items to add.
-> BFInsertOpts -- ^ Optional creation and scaling parameters.
-> m (f [Bool])
bfinsertOpts key items opts =
sendRequest $ ["BF.INSERT", key] ++ bfInsertOptsToArgs opts ++ ["ITEMS"] ++ NE.toList items
-- |Adds one or more items to a Bloom filter (<https://redis.io/commands/bf.madd>).
--
-- A filter is created automatically if the key does not exist.
--
-- /O(kn)/, where /k/ is the number of hash functions and /n/ is the number of items.
--
-- Since RedisBloom 1.0.0
bfmadd
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> NonEmpty ByteString -- ^ Items to add.
-> m (f [Bool])
bfmadd key items = sendRequest $ ["BF.MADD", key] ++ NE.toList items
-- |Checks whether one or more items were added to a Bloom filter (<https://redis.io/commands/bf.mexists>).
--
-- A 'False' result means the item is definitely absent, or the key does not exist.
--
-- /O(kn)/, where /k/ is the number of hash functions and /n/ is the number of items.
--
-- Since RedisBloom 1.0.0
bfmexists
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter.
-> NonEmpty ByteString -- ^ Items to check.
-> m (f [Bool])
bfmexists key items = sendRequest $ ["BF.MEXISTS", key] ++ NE.toList items
-- |Creates an empty Bloom filter (<https://redis.io/commands/bf.reserve>).
--
-- The filter will fail if the key already exists.
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfreserve
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter to create.
-> Double -- ^ Desired false positive probability, between @0@ and @1@.
-> Integer -- ^ Initial capacity.
-> m (f Status)
bfreserve key errorRate capacity = bfreserveOpts key errorRate capacity defaultBFReserveOpts
-- |Creates an empty Bloom filter (<https://redis.io/commands/bf.reserve>).
--
-- /O(1)/
--
-- Since RedisBloom 1.0.0
bfreserveOpts
:: (RedisCtx m f)
=> ByteString -- ^ Key of the Bloom filter to create.
-> Double -- ^ Desired false positive probability, between @0@ and @1@.
-> Integer -- ^ Initial capacity.
-> BFReserveOpts -- ^ Scaling options for the reserved filter.
-> m (f Status)
bfreserveOpts key errorRate capacity opts =
sendRequest $ ["BF.RESERVE", key, encode errorRate, encode capacity] ++ bfReserveOptsToArgs opts