/multi-search 路由允许您通过将多个搜索查询打包到单个 HTTP 请求中,在一个或多个索引上执行多重搜索。多重搜索也被称为联邦搜索(federated search)。

执行多重搜索

将多个搜索查询打包到单个 API 请求中。使用此端点可以同时搜索多个索引。

POST
/multi-search

请求体

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

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

federation

使用 federation 可以获取一个包含所有指定查询结果的统一列表,结果按照评分降序排列。这被称为联邦搜索(federated search)。

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 且不为空时,多搜索响应中包含的分面信息会在所有查询索引中合并。响应中将不再包含 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. 如果两条结果在同一排序方向上有 sort 或 geosort 分数,则 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

这些选项不兼容联邦搜索(federated searches)。

federationOptions

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

  • weight: 作为该特定查询中搜索结果排名分数的乘数因子。如果小于 1.0,该查询的结果在最终结果列表中出现的可能性会降低;如果大于 1.0,则出现的可能性会提高。必须是一个正浮点数,默认为 1.0
  • remote experimental: 指定 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": "小熊维尼之大风吹",

        },

      ],
      "query": "pooh",
      "processingTimeMs": 26,
      "limit": 5,
      "offset": 0,
      "estimatedTotalHits": 22
    },
    {
      "indexUid": "movies",
      "hits": [
        {
          "id": 12,
          "title": "海底总动员",

        },

      ],
      "query": "nemo",
      "processingTimeMs": 5,
      "limit": 5,
      "offset": 0,
      "estimatedTotalHits": 11
    },
    {
      "indexUid": "movie_ratings",
      "hits": [
        {
          "id": "Us",
          "director": "乔丹·皮尔",

        }
      ],
      "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": "蝙蝠侠归来",
      "overview": , 
      "_federation": {
        "indexUid": "movies",
        "queriesPosition": 0
      }
    },
    {
      "comicsId": "batman-killing-joke",
      "description": ,
      "title": "蝙蝠侠:致命玩笑",
      "_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": "发送请求时出错",
      "code": "proxy_could_not_send_request",
      "type": "system",
      "link": "https://docs.meilisearch.com/errors#proxy_could_not_make_request"
    }
  }
}