How to feed Set operations represented as symbols to CLI/pyredis?

13 views
Skip to first unread message

Tharmalingam Viswanathan

unread,
Jan 18, 2018, 5:07:10 AM1/18/18
to Redis DB
Hi,

Perhaps this is a simple question for the experts, but I am struggling to solve this for a while now.
Let's say I have these sets stored in redis:  S1, S2, and S3.

Below is what I want to get evaluated within redis (without having to taking the route that involves pulling independent sets into numpy and operate on them):
(S1 + S2) - S3

i.e., Intersection of S1 and S2, and remove elements from S3.

So essentially I want to get a solution to get a much more complex operations like that evaluated (involves intersection and NOR stuff like that).
I would greatly appreciate if you could throw some lights on the above.

Thanks,
Tharma

Michel Martens

unread,
Jan 18, 2018, 5:27:39 AM1/18/18
to redi...@googlegroups.com
You can use set operations and store intermediate values, for example:

SUNIONSTORE temp S1 S2
SDIFF temp S3

Then you can delete the `temp` key. If that works for you, an
optimization would be to wrap those commands in a MULTI/EXEC block:

MULTI
SUNIONSTORE temp S1 S2
SDIFF temp S3
DEL temp
EXEC

At some point I had to do something similar but without knowing in
advance the operations I needed to perform. I wrote a Lua script
called Stal (https://github.com/soveran/stal) that receives an
s-expression in the form of a JSON array and returns the result. For
example, let's say you want to express the above operation as an
s-expression:

(SDIFF (SUNION S1 S2) S3)

Translated to a JSON array, it would be like this:

["SDIFF", ["SUNION", "S1", "S2"], "S3"]

And that's what you can ask Stal to solve:

$ redis-cli --eval stal.lua , '["SDIFF", ["SUNION", "S1", "S2"], "S3"]'

Stal will take care of creating and removing any temporary keys.

There are two wrappers available, one for Ruby and one for Crystal,
that allow you interact with Stal. Writing a wrapper for Python should
be trivial if you think this solves your problem.
> --
> You received this message because you are subscribed to the Google Groups
> "Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to redis-db+u...@googlegroups.com.
> To post to this group, send email to redi...@googlegroups.com.
> Visit this group at https://groups.google.com/group/redis-db.
> For more options, visit https://groups.google.com/d/optout.

Tharmalingam Viswanathan

unread,
Jan 18, 2018, 11:58:04 AM1/18/18
to Redis DB
Thank you so much, Michel.
I found your stal.lua script solution is what I was looking for. 

Here is how it finally ended up like :

from redis_lua import load_script
import redis

# Loads the 'create_foo.lua' in the 'lua' directory.
script = load_script(name='stal', path='./')

redis_client
= redis.StrictRedis(host='xx..xx..xx..xx', port=6379, db=0)

redis_client
.sadd  ('A', 1 ,2, 3)
redis_client
.sadd  ('B', 2 ,3, 4)
redis_client
.sadd  ('C', 3 ,4, 5)


# Run the script with the specified arguments.
foo = script.get_runner(client=redis_client)(
   
expr = '["SDIFF", ["SUNION", "A", "C"], "B"]'
)

print (foo)


Thank you!!! Really appreciated.
Tharma

Michel Martens

unread,
Jan 18, 2018, 12:54:48 PM1/18/18
to redi...@googlegroups.com
Glad it worked!
Reply all
Reply to author
Forward
0 new messages