/multi-search 路由允许您通过将多个搜索查询捆绑到单个 HTTP 请求中,从而在一个或多个索引上执行多重搜索。多重搜索也称为联邦搜索。

将多个搜索查询捆绑到单个 API 请求中。使用此端点可以一次性搜索多个索引。

POST
/multi-search

请求体

名称类型描述
federation对象如果存在且不为 null,则返回一个合并所有指定查询搜索结果的单一列表
queries对象数组包含要执行的搜索查询列表。indexUid 搜索参数是必需的,所有其他参数都是可选的

如果 Meilisearch 在处理多重搜索请求中的任何查询时遇到错误,它将立即停止处理该请求并返回错误消息。返回的消息将仅指出遇到的第一个错误。

federation

使用 federation 来接收包含所有指定查询的所有搜索结果的单一列表,按排名分数降序排列。这称为联邦搜索。

federation 可选地包含以下参数:

参数类型默认值描述
offset整数0要跳过的文档数量
limit整数20返回的最大文档数量
facetsByIndex数组对象null显示指定索引的分面信息
mergeFacets对象null显示指定索引的分面信息

如果 federation 缺失或为 null,Meilisearch 将返回一个包含多个搜索结果对象的列表,其中列表中的每个项目对应于请求中的一个搜索查询。

facetsByIndex

facetsByIndex 必须是一个对象。其键必须与 Meilisearch 项目中的索引相对应。每个键必须与该索引的可筛选属性列表中的属性数组相关联。

"facetsByIndex": {
  "INDEX_A": ["ATTRIBUTE_X", "ATTRIBUTE_Y"],
  "INDEX_B": ["ATTRIBUTE_Z"]
}

当您指定 facetsByIndex 时,多重搜索响应将包含一个额外的 facetsByIndex 字段。响应的 facetsByIndex 是一个对象,其中包含每个查询索引的一个字段。

{
  "hits" [ ],

  "facetsByIndex": {
    "INDEX_A": {
      "distribution": {
        "ATTRIBUTE_X": {
          "KEY": <Integer>,
          "KEY": <Integer>,

        },
        "ATTRIBUTE_Y": {
          "KEY": <Integer>,

        }
      },
      "stats": {
        "KEY": {
          "min": <Integer>,
          "max": <Integer>
        }
      }
    },
    "INDEX_B": {

    }
  }
}
mergeFacets

mergeFacets 必须是一个对象,并且可能包含以下字段:

  • maxValuesPerFacet: 必须是整数。指定时,表示单个分面返回的最大值数量。默认为分配给 maxValuesPerFacet 索引设置的值。

facetsByIndexmergeFacets 都存在且不为 null 时,多重搜索响应中包含的分面信息将在所有查询的索引中合并。响应将不再包含 facetsByIndex,而是包含两个额外字段:facetDistributionfacetStats

{
  "hits": [  ],

  "facetDistribution": {
    "ATTRIBUTE": {
      "VALUE": <Integer>,
      "VALUE": <Integer>
    }
  },
  "facetStats": {
    "ATTRIBUTE": {
      "min": <Integer>,
      "max": <Integer>
    }
  }
}
联邦搜索的合并算法

联邦搜索的合并结果按排名分数降序返回。为了获得最终结果列表,Meilisearch 遵循以下比较程序:

  1. 详细排名分数按以下方式对两次命中进行归一化:
    1. 连续的相关性分数(与 wordstypoattributeexactnessvector 规则相关)将为每次命中分组为一个单一分数。
    2. sortgeosort 分数详情保持不变
  2. 归一化的详细排名分数将对两次命中进行字典顺序比较。
    1. 如果两次命中都具有相关性分数,则分数较高者胜出。如果打平,则进入下一步。
    2. 如果一个结果具有相关性分数或(地理)排序分数,Meilisearch 将选择它。
    3. 如果两个结果在相同的排序方向上都具有排序或地理排序分数,Meilisearch 将根据共同的排序方向比较这些值。根据共同排序方向必须排在首位的值所对应的结果获胜。如果打平,则进入下一步。
    4. 比较两次命中的全局排名分数以确定哪个排在前面,忽略任何排序或地理排序。
    5. 在完美打平的情况下,优先选择 queries 数组中排名最低的查询中的文档。

Meilisearch 认为两个文档相同,如果它们

  1. 来自相同的索引
  2. 并且它们的主键相同

无法指定在多个索引中将两个文档视为相同。

queries

queries 必须是一个对象数组。每个对象可能包含以下搜索参数:

搜索参数类型默认值描述
federationOptions对象null配置特定查询的联邦设置
indexUid字符串不适用请求索引的 uid
q字符串""查询字符串
offset整数0要跳过的文档数量
limit整数20返回的最大文档数量
hitsPerPage整数1每页返回的最大文档数量
page整数1请求特定结果页
filter字符串null按属性值筛选查询
facets字符串数组null显示每个分面的匹配计数
distinct字符串null将搜索限制为具有指定属性唯一值的文档
attributesToRetrieve字符串数组["*"]要在返回文档中显示的属性
attributesToCrop字符串数组null需要裁剪其值的属性
cropLength整数10裁剪值的最大字数长度
cropMarker字符串"…"标记裁剪边界的字符串
attributesToHighlight字符串数组null高亮显示属性中包含的匹配词条
highlightPreTag字符串"<em>"插入到高亮词条开头的字符串
highlightPostTag字符串"</em>"插入到高亮词条末尾的字符串
showMatchesPosition布尔值false返回匹配词条位置
sort字符串数组null按属性值排序搜索结果
matchingStrategy字符串last用于匹配文档中查询词条的策略
showRankingScore布尔值false显示文档的全局排名分数
showRankingScoreDetails布尔值false添加详细的全局排名分数字段
rankingScoreThreshold数值null排除排名分数较低的结果
attributesToSearchOn字符串数组["*"]将搜索限制为指定的属性
hybrid对象null根据查询关键词和含义返回结果
vector数字数组null使用自定义查询向量进行搜索
retrieveVectors布尔值false返回文档向量数据
locales字符串数组null明确指定查询中使用的语言

除非另有说明,多重搜索查询的搜索参数功能与 /search 端点的搜索参数完全相同。

limitoffsethitsPerPagepage

这些选项与联邦搜索不兼容。

federationOptions

federationOptions 必须是一个对象。它接受以下参数:

  • weight: 作为此特定查询中搜索结果排名分数的乘数因子。如果小于 1.0,则此查询的命中项不太可能出现在最终结果列表中。如果大于 1.0,则此查询的命中项更可能出现在最终结果列表中。必须是正浮点数。默认为 1.0
  • remote 实验性功能:指示 Meilisearch 将执行查询的远程实例。必须是与 远程对象对应的字符串。默认为 null

响应

/multi-search 查询的响应可能因您发出的查询类型而异。

非联邦多重搜索请求

名称类型描述
results对象数组搜索查询的结果,按请求时的顺序排列

每个搜索结果对象由以下字段组成:

名称类型描述
indexUid字符串请求索引的 uid
hits对象数组查询结果
offset数值跳过的文档数量
limit数值要获取的文档数量
estimatedTotalHits数值估计的总匹配数量
totalHits数值详尽的总匹配数量
totalPages数值详尽的搜索结果总页数
hitsPerPage数值每页结果数量
page数值当前搜索结果页
facetDistribution对象给定分面的分布
facetStats对象每个分面的数字 minmax
processingTimeMs数值查询的处理时间
query字符串发起响应的查询

联邦多重搜索请求

联邦搜索请求返回一个单一对象和以下字段:

名称类型描述
hits对象数组查询结果
offset数值跳过的文档数量
limit数值要获取的文档数量
estimatedTotalHits数值估计的总匹配数量
processingTimeMs数值查询的处理时间
facetsByIndex对象搜索结果中存在的分面数据
facetDistribution对象给定分面的分布
facetStats对象每个分面的数字 minmax
remoteErrors对象指示哪些远程请求失败以及原因

hits 数组中的每个结果都包含一个额外的 _federation 字段,其中包含以下字段:

名称类型描述
indexUid字符串此文档的原始索引
queriesPosition数值请求的 queries 数组中查询的数组索引号
remote字符串此文档的原始远程实例
weightedRankingScore数值命中项的 _rankingScore 与原始查询权重的乘积。

示例

curl \
  -X POST 'MEILISEARCH_URL/multi-search' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "queries": [
      {
        "indexUid": "movies",
        "q": "pooh",
        "limit": 5
      },
      {
        "indexUid": "movies",
        "q": "nemo",
        "limit": 5
      },
      {
        "indexUid": "movie_ratings",
        "q": "us"
      }
    ]
  }'
响应: 200 Ok
{
  "results": [
    {
      "indexUid": "movies",
      "hits": [
        {
          "id": 13682,
          "title": "Pooh's Heffalump Movie",

        },

      ],
      "query": "pooh",
      "processingTimeMs": 26,
      "limit": 5,
      "offset": 0,
      "estimatedTotalHits": 22
    },
    {
      "indexUid": "movies",
      "hits": [
        {
          "id": 12,
          "title": "Finding Nemo",

        },

      ],
      "query": "nemo",
      "processingTimeMs": 5,
      "limit": 5,
      "offset": 0,
      "estimatedTotalHits": 11
    },
    {
      "indexUid": "movie_ratings",
      "hits": [
        {
          "id": "Us",
          "director": "Jordan Peele",

        }
      ],
      "query": "Us",
      "processingTimeMs": 0,
      "limit": 20,
      "offset": 0,
      "estimatedTotalHits": 1
    }
  ]
}
curl \
  -X POST 'MEILISEARCH_URL/multi-search' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "federation": {},
    "queries": [
      {
        "indexUid": "movies",
        "q": "batman"
      },
      {
        "indexUid": "comics",
        "q": "batman"
      }
    ]
  }'
响应: 200 Ok
{
  "hits": [
    {
      "id": 42,
      "title": "Batman returns",
      "overview": , 
      "_federation": {
        "indexUid": "movies",
        "queriesPosition": 0
      }
    },
    {
      "comicsId": "batman-killing-joke",
      "description": ,
      "title": "Batman: the killing joke",
      "_federation": {
        "indexUid": "comics",
        "queriesPosition": 1
      }
    },

  ],
  "processingTimeMs": 0,
  "limit": 20,
  "offset": 0,
  "estimatedTotalHits": 2,
  "semanticHitCount": 0
}
curl \
  -X POST 'MEILISEARCH_URL/multi-search' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "federation": {},
    "queries": [
      {
        "indexUid": "movies",
        "q": "batman",
        "federationOptions": {
          "remote": "ms-00"
        }
      },
      {
        "indexUid": "movies",
        "q": "batman",
        "federationOptions": {
          "remote": "ms-01"
        }
      }
    ]
  }'
响应: 200 Ok
{
  "hits": [
    {
      "id": 42,
      "title": "Batman returns",
      "overview": , 
      "_federation": {
        "indexUid": "movies",
        "queriesPosition": 0,
        "weightedRankingScore": 1.0,
        "remote": "ms-01"
    }
    },
    {
      "id": 87,
      "description": ,
      "title": "Batman: the killing joke",
      "_federation": {
        "indexUid": "movies",
        "queriesPosition": 1,
        "weightedRankingScore": 0.9848484848484849,
        "remote": "ms-00"
      }
    },

  ],
  "processingTimeMs": 35,
  "limit": 5,
  "offset": 0,
  "estimatedTotalHits": 111,
  "remoteErrors": {
    "ms-02": {
      "message": "error sending request",
      "code": "proxy_could_not_send_request",
      "type": "system",
      "link": "https://docs.meilisearch.com/errors#proxy_could_not_make_request"
    }
  }
}