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

这篇帮到你了吗?

刚解决了一个棘手的报错?花两分钟记录下来,帮助下一个遇到同样问题的开发者。

贡献一条解法