Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Redis中,如何通过从第二个排序集排除记录来将记录从第一个集合中分离出来。?_Redis_Sortedset_Set Difference - Fatal编程技术网

在Redis中,如何通过从第二个排序集排除记录来将记录从第一个集合中分离出来。?

在Redis中,如何通过从第二个排序集排除记录来将记录从第一个集合中分离出来。?,redis,sortedset,set-difference,Redis,Sortedset,Set Difference,我有两个排序集,我想通过排除第二个排序集的记录,将记录从第一个集合中分离出来,并存储在新列表/排序集合中 以下是一个例子: set1:1,2,3,4,5 set2:3,5,7,8,9 产量:1,2,4 编辑:我已经找到了加载脚本并使用eval从nodejs执行脚本的方法 奇怪的是,当我执行你的脚本时,即使是5-10条记录,它也需要1秒来处理,这让我怀疑如果我有数千条记录,它的可伸缩性有多大 下面是我的示例nodejs代码: hsetxx = 'redis.call("ZINTERSTORE","

我有两个排序集,我想通过排除第二个排序集的记录,将记录从第一个集合中分离出来,并存储在新列表/排序集合中

以下是一个例子:

set1:1,2,3,4,5 set2:3,5,7,8,9

产量:1,2,4

编辑:我已经找到了加载脚本并使用eval从nodejs执行脚本的方法

奇怪的是,当我执行你的脚本时,即使是5-10条记录,它也需要1秒来处理,这让我怀疑如果我有数千条记录,它的可伸缩性有多大

下面是我的示例nodejs代码:

hsetxx = 'redis.call("ZINTERSTORE","temp",2,"set11","set21","weights",1,0) redis.call("ZUNIONSTORE","result",2,"set11","temp","weights",1,-1) redis.call("ZREMRANGEBYSCORE","result",0,0)';

var redis = require('redis');
var client = redis.createClient('14470', connection);

client.on('connect', function() {
    console.log('Connected to Redis');
});

client.script('load',hsetxx,function(err, result) {
     console.log(err+'------------'+result);
 });

client.zadd('set11', 1,1,1,2,1,3,1,4,1,5);
client.zadd('set21', 1,1,1,5);

client.evalsha(
 '39c0da298cab6a6223b4d1e8222cf6d6a84e67b1', //lua source 
 0,
 function(err, result) {
     client.zrange('result', 0, -1, function(err, result) {
          console.log(err+'------------'+result);
      });
 }
);

我认为您正在寻找SDIFF:

key1 = {a,b,c,d}
key2 = {c}
key3 = {a,c,e}
SDIFF key1 key2 key3 = {b,d}

但是,排序集没有等效项。

检查问题:

您可以做的是首先使用ZUNIONSTORE和 将交叉点的分数设置为0。然后做一个不包括0的范围, e、 g:


能早点讨论真是太好了。正如承诺的那样,解决这一挑战的另一种方法是使用Lua和Redis。我不知道它的性能如何,但这里有一个(没有经过太多测试)脚本,它模拟了
SDIFF
,但用于排序集:

~/src/redis-lua-scripts$ cat zdiff.lua 
-- ZDIFF key [key ...]
-- Returns the elements in the first key that are also present in all other keys

local key = table.remove(KEYS,1)
local elems = redis.call('ZRANGE', key, 0, -1)
local reply = {}

if #KEYS > 0 and #elems > 0 then
  for i, e in ipairs(elems) do
    local exists = true
    for j, k in ipairs(KEYS) do
      local score = redis.call('ZSCORE', k, e)
      if not score then
        exists = false
        break
      end
    end
    if exists then
      reply[#reply+1] = e
    end
  end
end

return reply
~/src/redis-lua-scripts$ redis-cli SCRIPT LOAD "`cat zdiff.lua`"
"e25d895f05dc638be87d13aed64e8d5780f17c99"
~/src/redis-lua-scripts$ redis-cli ZADD zset1 0 a 0 b 0 c 0 d 0 e
(integer) 5
~/src/redis-lua-scripts$ redis-cli ZADD zset2 0 a
(integer) 1
~/src/redis-lua-scripts$ redis-cli ZADD zset3 0 a 0 b
(integer) 2
~/src/redis-lua-scripts$ redis-cli EVALSHA e25d895f05dc638be87d13aed64e8d5780f17c99 3 zset1 zset2 zset3
1) "a"

不,我想使用排序集。我找不到ZDIFF,有什么解决办法吗?你可以用Lua编写它或将它实现为一个模块。@Not_a_Golfer你能详细说明一下吗?为什么是Lua?什么模块?@LorenzoBelli有两种方法可以向运行在服务器内部的redis-Lua脚本添加功能,或者用C编写的模块可以扩展它。两者都可以实现ZDIFF的功能。事实上,我并不介意快速编写一个模块来演示ZDIFF。Lua会慢很多,但这两种方法都会奏效。以下解决方案的可能副本对我来说很有效:ZADD key1 1 2 1 3 1 4 1 5 ZADD key2 1 1 5 ZINTERSTORE temp 2 key1 2 weights 1 0 ZUNIONSTORE result 2 key1 temp weights 1-1 ZREMRANGEBYSCORE result 0 0 DEL temp ZRANGE result 0-1 1“2”3“3”4”你认为有什么性能问题吗?哈-这也是我的:)将其与Lua脚本进行比较会很有趣,因为我对Redis和Lua脚本不熟悉,很难理解-我如何在redislabs托管的Redis db上部署Lua脚本-从我的节点应用程序调用lua脚本任何参考或步骤都可以帮助我。JFYI:我现在正在使用redislabs的免费版本,因为我还在评估它。你能给我一个脚本来排除set1中存在于set2中的记录吗?我们也有数百万的记录。它会导致性能问题吗?
~/src/redis-lua-scripts$ cat zdiff.lua 
-- ZDIFF key [key ...]
-- Returns the elements in the first key that are also present in all other keys

local key = table.remove(KEYS,1)
local elems = redis.call('ZRANGE', key, 0, -1)
local reply = {}

if #KEYS > 0 and #elems > 0 then
  for i, e in ipairs(elems) do
    local exists = true
    for j, k in ipairs(KEYS) do
      local score = redis.call('ZSCORE', k, e)
      if not score then
        exists = false
        break
      end
    end
    if exists then
      reply[#reply+1] = e
    end
  end
end

return reply
~/src/redis-lua-scripts$ redis-cli SCRIPT LOAD "`cat zdiff.lua`"
"e25d895f05dc638be87d13aed64e8d5780f17c99"
~/src/redis-lua-scripts$ redis-cli ZADD zset1 0 a 0 b 0 c 0 d 0 e
(integer) 5
~/src/redis-lua-scripts$ redis-cli ZADD zset2 0 a
(integer) 1
~/src/redis-lua-scripts$ redis-cli ZADD zset3 0 a 0 b
(integer) 2
~/src/redis-lua-scripts$ redis-cli EVALSHA e25d895f05dc638be87d13aed64e8d5780f17c99 3 zset1 zset2 zset3
1) "a"