Skip to content

Instantly share code, notes, and snippets.

@naile
Last active January 21, 2022 05:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save naile/96de4e9548c7b5fd6c0614009ffec755 to your computer and use it in GitHub Desktop.
Save naile/96de4e9548c7b5fd6c0614009ffec755 to your computer and use it in GitHub Desktop.
Extension methods for using RedisBloom module with StackExchange.Redis

RedisBloom is an awesome Redis module that adds several probabilistic data structures.

Recently found myself needing to use it in .NET Core with the StackExchange.Redis Client.

Couldn't find any ready to use implementation so I put together some extension methods for Bloom Filter and Top-K. Maybe it's useful for someone else!

Example usage:

using StackExchange.Redis

var multiplexer = ConnectionMultiplexer.Connect("localhost");
var database = multiplexer.GetDatabase;

//Bloom Filter
await database.BloomAddAsync("newfilter", "foo"); // => true (item was added)
await database.BloomExistsAsync("newfilter", "foo") // => true (item most likely exists)
await database.BloomExistsAsync("newfilter", "bar") // => false (item do not exist)

//Top-K
await database.TopKReserveAsync("topk", 2); // reserve filter
await database.TopKAddAsync("topk", "item1"); // => null (no item was dropped)
await database.TopKAddAsync("topk", "item2"); // => null (no item was dropped)
await database.TopKAddAsync("topk", "item3"); // => null (no item was dropped)
await database.TopKAddAsync("topk", "item3"); // => item1 (dropped item)

await database.TopKListAsync("topk") // => ["item2", "item3"] (topk list)

RedisBloom documentation: https://oss.redislabs.com/redisbloom/ StackExchange Redis documentation: https://stackexchange.github.io/StackExchange.Redis/

public static class RedisBloomExtensions
{
public static async Task BloomReserveAsync(this IDatabaseAsync db, RedisKey key, double errorRate, int initialCapacity)
=> await db.ExecuteAsync("BF.RESERVE", key, errorRate, initialCapacity);
public static async Task<bool> BloomAddAsync(this IDatabaseAsync db, RedisKey key, RedisValue value)
=> (bool)await db.ExecuteAsync("BF.ADD", key, value);
public static async Task<bool[]> BloomAddAsync(this IDatabaseAsync db, RedisKey key, IEnumerable<RedisValue> values)
=> (bool[])await db.ExecuteAsync("BF.MADD", values.Cast<object>().Prepend(key).ToArray());
public static async Task<bool> BloomExistsAsync(this IDatabaseAsync db, RedisKey key, RedisValue value)
=> (bool)await db.ExecuteAsync("BF.EXISTS", key, value);
public static async Task<bool[]> BloomExistsAsync(this IDatabaseAsync db, RedisKey key, IEnumerable<RedisValue> values)
=> (bool[])await db.ExecuteAsync("BF.MEXISTS", values.Cast<object>().Prepend(key).ToArray());
public static async Task TopKReserveAsync(this IDatabaseAsync db, RedisKey key, int topK, int width = 8, int depth = 7, double decay = 0.9)
=> await db.ExecuteAsync("TOPK.RESERVE", key, topK, width, depth, decay);
public static async Task<RedisValue> TopKAddAsync(this IDatabaseAsync db, RedisKey key, RedisValue value)
=> (RedisValue)await db.ExecuteAsync("TOPK.ADD", key, value);
public static async Task<RedisValue[]> TopKAddAsync(this IDatabaseAsync db, RedisKey key, IEnumerable<RedisValue> values)
=> (RedisValue[])await db.ExecuteAsync("TOPK.ADD", values.Cast<object>().Prepend(key).ToArray());
public static async Task<RedisValue> TopKIncrementAsync(this IDatabaseAsync db, RedisKey key, RedisValue value, int increment)
=> (RedisValue)await db.ExecuteAsync("TOPK.INCRBY", key, value, increment);
public static async Task<RedisValue[]> TopKIncrementAsync(this IDatabaseAsync db, RedisKey key, (RedisValue value, int increment)[] increments)
=> (RedisValue[])await db.ExecuteAsync("TOPK.INCRBY", increments.SelectMany(i => new object[] { i.value, i.increment }).Prepend(key).ToArray());
public static async Task<RedisValue[]> TopKListAsync(this IDatabaseAsync db, RedisKey key)
=> (RedisValue[])await db.ExecuteAsync("TOPK.LIST", key);
public static async Task<bool> TopKQueryAsync(this IDatabaseAsync db, RedisKey key, RedisValue value)
=> (bool)await db.ExecuteAsync("TOPK.QUERY", key, value);
public static async Task<bool[]> TopKQueryAsync(this IDatabaseAsync db, RedisKey key, RedisValue[] values)
=> (bool[])await db.ExecuteAsync("TOPK.QUERY", values.Cast<object>().Prepend(key).ToArray());
public static async Task<int> TopKCountAsync(this IDatabaseAsync db, RedisKey key, RedisValue value)
=> (int)await db.ExecuteAsync("TOPK.COUNT", key, value);
public static async Task<int[]> TopKCountAsync(this IDatabaseAsync db, RedisKey key, RedisValue[] values)
=> (int[])await db.ExecuteAsync("TOPK.COUNT", values.Cast<object>().Prepend(key).ToArray());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment