Redis ZSCAN如何匹配包含指定字符的有序集合成员?
解决Redis有序集合多模式匹配的问题
首先得说清楚你当前的ZSCAN id_name 0 match t*:t* count 10为什么只返回t1:test——这个匹配模式是找以t开头,后面跟任意字符,再跟着:t开头的成员,所以只有t1:test符合(t开头,接着1,然后:t),而a:test是a开头不符合t*,t2:b虽然是t开头,但后面是:b不符合:t*,所以没被捞出来。
想要同时拿到t1:test、a:test、t2:b,你有几个可行的方案,根据你的Redis版本和需求来选:
方案1:多次ZSCAN+客户端合并(兼容所有Redis版本)
因为Redis的SCAN系列命令的match参数只支持单个模式,不直接支持OR逻辑,所以你可以分两次扫描,分别匹配不同的模式,然后在客户端把结果合并:
- 第一次扫描匹配
*:test:
这会返回ZSCAN id_name 0 match *:test count 10t1:test和a:test - 第二次扫描匹配
*:b:
这会返回ZSCAN id_name 0 match *:b count 10a:b和t2:b
之后你可以在客户端过滤掉不需要的a:b,或者直接合并你需要的三个结果。注意:SCAN的count只是给Redis的提示,不是精确返回数量,所以要循环执行直到游标返回0,确保拿到所有匹配的成员。
方案2:用ZSEARCH命令(Redis 7.0+可用)
如果你的Redis版本是7.0或以上,那就方便多了——Redis 7.0引入的ZSEARCH命令支持复杂的匹配逻辑,包括OR条件。你可以直接用一个命令搞定:
ZSEARCH id_name 0 MATCH {*:test | *:b} COUNT 10
这个命令会直接返回所有符合*:test或者*:b模式的成员,也就是你想要的t1:test、a:test、t2:b,还能自动帮你去重(如果有重复匹配的情况)。
方案3:预构建辅助索引(适合高频查询场景)
如果这个查询是高频操作,你可以在写入有序集合的时候,额外维护辅助的数据结构,比如:
- 把每个成员按冒号拆分,比如
a:test拆成前缀a和后缀test,然后用哈希表或者集合来索引后缀对应的成员。比如用HASH存储test对应的成员列表,b对应的成员列表。 - 每次执行
ZADD的时候,同时更新这些辅助结构。这样查询的时候直接从辅助结构里取对应的成员,再去有序集合里拿分数(如果需要的话)。不过这个方案会增加写入的复杂度和内存占用,适合查询频率远高于写入的场景。
内容的提问来源于stack exchange,提问作者Edwin Xavier
相关产品推荐
相关产品推荐

