使用redis进行多标准查询

时间:2014-12-14 12:54:36

标签: redis database nosql

让我们创建5个项目:

HMSET id1 x 0 y 1 z 3
HMSET id2 x 2 y 3 z 5
HMSET id3 x 8 y 4 z 3
HMSET id4 x 9 y 8 z 6
HMSET id5 x 1 y 3 z 5

如何查找0 < x < 22 < y < 54 < z < 8等元素?

更一般地说,如何使用redis执行多标准搜索?


旁注:在this nice tutorial中,我看了以下通知,是真的吗?

  

Redis查询

     

在Redis中,只能通过密钥查询数据。即使我们使用哈希,   我们不能说只要字段......等于......

就能得到钥匙

1 个答案:

答案 0 :(得分:2)

重要更新:在Secondary indexing with Redis

上可以找到更多相关信息

本教程是正确的 - Redis不提供开箱即用的搜索功能......但您可以使用Redis的数据结构来维护几乎任何值的索引。

继续您的示例,因为您要查看范围查询,所以您需要使用有序集来存储索引数据。对于每个索引的哈希字段,维护一个单独的有序集,其中成员是键名,分数是字段值。因此,对于您的数据,请执行以下操作:

ZADD _x 0 id1 2 id2 8 id3 9 id4 1 id5
ZADD _y 1 id1 3 id2 4 id3 8 id4 3 id5
ZADD _z 3 id1 5 id2 3 id3 6 id4 5 id5

要执行实际查询,请在每个有序集上使用ZRANGEBYSCORE,并将结果相交以应用逻辑和运算符。这可以在您的应用程序代码中执行,也可以使用服务器端Lua脚本执行。

编辑:这是执行此类查询的Redis Lua脚本。我选择使用Lua,因为我的Node.js技能低于标准(:))并且还因为效率 - 这种方法将节省数据到客户端的往返。:

local tmps = {}

for i = 1, #KEYS / 2, 1 do
  local range
  range = redis.call("ZRANGEBYSCORE", KEYS[i], "(" .. ARGV[i*2-1], "(" .. ARGV[i*2])

  local tmp = KEYS[#KEYS / 2 + i]
  redis.call("DEL", tmp)
  for k, v in ipairs(range) do
    redis.call("SADD", tmp, v)
  end

  tmps[#tmps + 1] = tmp               
end

return redis.call("SINTER", unpack(tmps))

按如下方式调用:

redis-cli --eval query.lua _x _y _z __x __y __z , 0 2 2 5 4 8

请注意,该脚本接受6个键 - 3个索引以及3个临时变量名(根据规范要求,这是集群兼容性所必需的)。

回答评论#1:是 - Redis的排序集分数可以是浮点数,数千个值不应该有任何问题

回答评论#2:没有基准测试我无法确定,但我有充分的理由相信这至少与任何SQL解决方案一样高。

最后,您可能会发现此演示文稿在此背景下非常有用:http://www.slideshare.net/itamarhaber/20140922-redis-tlv-redis-indices