首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Redis中查询嵌套数据

如何在Redis中查询嵌套数据
EN

Stack Overflow用户
提问于 2021-07-27 05:15:15
回答 2查看 97关注 0票数 1

对于我正在开发的API,我正在向Mongo说“再见”,我想使用Redis作为我的主要数据库。

我的API的身份验证是基于HTTP基本身份验证的,其中用户名本质上是一个API密钥。目前,我在Mongo中有以下user数据结构(为简洁起见进行了编辑):

代码语言:javascript
复制
{
    "_id" : ObjectId("6001a80743ceef211d9dee56"),
    "user_id" : 123,
    "email" : "bob@foo.com",
    "keys" : [
        {
            "key" : "mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2",
            "usage" : 0
        },
        {
            "key" : "wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn",
            "usage" : 40
        }
    ]
}

当请求进入时,我查询Mongo,如下所示:

代码语言:javascript
复制
db.users.find({
    "keys.key": "mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2"
});

如何在Redis中对数据进行建模才能获得大致相同的结果?我主要关心的是有一个查询,它将给我整个用户帐户,就像上面的例子一样。如果不是这样,我可以有以下结构:

代码语言:javascript
复制
api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2 : 123
api:wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn : 123

因此,api密钥映射到用户ID,然后将另一组数据与实际用户数据映射为:

代码语言:javascript
复制
user:123 : name Bob email bob@foo.com

这带来了一个问题,因为我需要查询Redis两次。首先,我需要获取api密钥:

代码语言:javascript
复制
GET api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2

它为我提供了用户ID 123,并且我只能通过ID获取用户:

代码语言:javascript
复制
HGETALL user:123

有没有办法在Redis中对数据进行建模,通过api key进行查询,并获得完整的用户数据?

EN

回答 2

Stack Overflow用户

发布于 2021-07-27 13:41:30

MongoDB可以处理BOSN/JSON文档,而Redis则是一个键值存储。因为它们不存储相同的数据结构,所以您将不能以相同的方式处理它。正如你在问题中提到的,现在你需要Redis中的两个查询,而不是Mongo中唯一的一个。

根据JSON的说法,Redis没有提供开箱即用的Data Types documentation数据类型。但是,RedisLabs提供了Redis JSON module。我还没用过,但也许能满足你的需要。

票数 1
EN

Stack Overflow用户

发布于 2021-07-27 19:24:03

我知道你担心的是:

不喜欢两个查询可能是由于网络延迟。

查询1(获取用户id):

代码语言:javascript
复制
GET api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2

查询2:(使用用户id获取其值)

代码语言:javascript
复制
HGETALL user:123

选项1:

就是有一个像这样的散列:

代码语言:javascript
复制
hmset api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2 user_id 123 email bob@foo.com

代码语言:javascript
复制
hmset api:wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn user_id 123 email bob@foo.com

您可以像这样在单个REDIS调用中获取所有字段,如下所示:

代码语言:javascript
复制
hgetall api:wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn 
1) "user_id"
2) "123"
3) "email"
4) "bob@foo.com"

缺点:

  1. 如果您需要更新用户电子邮件,您可能需要扫描每条记录并执行此操作,这将非常慢。
  2. 这将占用更多内存。

选项2:使用Lua脚本。保持与保持相同的数据结构。

代码语言:javascript
复制
api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2 : user:123
api:wcGXmeOCKSQ2UVocg1PibQQowwJJfmIqZb7TbwKn : user:123

然后是hash形式的用户,如下所示:

代码语言:javascript
复制
HMSET user:123 name Bob email bob@foo.com

现在为如下查询创建一个LUA脚本:

代码语言:javascript
复制
local key =  KEYS[1] 
local info =  redis.call('GET', key)
if info == false then
   return nil
end
return redis.call('HGETALL', info)

在Lua KEYS1 --api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2

您可以像这样使用eval运行此命令:

代码语言:javascript
复制
eval "local key =  KEYS[1] local info =  redis.call('GET', key) if info == false then return nil end return redis.call('HGETALL', info)" 1 api:mavgPVUG2ufy7grBTpfBG7aPb1vKlxO9rQUA8El2

它将返回

代码语言:javascript
复制
1) "name"
2) "Bob"
3) "email"
4) "bob@foo.com"

我觉得选项2更好,因为选项1的缺点都解决了。

参考:https://redis.io/commands/eval

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68536397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档