For the API I’m developing, I’m in the process of saying "goodbye" to Mongo and I’d like to use Redis as my primary database.
The authentication of my API is based on HTTP basic auth where user name is essentially an API key. Currently, I have the following user
data structure in Mongo (redacted for brevity):
{
"_id" : ObjectId("6001a80743ceef211d9dee56"),
"user_id" : 123,
"email" : "[email protected]",
"keys" : [
{
"key" : "mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2",
"usage" : 0
},
{
"key" : "wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn",
"usage" : 40
}
]
}
When the request comes in I query Mongo like the following:
db.users.find({
"keys.key": "mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2"
});
How do I model the data in Redis to achieve pretty much the same result? My main concern is to have a single query which will give me the entire User account like in the example above. If that was not the case, I could have the following structures:
api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2 : 123
api:wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn : 123
So the api key maps to the user ID. And than another set of data with the actual user data like so:
user:123 : name Bob email [email protected]
That poses a problem because I need to query Redis twice. First I need to GET the api key:
GET api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2
which gives me user ID 123
and only than I can get user by ID:
HGETALL user:123
Is there any way I could model the data in Redis and query by api key and get the entire User data?
2
Answers
MongoDB works with BOSN/JSON documents, while Redis is a key-value store. As they do not store the same data structure, you are not going to be able to deal with it the same way. As you have mentioned in your question, now you need two queries in Redis, rather than an only one in Mongo.
According to Data Types documentation Redis does not provide a JSON data type out of the box. However, RedisLabs provides a Redis JSON module. I have not used it, but maybe it can suit your needs.
I understand your concern is:
Do not like two queries may be due to network latency.
Query 1 (to get user id):
Query 2:(use user id to fetch its value)
Option 1:
Is to have a hash like this:
and
And you can fetch all the fields like this in a single REDIS call like this:
Disadvantage:
Option 2:
Use Lua script.
Keep the same data structure as you are keeping it.
Then user in hash like:
Now make an LUA script for queries like:
Here in Lua KEYS[1] –api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2
you can run this using eval like this:
which will return
I feel Option 2 is better since both Options 1 disadvantages are addressed.
Refer: https://redis.io/commands/eval