redis - 如何获取与全局键不匹配的 Redis 集合的元素?
问题描述
如何获取没有相应全局哈希的所有键?
我将我的主要数据存储在具有唯一键的哈希中,如下所示:
person_1: name: Anna, gender: female
person_2: name: Mark, gender: male
person_3: name: Pat, gender: female
person_4: name: Jo, gender: female
person_5: name: Robert, gender: male
假设我将所有男性的索引保持为一个 SET,如下所示:
male_persons: 2, 5, 6
如您所见,我偷偷输入了一个“错误”,因为没有 person_6。做一个排序,我可以很容易地建立一个“关系查询”,给我所有的男性:
SORT "male_persons" BY nosort GET # GET "person_*->name"
预期的输出是这样的:
"2", "Mark",
"5", "Robert",
"6", nil
我的问题是,我怎样才能只对没有对应人的 SET 键进行 1 或 2 个查询,即如何在上面的示例中只生成这一行:
"6", nil
甚至更好:
"6"
或者:
person_6
在 SQL 中,这将类似于:
SELECT id FROM male_person_index WHERE male_person_index.id NOT IN (SELECT person.id FROM person);
我知道这样做的一种方法是编写一个 Lua 脚本,但这似乎很基本,应该可以在 1 或 2 个标准查询中执行此操作,而我只是想念它。在这种特殊情况下,性能并不是非常重要的,因此一个接一个地发出 1 个或 2 个甚至 3 个标准查询就足够了。
更新:我写了一个 Lua 脚本的解决方案,但如前所述,我对此并不满意:
eval 'local out = {}; local i = 1; local exists; for _, key in ipairs(redis.call("SMEMBERS", KEYS[1])) do exists = redis.call("EXISTS", "persons_" .. key); if exists == 0 then out[i] = key .. " -> " .. exists; i = i + 1; end; end; return out;' 1 "male_persons"
我不满意的原因是这是“循环”且缓慢并且EXISTS
可能会调用数千或数百万次。我仍然认为这应该在 2 或 3 笔交易中完成,而不是 1000 或数百万。
一个优雅的解决方案将采用SORT
命令的输出数组STORE
,然后以某种方式从该结果中减去另一个查询结果数组,一举减少非孤立键的最终输出,最后给我,仅孤儿键。
那可能吗?
解决方案
您可以尝试以下非常棘手的方法:
溶液
使用您的排序解决方案并将结果存储到列表中:list1。
SORT "male_persons" BY nosort GET # GET "person_*->name" store list1
按字典顺序(即选项)按person_*->name对male_persons进行排序,并将结果存储到列表中:list2:
ALPHA
SORT "male_persons" BY person_*->name ALPHA GET # GET "person_*->name" store list2
删除list1中的所有空字符串,并获取删除的元素数:num:
num = LREM list1 0 ""
从list2中获取第一个
num * 2
元素:LRANGE list2 0 (num * 2 - 1)
解释:
- 将数据按字典顺序排序,即第2步,我们可以确保不存在的成员在结果列表的前面,即list2,对应的值为空字符串:
127.0.0.1:6379> lrange list2 0 -1
1) "6"
2) ""
3) "2"
4) "Mark"
5) "5"
6) "Robert"
- 我们可以从list1中移除所有空字符串,即第 1 步和第 3 步,这样我们就可以得到 hash 中不存在的成员数。
注意:我们不会在步骤 1 中进行排序以节省一些成本。
127.0.0.1:6379> lrem list1 0 ""
(integer) 1
- 那么list2
num * 2
中的第一个元素就是结果,即第4步:
127.0.0.1:6379> lrange list2 0 1
1) "6"
2) ""
推荐阅读
- javascript - Javascript 在哪里为函数调用的结果分配内存?堆栈还是堆?
- mongodb - 安装 MongoDB 时出现错误
- apache-kafka - 动态生成到新目的地,在 kstream 中读取它并在 Spring Cloud Stream Kafka 中删除目的地
- android - Flutter - 在构建 APK 上看不到通知图标
- javascript - 如何垂直为 Svg 路径设置动画?
- swift - Apple iMessage 扩展应用程序 - 你可以发出 http 请求吗?
- java - 在 JPA 中访问模型属性不起作用
- python - 使用 np.invert 反转布尔数组
- javascript - onClick 函数在渲染时被调用——我怎样才能阻止这种情况的发生?
- javascript - NDEFReader 未定义