設置自定義排名規則時沿用舊版函數式語法
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
