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

Redisearch通配符前缀索引失效求助:index_test_wildcard无法匹配数据

问题:Redis通配符前缀索引无法匹配键值

我正在排查为何index_test索引可正常工作,但index_test_wildcard索引无法匹配对应数据。后者虽尝试用通配符语法创建索引,却无法匹配函数内生成的doc:1:data:1记录。

相关代码

from redis.commands.json.path import Path
from redis.commands.search.field import TagField, TextField, NumericField
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
from redis import Redis

def initialise_redis():
    # 假设此处为Redis客户端初始化逻辑
    return Redis(host='localhost', port=6379, db=0)

def index_test(r: Redis):
    r.json().set('doc:data:1', Path.root_path(), {
        "title": "Example Title",
        "views": 150,
        "tags": ["tutorial", "redis"]
    })

    schema = [
        TextField('$.title', as_name='title', weight=5.0),
        NumericField('$.views', as_name='views'),
        TagField('$.tags', as_name='tags', separator=',')
    ]

    definition = IndexDefinition(prefix=['doc:data:'], index_type=IndexType.JSON)
    r.ft("index_test").create_index(schema, definition=definition)

def index_test_wildcard(r: Redis):
    r.json().set('doc:1:data:1', Path.root_path(), {
        "title": "Example Title",
        "views": 150,
        "tags": ["tutorial", "redis"]
    })

    schema = [
        TextField('$.title', as_name='title', weight=5.0),
        NumericField('$.views', as_name='views'),
        TagField('$.tags', as_name='tags', separator=',')
    ]

    definition = IndexDefinition(prefix=['doc:*:data:'], index_type=IndexType.JSON)
    r.ft("index_test_wildcard").create_index(schema, definition=definition)

redis_client = initialise_redis()

index_test(redis_client)
index_test_wildcard(redis_client)

查询结果

127.0.0.1:6379> FT.SEARCH index_test *
1) (integer) 1
2) "doc:data:1"
3) 1) "$"
   2) "{\"title\":\"Example Title\",\"views\":150,\"tags\":[\"tutorial\",\"redis\"]}"
127.0.0.1:6379> FT.SEARCH index_test_wildcard *
1) (integer) 0

问题原因

Redis Search的索引前缀通配符仅支持后缀通配——*只能放在前缀字符串的末尾,不能出现在中间。你使用的doc:*:data:属于中间插入通配符的格式,不符合Redis Search的前缀匹配规则,因此无法匹配doc:1:data:1这个键。

解决方法

方案1:调整键命名规则(推荐)

将键格式改为固定前缀+可变后缀,比如把doc:1:data:1改为doc:data:1:1,再将索引前缀设为doc:data:*,即可匹配所有以doc:data:开头的键:

def index_test_wildcard(r: Redis):
    # 修改键名格式
    r.json().set('doc:data:1:1', Path.root_path(), {
        "title": "Example Title",
        "views": 150,
        "tags": ["tutorial", "redis"]
    })

    schema = [
        TextField('$.title', as_name='title', weight=5.0),
        NumericField('$.views', as_name='views'),
        TagField('$.tags', as_name='tags', separator=',')
    ]

    # 前缀改为固定开头+末尾通配符
    definition = IndexDefinition(prefix=['doc:data:*'], index_type=IndexType.JSON)
    r.ft("index_test_wildcard").create_index(schema, definition=definition)

方案2:添加Tag字段存储分段信息

如果无法修改键名,可在JSON数据中添加字段存储键的可变分段(比如doc:和:data:之间的部分),创建Tag索引后通过过滤该字段匹配目标数据:

def index_test_wildcard(r: Redis):
    r.json().set('doc:1:data:1', Path.root_path(), {
        "title": "Example Title",
        "views": 150,
        "tags": ["tutorial", "redis"],
        "key_segment": "1"  # 新增存储可变分段的字段
    })

    schema = [
        TextField('$.title', as_name='title', weight=5.0),
        NumericField('$.views', as_name='views'),
        TagField('$.tags', as_name='tags', separator=','),
        TagField('$.key_segment', as_name='key_segment')  # 为该字段创建Tag索引
    ]

    # 前缀设为键的固定开头部分
    definition = IndexDefinition(prefix=['doc:'], index_type=IndexType.JSON)
    r.ft("index_test_wildcard").create_index(schema, definition=definition)

查询时用FILTER子句过滤:

FT.SEARCH index_test_wildcard * FILTER key_segment == "1"

方案3:查询时直接匹配键名(性能较低)

若不想修改数据或索引,可通过__key内置字段匹配键名通配符,但该方式性能不如前缀索引,仅适合小数据量场景:

FT.SEARCH index_test_wildcard * RETURN 1 $ WHERE __key LIKE "doc:*:data:*"

内容的提问来源于stack exchange,提问作者Harry Stuart

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:35:15