【问题标题】:Search in redis for keys not matching given pattern在 redis 中搜索与给定模式不匹配的键
【发布时间】:2019-12-08 15:54:54
【问题描述】:

目标是设计一个队列,其中包含一些值,例如 A。但只有当传入值 D 与 B & C 不匹配时,我才必须从队列中选择一个值。

A、B、C之间的关系可以看成表格数据。

+------------------+------------------+------------------+
|        A         |        B         |        C         |
+------------------+------------------+------------------+
| 12312            | 123123           | 2323             |
| <some int value> | <some int value> | <some int value> |
+------------------+------------------+------------------+

我有一个传入值 D。

现在我必须简单地从 D 的值不等于 B 或 C 的行中选择值 A。

请注意,A、B、C 都不是事先知道的。这些将由 db 或 redis 中的单独进程填充。我知道的唯一值是 D,我必须在第一行找到 A 的值,我发现 B 和 C 的值与 D 不匹配。

如果我在关系数据库上执行此操作非常简单,即示例查询将是

Select A from table where B != D and C != D LIMIT 1

但我不确定如何使用 redis 之类的键值存储来做到这一点?

试试 1

最基本的想法是在redis中按照以下格式维护一个列表

somekey: ['a1:b1:c1', 'a2:b2:c2', 'a3:b3:c3', ...]

然后我可以简单地运行lrange somekey 0 -1,然后遍历每个元素,在: 上拆分,直到找到bc 都不等于D 的元素。

但是这种方法非常昂贵,因为我必须为每个 D 值遍历整个列表。

试试 2

另一种方法我尝试创建以下格式的 redis 键

+------------------+-----------------------------+
|       Key        |            Value            |
+------------------+-----------------------------+
| prefix_<B1>_<C1> | [<A11>, <A12>, <A13>, ....] |
| prefix_<B2>_<C2> | [<A21>, <A22>, <A23>, ....] |
+------------------+-----------------------------+

这种方法的问题是redis不支持搜索键not matching a pattern

所以我必须先获取所有密钥,然后在应用程序级别进行正则表达式搜索。

然后,一旦我找到一个键,我就会从该键的列表中弹出第一个值。

我的首选方法是使用 redis,但也欢迎使用其他解决方案。

【问题讨论】:

  • 您可能需要考虑一种基于 RediSearch 的更有效方式

标签: database search data-structures redis


【解决方案1】:

假设您以以下格式存储值:

+--------------+-----------------+
| key          | value           |
+--------------+-----------------+
| a1:b1:c1     | any value       |
+--------------+-----------------+
| a2:b2:c2     | any value       |
+--------------+-----------------+
| a3:b3:c3     | any value       |
+--------------+-----------------+
| a4:b4:c4     | any value       |
+--------------+-----------------+

对于任何值d,您需要所有不包含 d:d 作为后缀的键,例如 whatever:d:d,下面的正则表达式将返回所有后缀中不包含 d:d 的键。

KEYS *[^d:d]

假设d 的值为123,那么模式将为:*[^123:123]

以下是我在控制台中测试过的一些案例:

127.0.0.1:6379> set 123:456:789 one
OK
127.0.0.1:6379> set 123:456:780 two
OK
127.0.0.1:6379> set 123:456:787 two
OK
127.0.0.1:6379> set 123:455:787 two
OK
127.0.0.1:6379> set aaa:bbb:ccc abc
OK
127.0.0.1:6379> set aaa:ddd:ddd abc
OK
127.0.0.1:6379> keys *
1) "123:456:789"
2) "123:456:787"
3) "123:455:787"
4) "aaa:ddd:ddd"
5) "aaa:bbb:ccc"
6) "123:456:780"
127.0.0.1:6379> keys aaa:*[^ddd:ddd]
1) "aaa:bbb:ccc"
127.0.0.1:6379> keys *[^ddd:ddd]
1) "123:456:789"
2) "123:456:787"
3) "123:455:787"
4) "aaa:bbb:ccc"
5) "123:456:780"

查看命令keys *[^ddd:ddd] 返回所有与我们预期的键不匹配的键。

1) "123:456:789"
2) "123:456:787"
3) "123:455:787"
4) "aaa:bbb:ccc"
5) "123:456:780"

更多信息请查看此链接:REDIS KEYS

您也可以使用REDIS SCAN 命令获取不匹配的键:

scan 0 MATCH *[^d:d] count 1000

【讨论】:

  • A、B、C 都不是事先知道的。这些将由 db 或 redis 中的单独进程填充。我知道的唯一值是 D,我必须在第一行找到 A 的值,我发现 B 和 C 的值与 D 不匹配。
  • @SushilSingh 符合您的要求吗?
  • @thanks ruhul。我以为redis只能接受通配符而不是完整的正则表达式。
猜你喜欢
  • 1970-01-01
  • 2015-07-08
  • 2023-03-21
  • 2019-05-28
  • 2020-02-18
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 2016-06-21
相关资源
最近更新 更多