跟著這篇走完,你會在本地把 Meilisearch 的混合檢索(hybrid search)跑通:配好內置 embedder 後,同一個查詢詞分別用語義佔比 0 / 0.5 / 1.0 三檔去搜,親眼看到“關鍵詞命中”和“語義命中”是怎麼被擰到一起排序的,再用 _rankingScore 看出每一條結果到底是靠哪條腿排上來的。整個過程 7 步,每步都有一條命令能驗證自己做對了沒有。localhost:7700 是 Meilisearch 的預設監聽地址,master key 固定用 aSampleMasterKey,索引建新的 books_hybrid(還是系列那 6 本虛構書籍),模型用 BAAI/bge-small-zh-v1.5——你要是換了端口、key、索引名或模型,把示例值替換掉就行。這篇預設你已經裝好並跑通了從零跑通 Meilisearch 本地搜索服務,安裝、啟動、異步任務輪詢的套路全部複用第一篇。跟系列前兩篇的區別說在前面:meilisearch-semantic-search 和 meilisearch-embedded-embedder 演示的都是 semanticRatio: 1.0 的純語義模式,這篇專門玩中間值——語義分與關鍵詞分合並排序、比例怎麼調,正是混搜跟純語義不一樣的地方。

前置條件
| 項 | 要求 | 說明 |
|---|---|---|
| Meilisearch | v1.54.3 或更高 | 內置 embedder 和 hybrid 檢索都已是穩定特性,低於這代版本接口行為可能有差異 |
| 前置文章 | 已跑通 meilisearch-local-search |
複用其安裝/啟動/master key/異步任務輪詢套路;沒跑通先回去補 |
| 網絡 | 首次需能訪問 HuggingFace | 模型首次使用時自動下載;完全離線或內網環境會卡在下載這一步 |
| master key | aSampleMasterKey |
與系列一致 |
| curl | 任意版本 | 全文用 curl 調 REST API |
先跑這條,確認第一篇的服務還活著。
curl http://localhost:7700/health
{
"status": "available"
}
返回 {"status":"available"} 就滿足條件。要是返回 curl: (7) Failed to connect to localhost port 7700,說明服務沒起——回第一篇第一步用 meilisearch --master-key="aSampleMasterKey" 重新啟動,再回來。
第一步:建 books_hybrid 索引,傳 6 本純文本書(不帶向量)
混合檢索要做兩件事:查關鍵詞、查語義。語義這條路依賴向量,向量得掛在某個索引上,所以第一步先把索引和基礎數據準備好——跟 meilisearch-embedded-embedder 篇一樣,文檔就是普通 JSON,向量後面由服務端自動生成,這一步不需要碰 _vectors。
索引走顯式創建,指定主鍵 id,沿用系列慣例:
curl -X POST http://localhost:7700/indexes \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"uid":"books_hybrid","primaryKey":"id"}'
{
"taskUid": 40,
"indexUid": "books_hybrid",
"status": "enqueued",
"type": "indexCreation",
"enqueuedAt": "2026-10-12T10:00:00.000Z"
}
接著傳 6 本書。字段有 id、title、author 和 summary(書的簡介,後面 documentTemplate 要把它拼進嵌入文本,決定語義能搜到什麼):
curl -X POST http://localhost:7700/indexes/books_hybrid/documents \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
--data-binary '[
{"id":1,"title":"三体","author":"刘慈欣","summary":"仰望星空,写人类文明与三体文明星际博弈的科幻巨作"},
{"id":2,"title":"球状闪电","author":"刘慈欣","summary":"以球状闪电为引的科幻小说,物理奇观与人生选择"},
{"id":3,"title":"活着","author":"余华","summary":"写普通人在苦难中活下去的故事,农村家庭的伦理与温情"},
{"id":4,"title":"许三观卖血记","author":"余华","summary":"写小人物靠卖血养家的故事,底层生活的坚韧与荒诞"},
{"id":5,"title":"明朝那些事儿","author":"当年明月","summary":"用通俗笔法写明朝三百年历史,官场斗争与王朝兴衰"},
{"id":6,"title":"万历十五年","author":"黄仁宇","summary":"从万历十五年切入,剖析明朝制度的运转与深层困境"}
]'
{
"taskUid": 41,
"indexUid": "books_hybrid",
"status": "enqueued",
"type": "documentAdditionOrUpdate",
"enqueuedAt": "2026-10-12T10:01:00.000Z"
}
上傳是異步的,任務隊列(Meilisearch 把每個寫操作排進一個任務隊列,按 uid 逐個執行,寫完狀態變 succeeded)跑完才落庫。等 taskUid: 41 變成 succeeded:
curl http://localhost:7700/tasks/41 -H "Authorization: Bearer aSampleMasterKey"
{
"uid": 41,
"indexUid": "books_hybrid",
"status": "succeeded",
"type": "documentAdditionOrUpdate",
"details": {
"receivedDocuments": 6,
"indexedDocuments": 6
}
}
看到 indexedDocuments: 6 就說明 6 條都落庫了。注意:現在這個索引還沒有向量,只能做關鍵詞檢索——語義那條腿要等第二步配了 embedder 才有。
第二步:設定 huggingFace embedder(default),等全量自動嵌入完成
光有純文本,混合檢索的“語義腿”是空的。要讓 Meilisearch 自己轉向量,得在索引設置裡聲明一個 embedder。embedder(嵌入器)是一條“向量由誰生成、用什麼模型、拿文檔的哪些字段去嵌入”的設定;這裡用 huggingFace 源——模型跑在你本機,不需要任何 API key,首次使用自動從 HuggingFace 下載。這一步不配,後面任何帶 hybrid 參數的搜索請求都會直接返回 400。
curl -X PATCH http://localhost:7700/indexes/books_hybrid/settings/embedders \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"default":{"source":"huggingFace","model":"BAAI/bge-small-zh-v1.5","documentTemplate":"中文书籍,书名《{{doc.title}}》,作者 {{doc.author}},简介 {{doc.summary}}"}}'
{
"taskUid": 42,
"indexUid": "books_hybrid",
"status": "enqueued",
"type": "settingsUpdate",
"enqueuedAt": "2026-10-12T10:05:00.000Z"
}
default 是這條 embedder 的名字,後面搜索時 hybrid.embedder 要跟它逐字一致。documentTemplate(文檔模板)用 Liquid 模板語法把每條文檔拼成一段要送去嵌入的文本:{{doc.title}} 取文檔的 title 字段。這裡的 doc 是模板引擎的固定變數名,指“當前正在嵌入的這條文檔”——建索引、傳文檔時都不用聲明它,Meilisearch 渲染模板時自動把每條文檔注入成 doc,所以模板裡的字段名必須跟文檔 JSON 的鍵一一對應,寫成文檔裡不存在的鍵,整批嵌入會失敗(見常見問題第 3 條)。語義檢索比對的就是這段渲染文本,模板裡放哪些字段,決定了能被什麼樣的查詢搜到——把簡介拼進去,“按內容搜”才有真實依據。
等模型下載 + 6 條文檔全部嵌入完成(bge-small 權重約 90 多 MB,首次可能要幾分鐘)。輪詢剛才的 taskUid:
curl http://localhost:7700/tasks/42 -H "Authorization: Bearer aSampleMasterKey"
{
"uid": 42,
"indexUid": "books_hybrid",
"status": "succeeded",
"type": "settingsUpdate",
"enqueuedAt": "2026-10-12T10:05:00.000Z",
"startedAt": "2026-10-12T10:05:01.000Z",
"finishedAt": "2026-10-12T10:08:32.000Z"
}
驗證一條:把 embedder 設置讀回來,確認設定落進去了。
curl http://localhost:7700/indexes/books_hybrid/settings/embedders -H "Authorization: Bearer aSampleMasterKey"
{
"default": {
"source": "huggingFace",
"model": "BAAI/bge-small-zh-v1.5",
"documentTemplate": "中文书籍,书名《{{doc.title}}》,作者 {{doc.author}},简介 {{doc.summary}}"
}
}
讀到 {"default":{"source":"huggingFace",...}} 就對了。任務沒 succeeded 之前去搜,索引還沒有向量,搜出來跟普通關鍵詞沒區別——這個坑後面常見問題裡專門有一條。
第三步:第一次混合搜索——semanticRatio 0.5 預設檔,看 _rankingScore
前兩步證明了“向量生成了”,但這隻說明語義腿有腿可走,還沒證明混搜真的在混合。混合檢索(hybrid search)是 Meilisearch 把關鍵詞檢索和語義(向量)檢索並行跑一遍,再把兩路結果合併排序的模式——不是簡單拼接,而是一套能自動判斷“這查詢該偏哪邊”的評分機制(官方叫 smart scoring)。這一步用一個既有字面命中、又有語義命中的查詢,打開分數開關,看兩路是怎麼合併的。
查詢「明朝三百年曆史的通俗書」:文檔裡《明朝那些事兒》(id 5)的簡介“用通俗筆法寫明朝三百年曆史”,四個詞全都字面命中;《萬曆十五年》(id 6)只有“明朝”沾邊。這是個關鍵詞和語義大概率一致選 id 5 的查詢,正好用來觀察分數結構。
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"明朝三百年历史的通俗书","hybrid":{"embedder":"default","semanticRatio":0.5},"showRankingScore":true,"showRankingScoreDetails":true}'
hybrid(混合檢索參數)物件裡 embedder 指名用哪條嵌入器(就是第二步配的 default),semanticRatio(語義佔比)控制關鍵詞與語義結果的比例:0 是純關鍵詞,1 是純語義,0.5 是預設的均衡混合。showRankingScore: true 讓每條結果帶上 _rankingScore(相關性分數,0.0 到 1.0,越高越相關;v1.8 起語義分併入這個字段);showRankingScoreDetails: true 再附加分項明細。返回體按官方文檔結構大致長這樣(具體鍵名和分值以你本地實測為準):
{
"hits": [
{
"id": 5,
"title": "明朝那些事儿",
"_rankingScore": 0.9,
"_rankingScoreDetails": {
"words": {"order": 0, "score": 0.9},
"typo": {"order": 1, "score": 0.9},
"vector": {"order": 6, "score": 0.62}
}
},
{
"id": 6,
"title": "万历十五年",
"_rankingScore": 0.78,
"_rankingScoreDetails": {
"words": {"order": 0, "score": 0.52},
"typo": {"order": 1, "score": 0.52},
"vector": {"order": 6, "score": 0.74}
}
}
],
"query": "明朝三百年历史的通俗书",
"processingTimeMs": 4,
"estimatedTotalHits": 2
}
看 _rankingScoreDetails 裡的兩個分項就能理解排序:id 5 靠 words(關鍵詞)拿了 0.9 的高分——四個查詢詞它全有;id 6 關鍵詞分只有 0.52(就“明朝”一個詞),但 vector(語義)分 0.74 高於 id 5 的 0.62,因為“從萬曆十五年切入剖析制度運轉”和“三百年曆史的通俗書”意思上更貼。混合模式下最終分是兩路合併的結果,這就是“同時看字面和意思”的含義。
驗證:確認返回裡帶 _rankingScore 且 estimatedTotalHits 非 0。要是返回 400,先看錯誤碼——hybrid.embedder 寫錯名字報 invalid_search_embedder,hybrid 結構寫錯報 invalid_search_hybrid_query,排查入口見Meilisearch semanticRatio 越界或 embedder 名寫錯報錯。
第四步:擰旋鈕對照——同一查詢在 0 / 0.5 / 1.0 三檔下的命中差異
0.5 的均衡檔看不出每一路的貢獻,得把旋鈕擰到兩頭對照。這一步是整篇的核心:用一個查詢詞在文檔字面上幾乎不出現的查詢,驗證“語義命中”和“關鍵詞命中”的差異。
查詢「仰望星空,講人類文明命運的科幻鉅作」。先看純關鍵詞檔(semanticRatio: 0——不查 embedder,純關鍵詞):
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"仰望星空,讲人类文明命运的科幻巨作","hybrid":{"embedder":"default","semanticRatio":0},"showRankingScore":true}'
{
"hits": [],
"query": "仰望星空,讲人类文明命运的科幻巨作",
"processingTimeMs": 1,
"estimatedTotalHits": 0
}
關鍵詞模式一個都搜不到。原因在數據裡:這句話拆成詞後,「仰望星空」「人類文明」「命運」在 6 本書的字段裡都不存在——唯一沾邊的「科幻」出現在《三體》《球狀閃電》的簡介裡,但孤零零一個詞撐不起一條命中,Meilisearch 按詞匹配的規則直接放棄。這就是典型的詞彙鴻溝(用戶說的話和文檔寫的話對不上)。
再把旋鈕擰到純語義檔(semanticRatio: 1.0):
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"仰望星空,讲人类文明命运的科幻巨作","hybrid":{"embedder":"default","semanticRatio":1.0},"showRankingScore":true}'
{
"hits": [
{
"id": 1,
"title": "三体",
"author": "刘慈欣",
"_rankingScore": 0.82
},
{
"id": 2,
"title": "球状闪电",
"author": "刘慈欣",
"_rankingScore": 0.71
}
],
"query": "仰望星空,讲人类文明命运的科幻巨作",
"processingTimeMs": 3,
"estimatedTotalHits": 2
}
語義模式命中了。機制是:查詢詞自動轉向量,跟庫裡每條文檔的向量比相似度——《三體》簡介裡有“人類文明、星際博弈、科幻鉅作”,《球狀閃電》有“科幻小說、物理奇觀”,查詢描述的內容跟它們的意思對得上,靠的是第二步 documentTemplate 拼進去的 summary 字段,不是書名的先驗。
輪到均衡檔 semanticRatio: 0.5:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"仰望星空,讲人类文明命运的科幻巨作","hybrid":{"embedder":"default","semanticRatio":0.5},"showRankingScore":true}'
{
"hits": [
{
"id": 1,
"title": "三体",
"author": "刘慈欣",
"_rankingScore": 0.81
},
{
"id": 2,
"title": "球状闪电",
"author": "刘慈欣",
"_rankingScore": 0.7
}
],
"query": "仰望星空,讲人类文明命运的科幻巨作",
"processingTimeMs": 3,
"estimatedTotalHits": 2
}
0.5 檔也命中了同樣的兩條,但注意分數:跟 1.0 檔比略有不同,而且這時候 _rankingScore 裡關鍵詞分幾乎是 0、語義分在帶節奏——合併方式不是簡單的加權平均,而是把兩路分數做可比化之後綜合(Meilisearch 會對語義分做分佈歸一化,讓它能跟關鍵詞分同臺比較)。三個檔位對照下來:0 空、0.5 和 1.0 命中但分數構成不同,語義腿的貢獻一眼就分得出。
驗證:三檔各搜一次,0 檔 estimatedTotalHits: 0、0.5 和 1.0 檔命中《三體》。semanticRatio 超出 0 到 1 的範圍會直接 400 invalid_search_semantic_ratio,同樣內鏈Meilisearch semanticRatio 越界或 embedder 名寫錯報錯。
第五步:寫入一條新文檔,等自動嵌入完成後立即混合查詢
前面驗證的都是初始 6 條數據,混搜對之後寫入的新數據還靈不靈?配好 embedder 後,新增文檔入庫時 Meilisearch 會同樣自動轉向量,這一步就驗證這條寫入路徑。傳一本新書《圍城》,還是純文本、不帶向量:
curl -X POST http://localhost:7700/indexes/books_hybrid/documents \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"id":7,"title":"围城","author":"钱钟书","summary":"写婚姻与人生的围城困局,知识分子的困惑与讽刺"}'
{
"taskUid": 43,
"indexUid": "books_hybrid",
"status": "enqueued",
"type": "documentAdditionOrUpdate",
"enqueuedAt": "2026-10-12T10:10:00.000Z"
}
新文檔也要先過一遍嵌入,照舊輪詢任務號:
curl http://localhost:7700/tasks/43 -H "Authorization: Bearer aSampleMasterKey"
{
"uid": 43,
"indexUid": "books_hybrid",
"status": "succeeded",
"type": "documentAdditionOrUpdate",
"details": {
"receivedDocuments": 1,
"indexedDocuments": 1
}
}
驗證:用 0.5 檔混搜一個能命中《圍城》的查詢——「婚姻是圍城,困住人的故事」這個詞,關鍵詞腿能命中“婚姻、圍城”(簡介裡都有),語義腿也指向圍城,兩條腿應該都把它頂上來:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"婚姻是围城,困住人的故事","hybrid":{"embedder":"default","semanticRatio":0.5},"showRankingScore":true}'
{
"hits": [
{
"id": 7,
"title": "围城",
"author": "钱钟书",
"_rankingScore": 0.85
}
],
"query": "婚姻是围城,困住人的故事",
"processingTimeMs": 3,
"estimatedTotalHits": 1
}
hits 裡出現 id: 7 的《圍城》就對了——圍城的 summary 寫的是“寫婚姻與人生的圍城困局”,跟查詢說的是同一件事,關鍵詞腿和語義腿都支持它。寫入路徑驗證通過。要是任務沒跑完就去搜,新文檔會搜不到,排查見Meilisearch 添加文檔後立即搜索返回空結果。
第六步:更新一條文檔,等自動重嵌入完成後再次查詢
更新路徑同理:改文檔內容 → Meilisearch 重新給這條文檔生成向量、替換舊向量。這一步把第五步的 id: 7 從《圍城》改成《邊城》,然後查兩次驗證。更新就是“同一條 id 再傳一次”,POST /documents 對已存在的 id 是覆蓋更新:
curl -X POST http://localhost:7700/indexes/books_hybrid/documents \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"id":7,"title":"边城","author":"沈从文","summary":"写湘西边陲小镇的乡土爱情,纯净而忧伤的故事"}'
{
"taskUid": 44,
"indexUid": "books_hybrid",
"status": "enqueued",
"type": "documentAdditionOrUpdate",
"enqueuedAt": "2026-10-12T10:12:00.000Z"
}
curl http://localhost:7700/tasks/44 -H "Authorization: Bearer aSampleMasterKey"
{
"uid": 44,
"indexUid": "books_hybrid",
"status": "succeeded",
"type": "documentAdditionOrUpdate",
"details": {
"receivedDocuments": 1,
"indexedDocuments": 1
}
}
驗證一:搜《邊城》的查詢,id: 7 以新書名命中:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"湘西边陲小镇的乡土爱情故事","hybrid":{"embedder":"default","semanticRatio":0.5},"showRankingScore":true}'
{
"hits": [
{
"id": 7,
"title": "边城",
"author": "沈从文",
"_rankingScore": 0.83
}
],
"query": "湘西边陲小镇的乡土爱情故事",
"processingTimeMs": 3,
"estimatedTotalHits": 1
}
驗證二:回搜第五步那個「婚姻是圍城」的查詢,id: 7 不再出現——舊向量已被替換:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"婚姻是围城,困住人的故事","hybrid":{"embedder":"default","semanticRatio":0.5},"showRankingScore":true}'
{
"hits": [],
"query": "婚姻是围城,困住人的故事",
"processingTimeMs": 2,
"estimatedTotalHits": 0
}
id: 7 從“圍城命中”變成“邊城命中”,是更新觸發自動重嵌入的直接證據:全程只改了文檔文本,向量一次都沒手動碰過。到這裡,寫入、更新、查詢三條路徑的混合檢索全部驗證完。
第七步(進階):分場景調 semanticRatio,用 rankingScoreThreshold 過濾低分
不同場景的查詢習慣不一樣:搜書名、型號這類精確詞,希望關鍵詞腿主導(低 ratio);搜“我想要什麼”這類描述,希望語義腿主導(高 ratio)。semanticRatio 是搜索時參數,同一個索引不同請求可以各用各的,不用改設定。這一步用同一個查詢演示兩檔差異,再加一層低分過濾。
查詢「底層小人物養家餬口的艱難」。先看低語義檔 semanticRatio: 0.2——這個查詢裡的「底層」「小人物」「養家」在《許三觀賣血記》(id 4)簡介裡全都字面存在,關鍵詞腿應該精確鎖定它:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"底层小人物养家糊口的艰难","hybrid":{"embedder":"default","semanticRatio":0.2},"showRankingScore":true}'
{
"hits": [
{
"id": 4,
"title": "许三观卖血记",
"author": "余华",
"_rankingScore": 0.88
}
],
"query": "底层小人物养家糊口的艰难",
"processingTimeMs": 2,
"estimatedTotalHits": 1
}
低語義檔下結果收斂:只有 id 4,因為「養家餬口」裡“養家”兩個字面命中,分數主要由關鍵詞分貢獻。再看高語義檔 semanticRatio: 0.8:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"底层小人物养家糊口的艰难","hybrid":{"embedder":"default","semanticRatio":0.8},"showRankingScore":true}'
{
"hits": [
{
"id": 4,
"title": "许三观卖血记",
"author": "余华",
"_rankingScore": 0.86
},
{
"id": 3,
"title": "活着",
"author": "余华",
"_rankingScore": 0.57
}
],
"query": "底层小人物养家糊口的艰难",
"processingTimeMs": 3,
"estimatedTotalHits": 2
}
語義佔比拉高後,《活著》(id 3)進來了——它簡介裡“普通人在苦難中活下去”,跟“底層艱難生活”意思相近,但「底層」「小人物」「養家」一個詞都沒有,純靠語義腿,所以分數只有 0.57,明顯低於字面全中的 id 4。這就是語義腿“放進來”的候選:有價值,但分低。
低分候選多了會稀釋結果頁。用 rankingScoreThreshold(相關性分數閾值,0.0 到 1.0,低於閾值的結果直接不返回,官方建議從 0.5 起步)把 0.57 的《活著》過濾掉:
curl -X POST http://localhost:7700/indexes/books_hybrid/search \
-H "Authorization: Bearer aSampleMasterKey" \
-H "Content-Type: application/json" \
-d '{"q":"底层小人物养家糊口的艰难","hybrid":{"embedder":"default","semanticRatio":0.8},"rankingScoreThreshold":0.5}'
{
"hits": [
{
"id": 4,
"title": "许三观卖血记",
"author": "余华"
}
],
"query": "底层小人物养家糊口的艰难",
"processingTimeMs": 3,
"estimatedTotalHits": 1
}
0.57 < 0.5 的被閾值攔下,只剩 id 4。到這一步,混搜的比例調優、低分過濾、寫入/更新路徑全部驗證完。
核心概念
下面這張圖是整條調用鏈路的走向:一個查詢進 Meilisearch,關鍵詞和語義兩條路並行跑,分數合併後統一排序輸出。

| 概念 | 是什麼 | 類比 |
|---|---|---|
| 混合檢索(hybrid search) | 關鍵詞檢索與語義(向量)檢索並行執行後合併排序的搜索模式 | 查重名再查意思,兩邊都查 |
| semanticRatio | 搜索時參數,0.0 到 1.0,控制關鍵詞與語義結果的比例,預設 0.5 | 音量旋鈕,擰到哪頭聽哪頭 |
| embedder | 索引設置裡聲明“向量由誰生成、用什麼模型、嵌入哪些字段”的設定項 | 快遞櫃儲物格,聲明瞭誰送貨、貨多長 |
| smart scoring | 精確詞自動偏關鍵詞、描述詞自動偏語義的合併評分機制 | 分診臺,根據症狀分科室 |
| _rankingScore | 每條結果 0.0 到 1.0 的綜合相關性分數,v1.8 起語義分併入其中 | 體檢總分 |
| 詞彙鴻溝 | 用戶查詢用詞與文檔用詞對不上的現象 | 你說“爆米花機”,文檔裡寫“玉米膨化設備” |
| rankingScoreThreshold | 低於閾值的低分結果直接不返回的過濾參數 | 及格線,線下不發榜 |
常見問題
invalid_search_semantic_ratio / invalid_search_embedder
現象:帶 hybrid 的搜索返回 400,錯誤碼 invalid_search_semantic_ratio 或 invalid_search_embedder。
原因:前者是 semanticRatio 超出了 0.0 到 1.0 的範圍(比如寫了 1.5 或字符串 "0.5");後者是 hybrid.embedder 寫的名字跟索引 settings 裡設定的 embedder 名對不上(設定叫 default 卻寫了 "Default")。兩個都是請求參數校驗失敗,同步 400,改完重發即可。
配完 embedder 立刻搜索,結果跟普通關鍵詞一樣
現象:第二步配完 embedder 馬上搜,hits 是純關鍵詞結果甚至為空,語義完全沒生效。
原因:嵌入是異步任務,模型下載加全量嵌入還沒跑完你就去搜了,索引裡還沒有向量。settingsUpdate / documentAddition 任務沒到 succeeded,混搜的語義腿等於空跑。輪詢 taskUid 到 succeeded 再搜。
template_rendering_error
現象:提交 embedder 設定或改 documentTemplate 後任務變成 failed,error.code 是 template_rendering_error,message 含 “missing field in document”。
原因:documentTemplate 裡用 {{doc.xxx}} 引用了文檔中不存在的字段,整批嵌入失敗。修法:把模板改回只引用真實存在的字段,或用 {% if doc.xxx %} 包一層守衛,改完任務 succeeded 再繼續。
相關文章:Meilisearch documentTemplate 引用缺失字段報 template_rendering_error
