【问题标题】:Redis - Sorted set, find item by property valueRedis - 排序集,按属性值查找项目
【发布时间】:2015-12-27 13:29:09
【问题描述】:

在 redis 中,我将对象存储在有序集中。 在我的解决方案中,能够按日期运行范围查询很重要,因此我将分数存储为每个项目的时间戳,例如:

#   Score   Value
0   1443476076  {"Id":"92","Ref":"7ADT","DTime":1443476076,"ATime":1443901554,"ExTime":0,"SPName":"7ADT33CFSAU6","StPName":"7ADT33CFSAU6"}
1   1443482969  {"Id":"11","Ref":"DAJT","DTime":1443482969,"ATime":1443901326,"ExTime":0,"SPName":"DAJTJTT4T02O","StPName":"DAJTJTT4T02O"}

但是,在其他情况下,我需要根据其 ID 在集合中查找单个项目。 我知道我不能只查询这个数据结构,就好像它是一个 nosql db,但我尝试使用 ZSCAN,但没有用。

ZSCAN MySet 0 MATCH Id:92 count 1

返回; “空列表或集合”

也许我需要序列化不同的? 我已经使用 Json.Net 进行了序列化。

如果可能的话,我怎样才能做到这一点;使用日期作为分数并且仍然能够通过它的 ID 查找项目?

非常感谢,

拉尔斯

编辑:

假设这是不可能的,但欢迎任何想法或意见:

参考:http://openmymind.net/2011/11/8/Redis-Zero-To-Master-In-30-Minutes-Part-1/

在 Redis 中,只能通过 key 来查询数据。即使我们使用哈希, 我们不能说在野外比赛等于的地方给我钥匙 萨扬。

编辑 2:

我尝试过:

ZSCAN MySet 0 MATCH *87*

127.0.0.1:6379> ZSCAN MySet 0 MATCH *87*
1) "192"
2) 1) "{\"Id\":\"64\",\"Ref\":\"XQH4\",\"DTime\":1443837798,\"ATime\":1444187707,\"ExTime\":0,\"SPName\":\"XQH4BPGW47FM\",\"StPName\":\"XQH4BPGW47FM\"}"
   2) "1443837798"
   3) "{\"Id\":\"87\",\"Ref\":\"5CY6\",\"DTime\":1443519199,\"ATime\":1444172326,\"ExTime\":0,\"SPName\":\"5CY6DHP23RXB\",\"StPName\":\"5CY6DHP23RXB\"}"
   4) "1443519199"

它找到了所需的项目,但它还在属性 ATime 中找到了出现次数为 87 的另一个项目。拥有更多唯一、更长的 ID 可能会以这种方式工作,我必须在代码中过滤结果以找到其属性中具有确切值的 ID。

仍然欢迎提出建议。

【问题讨论】:

    标签: redis


    【解决方案1】:

    我觉得很简单。

    方案一(劣质,不推荐)

    您的ZSCAN MySet 0 MATCH Id:92 count 1 方式无效,因为存储的字符串是"{\"Id\":\"92\"... 而不是"{\"Id:92\"...。该字符串已更改为另一种格式。所以尝试使用MATCH Id\":\"64或类似的东西来匹配redis中的json序列化数据。我对 json.net 不熟悉,所以实际的字符串留给你去发现。

    顺便问一下,ZSCAN MySet 0 MATCH Id:92 count 1 有没有返回游标?我怀疑你以错误的方式使用了ZSCAN

    方案2(更好,强烈推荐)

    ZSCAN 适用于您的排序集不大并且您知道如何通过 Redis 的 Lua 事务节省网络往返时间的情况。这仍然使“按 ID 查找”操作 O(n)。因此,更好的解决方案是通过以下方式更改您的数据模型:

    更改排序集 来自

    #   Score   Value
    0   1443476076 {"Id":"92","Ref":"7ADT","DTime":1443476076,"ATime":1443901554,"ExTime":0,"SPName":"7ADT33CFSAU6","StPName":"7ADT33CFSAU6"}
    1   1443482969 {"Id":"11","Ref":"DAJT","DTime":1443482969,"ATime":1443901326,"ExTime":0,"SPName":"DAJTJTT4T02O","StPName":"DAJTJTT4T02O"}
    

    #   Score   Value
    0   1443476076 Id:92
    1   1443482969 Id:11
    

    将其余详细数据移动到另一组哈希类型键中:

    #   Key   field-value field-value ...
    0   Id:92 Ref-7ADT DTime-1443476076 ...
    1   Id:11 Ref-7ADT DTime-1443476076 ...
    

    然后,您可以通过hgetall id:92 按ID 定位。对于按日期进行的范围查询,您需要对每个 id 一个一个地执行 ZRANGEBYSCORE sortedset mindate maxdate 然后 hgetall 。最好用 lua 把这些命令封装成一个,还是会超级快的!

    NoSql 数据库中的数据需要像上面那样以冗余方式组织。这可能会使一些常规操作涉及多个命令和往返,但可以通过 redis 的 lua 功能解决。我强烈推荐 redis 的 lua 特性,因为它将命令包装到一个网络往返中,所有这些都在 redis-server 端执行,并且是原子的并且超级快!

    如果有什么不知道的请回复

    【讨论】:

    • 您好,感谢您花时间写一个非常好的答案。似乎解决方案 2 是这里的方法。我从来没有进入lua,我会研究它。非常感谢! :)
    • 我建议删除解决方案 1,因为它肯定不如解决方案 2,特别是因为它不像可能的路线那样需要询问者想出更多答案。
    • @TheRealBill 我只是认为解决方案 1 很容易解决被问者迫在眉睫的问题。解决方案 2 需要重新建模数据结构。解决方案1可能会引导提问者找到答案,虽然只是指出了问题的关键,但没有给出详细的方法,
    • 如果按字段进行查找,不应该是 HGET 而不是 HGETALL
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多