StackTraces
Meilisearch已驗證

Meilisearch federated search 在 queries 裡寫 offset/limit 被忽略

@debug_master1 天前更新閱讀 6 min00

federated search 的分頁是合併結果層面的——所有索引的結果混在一起後再分頁。所以分頁參數必須放在 federation 物件裡,寫在單條 query 裡的 offset / limit / page / hitsPerPage 全部被靜默忽略,不報錯但也不生效。這是 Meilisearch 官方 API reference 明確寫的限制:「These options are not compatible with federated searches.」

Issue & Env(案發現場與環境)

  • 業務場景:federated search 搜 movies 和 movie_ratings 兩個索引,想讓 movies 只返回前 5 條、movie_ratings 返回前 10 條。結果發現兩個索引都返回了 20 條(預設 limit)——queries 裡寫的 limit 參數完全沒生效。
  • 環境:Meilisearch v1.54+,帶 federation: {} 或 federation 子參數的 multi-search 請求。
  • 關鍵區分:這和 multi-index search(不傳 federation)相反——multi-index 模式下,每條 query 的 offset/limit 獨立生效。一用 federation,queries 裡的分頁參數就被引擎忽略了。

StackTrace(無報錯,靜默忽略)

# federation 模式下,queries 里的 limit 被忽略
curl -X POST 'http://localhost:7700/multi-search' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '{
    "federation": {},
    "queries": [
      { "indexUid": "movies", "q": "batman", "limit": 5 },
      { "indexUid": "movie_ratings", "q": "batman", "limit": 10 }
    ]
  }'
{
  "hits": [
    {"id": 268, "title": "Batman", "_federation": {"indexUid": "movies", "queriesPosition": 0}}
  ],
  "processingTimeMs": 1,
  "limit": 20,
  "offset": 0,
  "estimatedTotalHits": 14
}

返回體裡 "limit": 20——federation 預設值,不是 queries 裡寫的 5 或 10。沒有任何報錯,queries 裡的 limit 被靜默忽略。

Root Cause(根因分析)

federated 分頁是合併層面的,不是單索引層面的

federated search 的處理流程是:

  1. 並行執行所有 query(不做單 query 分頁)
  2. 拿到所有命中文檔,按 merge 算法合併重排
  3. 對合併後的單列表做分頁

因為第 1 步不做分頁,queries 裡寫的 offset/limit/page/hitsPerPage 就沒有任何作用——引擎在執行時先忽略它們,合併完再用 federation 層的分頁參數來切。

兩套分頁體系,二選一

federation 物件裡支持兩種分頁模式:

模式 參數 返回體字段 適用場景
estimation(預設) federation.offset + federation.limit estimatedTotalHits 大部分場景,性能好
exhaustive federation.page + federation.hitsPerPage totalPages, totalHits 精確知道總數時(頁碼導航)

不能混用——同時寫 federation.offset 和 federation.page,行為未定義,實踐中避免。

對比 multi-index 模式

不傳 federation 時,每條 query 的 offset/limit/page/hitsPerPage 獨立生效——因為每條 query 返回獨立的 results 陣列,分頁在單 query 層面做。一用 federation,分頁的「層級」就從單 query 升到了合併列表。

The Fix(解決方案)

第一步:把分頁參數移到 federation 物件裡

curl -X POST 'http://localhost:7700/multi-search' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '{
    "federation": { "offset": 0, "limit": 20 },
    "queries": [
      { "indexUid": "movies", "q": "batman" },
      { "indexUid": "movie_ratings", "q": "batman" }
    ]
  }'

或者用 exhaustive 分頁:

curl -X POST 'http://localhost:7700/multi-search' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer aSampleMasterKey' \
  --data-binary '{
    "federation": { "page": 2, "hitsPerPage": 10 },
    "queries": [
      { "indexUid": "movies", "q": "batman" },
      { "indexUid": "movie_ratings", "q": "batman" }
    ]
  }'

第二步:如果需要單 query 限制,用 filter 或 weight 替代

如果你確實想讓 movies 的結果少一些、movie_ratings 的結果多一些,正確的做法不是在 query 裡寫 limit,而是用 weight 控制排名優先級——weight > 1.0 的 query 結果會更多地出現在合併列表的前面。或者在 query 里加 filter(比如只搜 genres = “Action” 的 movies)來減少命中數。

排查建議

  • 觸發 federation 模式的唯一條件:請求體裡 federation 字段存在(哪怕是 {} 空物件)。一旦 federation 存在,queries 裡的分頁參數就作廢。
  • 這不是 bug 是設計——官方 API reference 明確寫了 offset / limit / hitsPerPage / page「not compatible with federated searches」。
  • 沒有報錯 = 靜默忽略。所以調試時別假設「我寫了 limit: 5 為什麼返回了 20 條」——先確認自己是不是不小心加了 federation: {}。

References(參考來源)

最後更新於 2026-10-29

這篇幫到你了嗎?

剛解決了一個棘手的報錯?花兩分鐘記錄下來,幫助下一個遇到同樣問題的開發者。

貢獻一條解法