You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 09:48:12