添加文檔後立即搜索返回空結果,不是文檔沒加成功,是異步任務還沒跑完。Meilisearch 的文檔添加是異步操作,POST 返回的
taskUid只表示任務入隊,文檔尚未被索引。必須輪詢GET /tasks/{taskUid}直到status變為succeeded,文檔才可搜索。適用 Meilisearch 全版本。
Issue & Env(案發現場與環境)
- 業務場景:通過
POST /indexes/{uid}/documents添加了一批文檔,API 返回了taskUid,緊接著調用POST /indexes/{uid}/search搜索,返回hits為空陣列或estimatedTotalHits為 0。 - 環境:Meilisearch v1.54.3,curl / JS SDK / Python SDK 均可復現。
- 關鍵區分:這不是索引創建失敗,也不是 master key 認證問題,是異步任務尚未完成。文檔確實已收到(
receivedDocuments > 0),但還沒建完倒排索引。
StackTrace(堆疊日誌)
添加文檔後立即搜索,返回空結果:
{
"hits": [],
"query": "botman",
"processingTimeMs": 0,
"limit": 20,
"offset": 0,
"estimatedTotalHits": 0
}
查看任務狀態,發現還停在 enqueued:
{
"uid": 0,
"indexUid": "movies",
"status": "enqueued",
"type": "documentAdditionOrUpdate",
"details": {
"receivedDocuments": 19547,
"indexedDocuments": null
},
"enqueuedAt": "2026-10-02T09:25:53.000000Z",
"startedAt": null,
"finishedAt": null
}
indexedDocuments 為 null 說明還沒開始索引。等幾秒後再查,狀態變成 succeeded:
{
"uid": 0,
"indexUid": "movies",
"status": "succeeded",
"type": "documentAdditionOrUpdate",
"details": {
"receivedDocuments": 19547,
"indexedDocuments": 19547
},
"duration": "PT0.030750S",
"enqueuedAt": "2026-10-02T09:25:53.000000Z",
"startedAt": "2026-10-02T09:25:53.352490Z",
"finishedAt": "2026-10-02T09:25:53.380038Z"
}
此時再搜索才能命中。
官方 FAQ 原文:
I uploaded documents but get no search results — Your document upload likely failed. Check the status of the task using the returned
taskUid.
Reproduce(復現程式碼)
# 1. 添加文档
curl -X POST 'http://localhost:7700/indexes/movies/documents?primaryKey=id' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer aSampleMasterKey' \
--data-binary @movies.json
# 返回:{"taskUid": 0, "indexUid": "movies", "status": "enqueued", "type": "documentAdditionOrUpdate", ...}
# 2. 立即搜索——返回空
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
--data-binary '{"q": "botman"}'
# 返回:{"hits": [], "estimatedTotalHits": 0, ...}
Root Cause(根因分析)
所有寫操作都是異步的
Meilisearch 的設計哲學是把耗時操作全部異步化。官方異步操作指南原文:
Many operations in Meilisearch are processed asynchronously. These API requests are not handled immediately—instead, Meilisearch places them in a queue and processes them in the order they were received.
異步操作包括:創建 / 更新 / 刪除索引、更新設置、添加 / 更新 / 刪除文檔、創建 dump / snapshot 等。API 請求被放入 FIFO 隊列,逐個處理。請求立即返回一個 summarized task object(含 taskUid、status: enqueued),客戶端需要輪詢 GET /tasks/{taskUid} 等待 status 變為 succeeded。
任務狀態流轉
任務狀態經過四個階段:
enqueued:任務已入隊,等待處理processing:Meilisearch 正在處理succeeded:處理成功,數據可搜索failed:處理失敗,數據庫無變更
在 enqueued 或 processing 狀態下搜索,文檔尚未進入倒排索引,自然搜不到。只有 succeeded 後文檔才可搜索。
為什麼不是同步的
Meilisearch 把索引構建和搜索查詢分離,搜索請求永遠優先於索引任務。這樣即使後臺正在索引數百萬文檔,前臺搜索響應不受影響。代價是客戶端必須自行輪詢任務狀態——沒有“索引完成”的回調推送(v1.x 有實驗性的 stream 端點,但主流用法還是輪詢)。
The Fix(解決方案)
第一步:拿到 taskUid 後輪詢任務狀態
# 添加文档后拿到 taskUid=0,轮询直到 succeeded
curl http://localhost:7700/tasks/0 \
-H 'Authorization: Bearer aSampleMasterKey'
第二步:循環等待直到 status=succeeded
用 shell 輪詢:
TASK_UID=0
while true; do
STATUS=$(curl -s "http://localhost:7700/tasks/${TASK_UID}" \
-H 'Authorization: Bearer aSampleMasterKey' | jq -r '.status')
if [ "$STATUS" = "succeeded" ]; then
echo "Indexing complete"
break
elif [ "$STATUS" = "failed" ]; then
echo "Indexing failed"
curl -s "http://localhost:7700/tasks/${TASK_UID}" \
-H 'Authorization: Bearer aSampleMasterKey' | jq '.error'
break
fi
sleep 1
done
用 Python SDK 等待:
from meilisearch_sdk import Client
client = Client('http://localhost:7700', 'aSampleMasterKey')
index = client.index('movies')
# 添加文档,拿到 task
task = index.add_documents(movies_json)
# 等待任务完成(SDK 内置轮询)
client.wait_for_task(task.task_uid)
# 或指定超时和间隔
client.wait_for_task(task.task_uid, timeout_in_ms=60000, interval_in_ms=500)
第三步:任務成功後再搜索
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Authorization: Bearer aSampleMasterKey' \
-H 'Content-Type: application/json' \
--data-binary '{"q": "botman"}'
# 现在能搜到了:{"hits": [...], "estimatedTotalHits": 21, ...}
注意事項
- 如果任務狀態是
failed,檢查error字段。常見原因:primary key 推斷失敗、文檔格式錯誤。 - 大數據集索引時間較長(萬級文檔通常 <1 秒,百萬級可能數分鐘)。
- 中斷 Meilisearch 進程是安全的——
processing狀態的任務會重置為enqueued,重啟後繼續處理。 - 官方 FAQ 還提示:如果
status已經是succeeded但仍然搜不到,檢查indexedDocuments是否等於receivedDocuments,不等說明部分文檔被跳過。
References(參考來源)
- FAQ — Meilisearch 官方文檔meilisearch-docs
- Tasks and asynchronous operations — Meilisearch 官方文檔meilisearch-docs
- Quick start — Meilisearch 官方文檔meilisearch-docs
- Tasks API — Meilisearch 規範文檔meilisearch-spec
- Working with tasks — Meilisearch 官方文檔meilisearch-docs
