Redis-py匹配全部查询返回结果不一致问题求助
问题原因分析
1. Pipeline未正确使用
你创建了Redis管道,但循环中调用的是r.json().set()而非pipe.json().set(),导致所有JSON写入命令都是单独发送,完全没用到管道的批量执行能力,这属于代码逻辑错误。
2. 索引异步构建导致查询结果不全
你是先写入100个文档,再创建索引。Redis Search对已存在的匹配前缀的键,会在后台异步构建索引,刚创建完索引就执行查询时,索引还没完全构建完毕,所以返回的结果总数会小于100,且每次数值不一致(取决于后台构建的进度)。
修复方案
方案一:先创建索引,再写入数据(推荐)
让Redis Search自动索引后续写入的文档,这样每个文档写入时都会被实时索引,查询结果会准确匹配总数。同时修复Pipeline的使用问题:
import uuid import redis from redis.commands.json.path import Path from redis.commands.search.field import TextField, NumericField, TagField from redis.commands.search.indexDefinition import IndexDefinition, IndexType from redis.commands.search.query import Query r = redis.Redis(host="localhost", port=6379) r.flushall() # 清空之前的数据 # 1. 先创建索引 schema = ( TextField("$.user.name", as_name="name"), TagField("$.user.city", as_name="city"), NumericField("$.user.age", as_name="age"), ) r.ft().create_index( schema, definition=IndexDefinition(prefix=["user:"], index_type=IndexType.JSON) ) user4 = { "user": { "name": "Sarah Zamir", "email": "sarah.zamir@example.com", "age": 30, "city": "Paris", } } # 2. 使用Pipeline批量写入文档 with r.pipeline(transaction=True) as pipe: for i in range(100): # 创建字典副本,避免引用同一对象导致数据覆盖 u = user4.copy() u["user"] = u["user"].copy() u["user"]["text"] = str(uuid.uuid4()) * 50 pipe.json().set(f"user:{i}", Path.root_path(), u) pipe.execute() # 3. 执行查询 result = r.ft().search(Query("*").paging(0, 100)) print(result.total) # 现在会输出100 keys = r.keys("*") print(len(keys)) # 输出100 r.close()
补充说明:
- 修复了Pipeline的使用:循环中调用
pipe.json().set(),确保批量执行命令。 - 每次循环创建字典副本:原代码中
[user4] * 100会创建100个指向同一字典的引用,修改其中一个会影响所有,这里通过copy()避免数据覆盖问题(原代码中这个问题可能导致所有文档的text字段是同一个值,但不影响计数,属于潜在bug)。 - 先创建索引再写入,确保每个文档都被实时索引。
方案二:先写数据再强制同步索引(不推荐,仅作参考)
如果必须先写入数据再创建索引,可以在创建索引后等待后台构建完成:
# 创建索引后添加以下代码 import time while True: info = r.ft().info() if info['num_docs'] == 100: break time.sleep(0.1) # 再执行查询 result = r.ft().search(Query("*").paging(0, 100)) print(result.total)
内容的提问来源于stack exchange,提问作者monopoly
相关产品推荐
相关产品推荐

