Stal is a small library (54 lines of code at the time of writing this article) that abstracts multi-step set operations in Redis. To illustrate what it does, consider the trivial example of computing the difference between one set and the intersection of two other sets. This is what you can do with Redis:

    SDIFF C temp1

The first command computes the intersection of sets A and B, then stores the result in temp1. The next command computes the difference between sets C and temp1 and returns the result. The goal is met, but you may want to delete the temp1 key as it’s no longer needed. In addition, for atomicity, you may want to wrap those commands in a MULTI/EXEC call. This is what we would have so far:

    SDIFF C temp1
    DEL temp1

Finally, for performance, you may want to pipeline all those commands. This is what you would end up with if you use a client that supports pipelining:

    redis.queue("SINTERSTORE", "temp1", "A", "B")
    redis.queue("SDIFF", "C", "temp1")
    redis.queue("DEL", "temp1")

I’m using Redic in the example.

This is all very simple and efficient, and building these operations by hand is a no-brainer. If you want to create more complex queries, and particularly if you want to build them on the fly, it can get a bit more complicated.

With Stal, you can build that query with an s-expression:

    Stal.solve(redis, [:SDIFF, "C", [:SINTER, "A", "B"]])

Stal takes care of pipelining the commands in a MULTI/EXEC block, as well as generating and deleting any temporary keys. But most importantly, it makes it very easy to incrementally build complex queries.

Ohm is an object-hash mapper that is almost as old as Redis itself. It has support for complex queries, and until recently it shipped with code to ease that process. By relying on Stal, its code went from 600 to 516 lines of code. Stal itself is tiny, just 54 lines of code, so the net change for Ohm was 30 lines less.

Stal can be used directly or as a valuable building block for other libraries.