redisearch 在 webman 中需 redis 8.0+ 内置支持,建索引须正确设置 numeric/tag 字段类型以支持范围与集合查询,php 调用需用 redis::command() 并严格转义、规范 dsl 语法,聚合结果需手动解析结构。

RediSearch 在 Webman 中必须用 Redis 8.0+ 内置模块
Webman 本身不提供 RediSearch 封装,你得直接通过 redis-cli 或 PHP Redis 扩展调用命令。关键前提是:Redis 版本 ≥ 8.0 —— 因为从这个版本起,RediSearch 已作为内置模块集成,不再需要手动编译安装 redis-search.so。低于 6.0 的 Redis 根本不支持,而 6.x–7.x 需额外加载模块,极易在 Docker 或多环境部署中因路径、权限、协议不匹配失败。
验证是否就绪只需两步:
- 连上 Redis:
redis-cli - 执行:
MODULE LIST,输出中必须含name:search且ver:200+(表示 RediSearch v2.x)
如果返回空或报错 (error) ERR unknown command MODULE,说明 Redis 版本太低或未启用模块——别折腾配置,直接升级 Redis。
FT.CREATE 建索引时字段类型和权重决定组合筛选能力
RediSearch 的组合筛选(比如“价格 100–500 且分类=手机 且标题含‘旗舰’”)完全依赖索引定义。建错字段类型,后续查询就废一半。常见错误是把数值当文本、把标签数组当单值字符串。
正确做法示例(以商品表为例):
FT.CREATE idx:product SCHEMA id NUMERIC SORTABLE title TEXT WEIGHT 3.0 category TAG SEPARATOR ',' price NUMERIC RANGE tags TAG SEPARATOR ',' created_at NUMERIC SORTABLE
-
NUMERIC字段才能用@price:[100 500]范围查询,TEXT 类型只能模糊匹配,无法做区间判断 -
TAG字段支持多值(如category存"phone,smartphone"),查询写@category:{phone};若误用 TEXT,则FT.SEARCH idx:product "@category:phone"只能匹配完整字段,无法做集合内任意值筛选 -
WEIGHT不影响筛选逻辑,但影响排序相关性——组合查询时若没显式SORTBY,默认按权重加权打分
建好后务必用 FT.INFO idx:product 确认字段类型和属性,别凭记忆写查询。
PHP 中用 Redis::command() 构造组合查询要防注入和语法错
Webman 没有 RediSearch 官方 SDK 封装,直接走 Redis::command() 是最稳的。但手拼 DSL 容易出错:漏转义、括号不闭合、布尔运算符大小写不对(AND 必须大写),都会导致 (error) Syntax error。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
安全写法要点:
- 用户输入关键词必须用双引号包裹并转义特殊字符:
str_replace(['"', '\'], ['\"', '\\'], $keyword) - TAG 查询固定格式:
@category:{'.$category.'},不要写成@category:'.$category(后者会被当全文词) - 组合条件用空格分隔,AND/OR/NOT 全大写,且前后必须有空格:
'@title:"'.$kw.'" @price:[100 500] @category:{phone} -@status:{deleted}' - 避免直接拼接用户可控的
SORTBY或RETURN字段,应白名单校验
一个真实可用的搜索调用:
$redis = supportRedis::instance();
$result = $redis->command('FT.SEARCH', [
'idx:product',
'@title:"'.$escaped_kw.'" @price:['.$min.' '.$max.'] @category:{'.$cat.'}',
'LIMIT', 0, 20,
'RETURN', 3, 'id', 'title', 'price'
]);
聚合分析(AGGREGATE)在 Webman 中需手动解析响应结构
RediSearch 的 FT.AGGREGATE 返回的是扁平数组,不是 JSON 对象,Webman 直接 json_encode() 会丢字段名。比如按分类统计数量:
FT.AGGREGATE idx:product "*" GROUPBY 1 @category REDUCE COUNT 0 AS count
PHP 返回类似:['1', ['category', 'phone', 'count', '127'], ['category', 'laptop', 'count', '89']] —— 第一个元素是总条数,后面每两项是一组 key-value。
必须自己解析:
- 跳过第一个元素(
array_shift($res)) - 用
array_chunk($res, 4)拆成 [key,val,key,val] 四元组 - 再
array_map提取成['category' => 'phone', 'count' => 127]结构
别图省事用 json_encode($res) 直接返回给前端——前端拿到的是错位数组,前端同学会半夜打电话问你“为什么 category 字段在奇数位”。










