從 v1.15 之前的版本升級上來、索引裡本來就存著中文數據的話,升級後如果不重建索引(reindex),中文查詢和中文文檔會被無視——搜索命中為空或明顯偏少,也不報錯。原因不是升級壞了,是 v1.15 換了 Charabia 的中文分詞策略,舊索引裡的 token 還是舊版本切出來的,跟新查詢對不上。觸發一次 reindex 就恢復。這條只對「從 v1.15 之前升級上來、庫裡已有中文」的實例成立;全新安裝 v1.54.3 中文開箱可用,沒有這個問題。
Issue & Env(案發現場與環境)
- 觸發場景:實例原本跑在 v1.15 之前的版本(如 v1.14 及更早),索引裡已有中文數據。用 dumpless upgrade 之類的方式升級到 v1.15+ 之後,之前能搜到的中文詞突然搜不到,或者命中數量驟減。
- 環境:Meilisearch v1.15 及以上(本文背景實例升級到 v1.54.3)。跟 master key、索引 uid、有沒有加
filter都無關。 - 適用邊界:只有「先有中文數據 → 再升級到 v1.15+」這一條路徑會中招。全新空庫、之後才灌中文文檔的 v1.54.3 實例,中文分詞是開箱就對的(本地實跑 v1.54.3,搜「三體」直接命中 id 1)。
- 關鍵區分:它不是報錯,沒有 4xx,沒有例外堆疊。搜索請求正常返回 200,只是結果不對——中文部分像是沒進過索引。
StackTrace(堆疊日誌)
這一條是官方說明型問題,沒有報錯文本。官方 v1.15 release notes 裡的原文提示就是判斷依據:
We’ve enhanced the Charabia tokenizer to provide more precise segmentation of Chinese text. If your dataset contains Chinese-language content, you must reindex your database. Otherwise, Chinese queries and documents will not be processed correctly and may be ignored during search.
(來源:Meilisearch 1.15 release notes)
對應的現象是搜索返回 200 但命中為空或偏少。比如重建前搜一箇中文詞,返回類似:
{
"hits": [],
"query": "三体",
"processingTimeMs": 0,
"limit": 20,
"offset": 0,
"estimatedTotalHits": 0
}
這裡貼的是「中文被忽略」時 search 響應的形態(命中為空),不是報錯 JSON——它不是錯誤,Meilisearch 不會為此返回錯誤碼。要確認,請看下一節的判斷方法。
Reproduce(復現步驟)
在升級後的實例上按順序確認:
# 1. 确认当前版本 ≥ v1.15
curl -s http://localhost:7700/version \
-H 'Authorization: Bearer aSampleMasterKey'
# 2. 搜一个库里的中文词,观察 estimatedTotalHits
curl -s -X POST http://localhost:7700/indexes/books_zh/search \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '{"q":"三体"}'
# 3. 查看该索引 localizedAttributes 是否为 null(未声明语言)
curl -s http://localhost:7700/indexes/books_zh/settings/localized-attributes \
-H 'Authorization: Bearer aSampleMasterKey'
如果版本 ≥ v1.15、數據在升級前就存在、中文詞命中為空或偏少,基本可以判定是舊索引沒重建。
Root Cause(根因分析)
v1.15 換了中文分詞策略
Meilisearch 的分詞由 Charabia 負責。v1.15 增強了它對中文的切分精度(對應 GitHub release 裡更新 charabia 的動作)。分詞結果在索引階段就寫進了倒排索引——文檔裡的每個 token、它的位置信息都落盤了。
舊索引裡的 token 是舊分詞器切的
升級 Meilisearch 二進制不會自動重切已經索引好的文檔。舊索引裡存的是老版本 Charabia 切出來的中文 token;升級後查詢側用的是新版本分詞邏輯,兩邊對不上,中文部分自然匹配不到。這不是數據丟了,是索引裡的 token 過期了。
什麼時候必須重建
官方給的判定很直接:只要數據集含中文內容,升級到 v1.15 後就得重建索引。官方同時給出了三種「觸發重建」的方式,任選其一即可(它們都是會重索引全部文檔的設置變更):
- 把中文 locale 加進
localizedAttributes(例如cmn); - 改動 stop words 或自定義
dictionary; - 刷新
searchableAttributes——先把某個屬性移出列表,等移除任務完成後再加回來。
The Fix(解決方案)
方式一:加中文 locale 觸發重建
curl -X PUT 'http://localhost:7700/indexes/books_zh/settings/localized-attributes' \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '[{"locales":["cmn"],"attributePatterns":["*_zh"]}]'
返回 {"taskUid":...,"type":"settingsUpdate"},這是異步任務,會重建該索引全部文檔。
方式二:改動 dictionary 或 stop words 觸發重建
對 dictionary 或 stopWords 做一次實際變更(哪怕加一個詞)同樣會觸發重索引:
curl -X PUT 'http://localhost:7700/indexes/books_zh/settings/dictionary' \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
-d '["未来科技"]'
方式三:dump 恢復
用 dump 導出再導入到新版本,也能在建索引時用新分詞器重建全部數據。官方把 dump 列為重建索引的推薦方式之一。
別忘了等任務完成
以上方式返回的都是 taskUid,要輪詢到 succeeded 才算重建完:
curl -s http://localhost:7700/tasks/<taskUid> \
-H 'Authorization: Bearer aSampleMasterKey'
任務跑完再搜,中文恢復命中。
邊界提醒
- 如果你是從 v1.15 之前升級上來的,重建一次就夠,之後正常用。
- 全新安裝 v1.54.3、之後再灌中文數據的實例不需要做這些,中文本來就可用。
- 重建會重新索引該索引的全部文檔,數據量大時耗時較長,安排在低峰期做。
References(參考來源)
- Meilisearch 1.15 release notes — Meilisearch Blogmeilisearch-docs
- Meilisearch v1.15.0 — GitHub Releasegithub-release
- Settings — Meilisearch 官方文檔meilisearch-docs
