Skip to content

Instantly share code, notes, and snippets.

@sankarcheppali
Created May 16, 2023 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sankarcheppali/579de3a02b88dc6af5986567825bae4c to your computer and use it in GitHub Desktop.
Save sankarcheppali/579de3a02b88dc6af5986567825bae4c to your computer and use it in GitHub Desktop.
Using redis bloom filters with Spring redis-template
package net.icircuit.bf.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toSet;
@Component
public class RedisBloomFilter {
RedisTemplate<String, String> redisTemplate;
/**
* spring redis template backed by jedis driver
*/
@Autowired
public RedisBloomFilter(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
private static final String BF_MULTI_ADD = "BF.MADD";
private static final String BF_MULTI_FIND = "BF.MEXISTS";
/**
* returns entries that were not present previously in the bloom filter and were added
*/
public Set<String> put(String filterName, Set<String> entries) {
return runCmd(BF_MULTI_ADD, filterName, entries);
}
/**
* returns entries that were present in the bloom filter
*/
public Set<String> get(String filterName, Set<String> entries) {
return runCmd(BF_MULTI_FIND, filterName, entries);
}
private Set<String> runCmd(String bfOp, String key, Set<String> entries) {
return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
final String[] entriesArr = entries.toArray(new String[0]);
byte[][] args = Stream.concat(Stream.of(key), Arrays.stream(entriesArr))
.map(String::getBytes)
.toArray(byte[][]::new);
List<Number> result = (List<Number>) connection.execute(bfOp, args);
return IntStream.range(0, result.size())
.filter(index -> result.get(index).intValue() == 1)
.mapToObj(index -> entriesArr[index])
.collect(toSet());
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment