Query Redis on two attributes
Somebody asked on StackOverflow how to query Redis for two attributes.
The use case is rather simple, the developer is storing a set of physical events, each of them has a start time and a finish time.
We would like to know all the events that are in progress at any given time.
The solution in raw Redis would involve creating two sorted sets, insert in one of those sets the events that start after the input time, insert in the other set all the events that end after the input time, and finally take the intersection of the two sets. The two sorted sets are not necessary anymore after we obtain our results, so they can be deleted.
This solution works, but it forces the developers to express the logic and all the steps necessary to obtain your results. Using procedural programming (expressing the steps necessary to obtain a result, like in this case) is more error-prone and complex than using declarative programming (expressing the result that you want, no how-to obtain it).
With zeeSQL, SQL and search by value for Redis we can obtain the same result procedurally, without thinking or taking care of temporary sorted sets in Redis.
In this case, we are going to use a zeeSQL secondary index.
The data format
Building on top of the StackOverflow question, we might expect that each event has a unique id, a start time, an end time, and maybe the number of participants.
We will express the two times as Unix timestamps.
Now is around ~1615402492 so only event:100
and event:101
are ongoing now.
With zeeSQL the very first step would be to create a new database where to store the data, we can create a database and called it EventsDB
.
After we have created the database, we can add a zeeSQL secondary index to it. zeeSQL will automatically add all the keys to the newly created secondary index.
With this command, we have created a new zeeSQL secondary index.
The secondary index is associated with the SQL table events
and stores all the Redis Hashes that start with the prefix event:
.
The index has 3 columns plus one.
The first column is the primary key and stores the Redis key of the hashes, in this case, it will store the string event:100
, event:101
, and event:102
.
The other columns are the start_time
, the end_time
, and the participants
column. Each one is an integer column and will store the respective fields of the Redis Hash.
As soon as the index is created, zeeSQL automatically populates it with the Redis Hash already in Redis.
We can immediately visualize the data.
Now we can try to answer the original question.
What are the events that are on-going now, or at any given time?
Simple.
No other data structure to manage, just a simple SQL query to write.
Use the standard SQLite time functions
You might not know what time it is now, in this case, you can use the standard SQLite functions.
Or maybe you need to answer more complex queries, like the original one.
We might want to know all the events that are on-going at the moment and will finish in one week.
We don't have any of them in our Redis instance, but we can add one.
zeeSQL automatically adds the new event to the secondary index.
And now we can express our more complex query:
Using all SQL
At this point, is useful to clarify that in zeeSQL you can use all the SQL provided by SQLite.
For instance, you may want to know how many people are registered for all the events that are ongoing right now.
Getting data as JSON
The last interesting step that I would like to make you aware, it is how to return data as JSON.
Working with Redis nested arrays is not always easy, and sometimes JSON is more convenient to deserialize.
In zeeSQL, you only need to add the JSON
flag, and your result will be returned as a JSON object.
Here we pipe the result in jq
for easier visualization.
Conclusions
zeeSQL solves a lot of problems when working with Redis.
In this particular case simplify the querying of data using a zeeSQL secondary index. This avoided the need to keeping separated indexes in Redis that can become cumbersome and error-prone.
This particular use case could have been solved without any Redis data structure, but simply using zeeSQL as the main datastore.
All the standard SQL commands are available like SELECT
, INSERT
, UPDATE
, and DELETE
.
zeeSQL by default works in-memory, like Redis, and it is blazing fast. Moreover, being completely integrated with Redis, zeeSQL supports AOF and RDB persistency.
Last updated