多重搜索

    /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 必须是一个对象,并且可以包含以下字段

    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字符串N/A请求索引的 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 必须是一个对象。它接受以下参数

    响应

    /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"
        }
      }
    }