设置自定义排名规则时沿用旧版函数式语法
asc(price)/desc(price),PUT /settings/ranking-rules返回 HTTP 400,错误码invalid_settings_ranking_rules。该语法自 v0.22 起废弃,现行写法是属性名:asc/属性名:desc(如"release_date:desc")。改成新语法即可,但注意PUT是全量覆盖,要把默认 7 条规则一起带上。适用 Meilisearch v0.22 之后的版本,本篇以 v1.54.3 实测。
Issue & Env(案发现场与环境)
- 业务场景:想给搜索结果加一条常驻的“新品优先”规则,让最新发行的书排前面。按网上旧教程写
desc(release_date),放进PUT /indexes/books_sort/settings/ranking-rules,直接返回 400 Bad Request,错误码invalid_settings_ranking_rules。换成release_date:desc后立即通过。 - 环境:Meilisearch v1.54.3,curl 调用 REST API。
- 关键区分:
invalid_settings_ranking_rules触发条件是 ranking-rules 设置值非法,与 search 请求无关,也不是异步任务没等完。最常见两类:旧语法asc()/desc(),以及保留关键字(_geoPoint等_geo系列)。本篇只讲第一类。 - 典型触发:项目从旧版 Meilisearch 升级,或照着 2022 年前的博客/SDK 示例写排名规则。旧资料里的
asc(price)写法在新版一律报错。
StackTrace(堆栈日志)
本地实测原文(索引 books_sort,规则数组第 8 位即下标 [7] 处传了 desc(release_date)):
{
"message": "Invalid value at `[7]`: `desc(release_date)` ranking rule is invalid. Valid ranking rules are words, typo, sort, proximity, attribute, exactness and custom ranking rules.",
"code": "invalid_settings_ranking_rules",
"type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#invalid_settings_ranking_rules"
}
asc(release_date)、desc(rating) 同样被拒,报错原文一致,只有 [7] 处的规则字符串不同。以上均为 HTTP 400 同步返回,不走异步任务。
注意 message 里列的合法规则是 words, typo, sort, proximity, attribute, exactness——它还停留在 v1.36 拆分前的旧名单(attribute 是旧名)。v1.54.3 实际默认规则是 7 条:words, typo, proximity, attributeRank, sort, wordPosition, exactness。别拿这行报错原文当默认规则的完整清单,以 GET /indexes/{uid}/settings 实际返回为准。
Reproduce(复现代码)
# 1. 用旧语法 desc() 设置自定义排名规则——报错
curl -X PUT 'http://localhost:7700/indexes/books_sort/settings/ranking-rules' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '["words","typo","proximity","attributeRank","sort","wordPosition","exactness","desc(release_date)"]'
# 返回 400:
# {"message": "Invalid value at `[7]`: `desc(release_date)` ranking rule is invalid. ...", "code": "invalid_settings_ranking_rules", ...}
Root Cause(根因分析)
语法自 v0.22 起废弃
Meilisearch 的自定义排名规则最早采用函数式写法 asc(属性) / desc(属性)。v0.22 起官方把语法改成 属性名:asc / 属性名:desc,旧的函数式写法进入废弃流程,新版本解析器直接拒绝,返回 invalid_settings_ranking_rules。官方博客 What’s new in v0.22 记录了这次变更,理由是与 sort 参数(一直是 属性:方向 格式)保持一致的表达。
报错信息能定位到具体下标
Invalid value at [7]`` 中的 [7] 是规则数组的下标:release_date:desc 放在默认 7 条之后,即数组第 8 位(下标 7)。哪一条非法,报错就指出哪一位,排查时直接看这个位置。
PUT 是全量覆盖,不是追加
PUT /settings/ranking-rules 的语义是把整个规则数组替换掉,漏带默认规则会直接冲掉 words/exactness。本地实测:只传 ["release_date:desc"] 后 GET /settings 返回的 rankingRules 只剩这一条,相关度排序完全失效。所以修复时要把默认 7 条一起写进去。
设置更新是异步任务
设置变更返回 taskUid(type 为 settingsUpdate),并触发该索引全量重建。任务还在 enqueued/processing 时搜索,新规则不生效,也不报错——表现是“看起来没排对”,和这里的 400 是两回事。
The Fix(解决方案)
第一步:改成新语法,并带上默认规则
curl -X PUT 'http://localhost:7700/indexes/books_sort/settings/ranking-rules' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary '["words","typo","proximity","attributeRank","sort","wordPosition","exactness","release_date:desc"]'
返回 taskUid,type 为 settingsUpdate。
第二步:等任务完成
轮询 GET /tasks/{taskUid} 直到 status: succeeded,再搜索验证。没等完就搜,新规则不生效。
第三步:验证常驻生效
不传 sort 参数直接搜,新规则已生效。本地实测 q=刘慈欣(该书库含《三体》2008 与《球状闪电》2004),加了 release_date:desc 后《三体》排到《球状闪电》前面。
恢复默认
curl -X DELETE 'http://localhost:7700/indexes/books_sort/settings/ranking-rules' \
-H 'Authorization: Bearer aSampleMasterKey'
其他排查点
- 先
GET /indexes/{uid}/settings核对当前 rankingRules,别凭记忆改。默认 7 条以实际返回为准(v1.36 起为attributeRank+wordPosition,旧文档可能仍写 6 条含attribute)。 - 自定义规则放链尾是“软排序”(tiebreaker,相关度优先),放链首是“硬排序”(业务排序优先、牺牲相关度)。
invalid_settings_ranking_rules的另一类触发是保留关键字,如_geoPoint(lat,lng):asc用于地理距离排序,误写成_geo:asc之类也会报同一错误码。
References(参考来源)
- Custom ranking rules — Meilisearch 官方文档meilisearch-docs
- Update rankingRules — Meilisearch 官方文档meilisearch-docs
- What's new in v0.22 — Meilisearch 官方博客meilisearch-blog
- Error codes — Meilisearch 官方文档meilisearch-docs
