如何对Redis ReJSON数据类型执行值匹配搜索?
ReJSON 条件查询替代实现方案
方案1:搭配 RediSearch 模块实现服务端过滤(最优)
Redis Stack 默认集成了 ReJSON 和 RediSearch 模块,支持直接对 JSON 字段建索引做条件查询,不需要客户端拉取全量数据,性能最高。
操作步骤:
- 先为JSON的
a字段创建索引,仅需要执行一次
import redis r = redis.Redis(host='你的Redis地址', port=6379, db=0, decode_responses=True) r.execute_command( "FT.CREATE", "json_doc_idx", "ON", "JSON", "PREFIX", "1", "data", "SCHEMA", "$.a", "AS", "a", "TAG" )
这里用TAG类型是因为需要精确匹配
a字段的值,不会做分词处理,适合枚举值、精确匹配场景。
- 直接查询
a等于abs的所有文档
# 执行查询 res = r.execute_command("FT.SEARCH", "json_doc_idx", "@a:{abs}") # 解析结果,res结构为[匹配数量, 键1, 内容1, 键2, 内容2...] match_docs = [] for i in range(1, len(res), 2): match_docs.append({ "key": res[i], "value": res[i+1]["$"][0] }) print(match_docs)
方案2:手动维护二级索引(无RediSearch时的高性能方案)
如果无法部署RediSearch模块,可以在写入JSON数据的同时手动维护二级索引,用Redis的Set存储同属性值的文档键:
- 写入数据时同步更新索引,比如写入
data1时额外执行:
# 假设写入的文档a字段值为abs,键为data1 r.sadd("idx:a:abs", "data1")
删改数据时也要同步更新对应Set,比如删除data1时要执行
r.srem("idx:a:abs", "data1")保证一致性。
- 查询时先从索引拿匹配的键,再批量拉取内容:
# 拿到所有a等于abs的文档键 doc_keys = r.smembers("idx:a:abs") # 批量获取内容 pipe = r.pipeline() for key in doc_keys: pipe.json().get(key) doc_values = pipe.execute() # 组合结果 match_docs = list(zip(doc_keys, doc_values))
方案3:客户端遍历过滤(仅适合小数据量场景)
如果数据量很小,不想修改写入逻辑,可以直接全量拉取后在Python侧过滤:
# 先拿到所有文档键,假设你的文档键都是data前缀,用scan避免keys命令阻塞 doc_keys = [] cursor = 0 while True: cursor, keys = r.scan(cursor, match="data*", count=100) doc_keys.extend(keys) if cursor == 0: break # 批量拉取内容后过滤 pipe = r.pipeline() for key in doc_keys: pipe.json().get(key) all_docs = pipe.execute() match_docs = [] for key, doc in zip(doc_keys, all_docs): if doc.get("a") == "abs": match_docs.append((key, doc))
该方案缺点是数据量大时会占用大量带宽,Redis端压力也高,不适合生产环境大数据量使用。
内容的提问来源于stack exchange,提问作者Jennifer Therese
相关产品推荐
相关产品推荐

