Multi-search

    The /multi-search route allows you to perform multiple search queries on one or more indexes by bundling them into a single HTTP request. Multi-search is also known as federated search.

    Bundle multiple search queries in a single API request. Use this endpoint to search through multiple indexes at once.

    POST/multi-search

    Body

    NameTypeDescription
    federationObjectIf present and not null, returns a single list merging all search results across all specified queries
    queriesArray of objectsContains the list of search queries to perform. The indexUid search parameter is required, all other parameters are optional
    WARNING

    If Meilisearch encounters an error when handling any of the queries in a multi-search request, it immediately stops processing the request and returns an error message. The returned message will only address the first error encountered.

    federation

    Use federation to receive a single list with all search results from all specified queries, in descending ranking score order. This is called federated search.

    federation may optionally contain the following parameters:

    ParameterTypeDefault valueDescription
    offsetInteger0Number of documents to skip
    limitInteger20Maximum number of documents returned
    facetsByIndexObject of arraysnullDisplay facet information for the specified indexes
    mergeFacetsObjectnullDisplay facet information for the specified indexes

    If federation is missing or null, Meilisearch returns a list of multiple search result objects, with each item from the list corresponding to a search query in the request.

    facetsByIndex

    facetsByIndex must be an object. Its keys must correspond to indexes in your Meilisearch project. Each key must be associated with an array of attributes in the filterable attributes list of that index:

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

    When you specify facetsByIndex, multi-search responses include an extra facetsByIndex field. The response's facetsByIndex is an object with one field for each queried index:

    {
      "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 must be an object and may contain the following fields:

    When both facetsByIndex and mergeFacets are present and not null, facet information included in multi-search responses is merged across all queried indexes. Instead of facetsByIndex, the response includes two extra fields: facetDistribution and facetStats:

    {
      "hits": [],"facetFederation": {
        "ATTRIBUTE": {
          "VALUE": <Integer>,
          "VALUE": <Integer>
        }
      },
      "facetStats": {
        "ATTRIBUTE": {
          "min": <Integer>,
          "max": <Integer>
        }
      }
    }
    
    Merge algorithm for federated searches

    Federated search's merged results are returned in decreasing ranking score. To obtain the final list of results, Meilisearch compares with the following procedure:

    1. Detailed ranking scores are normalized in the following way for both hits:
      1. Consecutive relevancy scores (related to the rules words, typo, attribute, exactness or vector) are grouped in a single score for each hit
      2. sort and geosort score details remain unchanged
    2. Normalized detailed ranking scores are compared lexicographically for both hits:
      1. If both hits have a relevancy score, then the bigger score wins. If it is a tie, move to next step
      2. If one result has a relevancy score or a (geo)sort score, Meilisearch picks it
      3. If both results have a sort or geosort score in the same sorting direction, then Meilisearch compares the values according to the common sort direction. The result with the value that must come first according to the common sort direction wins. If it is a tie, go to the next step
      4. Compare the global ranking scores of both hits to determine which comes first, ignoring any sorting or geosorting
      5. In the case of a perfect tie, documents from the query with the lowest rank in the queries array are preferred.
    Distinct documents and federated search

    Meilisearch considers two documents the same if:

    1. They come from the same index
    2. And their primary key is the same

    There is no way to specify that two documents should be treated as the same across multiple indexes.

    queries

    queries must be an array of objects. Each object may contain the following search parameters:

    Search parameterTypeDefault valueDescription
    federationOptionsObjectnullConfigure federation settings for a specific query
    indexUidStringN/Auid of the requested index
    qString""Query string
    offsetInteger0Number of documents to skip
    limitInteger20Maximum number of documents returned
    hitsPerPageInteger1Maximum number of documents returned for a page
    pageInteger1Request a specific page of results
    filterStringnullFilter queries by an attribute's value
    facetsArray of stringsnullDisplay the count of matches per facet
    attributesToRetrieveArray of strings["*"]Attributes to display in the returned documents
    attributesToCropArray of stringsnullAttributes whose values have to be cropped
    cropLengthInteger10Maximum length of cropped value in words
    cropMarkerString"…"String marking crop boundaries
    attributesToHighlightArray of stringsnullHighlight matching terms contained in an attribute
    highlightPreTagString"<em>"String inserted at the start of a highlighted term
    highlightPostTagString"</em>"String inserted at the end of a highlighted term
    showMatchesPositionBooleanfalseReturn matching terms location
    sortArray of stringsnullSort search results by an attribute's value
    matchingStrategyStringlastStrategy used to match query terms within documents
    showRankingScoreBooleanfalseDisplay the global ranking score of a document
    attributesToSearchOnArray of strings["*"]Restrict search to the specified attributes

    Unless otherwise noted, search parameters for multi-search queries function exactly like search parameters for the /search endpoint.

    limit, offset, hitsPerPage and page

    These options are not compatible with federated searches.

    federationOptions

    federationOptions must be an object. It accepts the following parameters:

    Response

    The response to /multi-search queries may take two shapes: federated and non-federated.

    Non-federated multi-search requests

    NameTypeDescription
    resultsArray of objectsResults of the search queries in the same order they were requested in

    Each search result object is composed of the following fields:

    NameTypeDescription
    indexUidStringuid of the requested index
    hitsArray of objectsResults of the query
    offsetNumberNumber of documents skipped
    limitNumberNumber of documents to take
    estimatedTotalHitsNumberEstimated total number of matches
    totalHitsNumberExhaustive total number of matches
    totalPagesNumberExhaustive total number of search result pages
    hitsPerPageNumberNumber of results on each page
    pageNumberCurrent search results page
    facetDistributionObjectDistribution of the given facets
    facetStatsObjectThe numeric min and max values per facet
    processingTimeMsNumberProcessing time of the query
    queryStringQuery originating the response

    Federated multi-search requests

    Federated search requests return a single object and the following fields:

    NameTypeDescription
    indexUidStringuid of the requested index
    hitsArray of objectsResults of the query
    offsetNumberNumber of documents skipped
    limitNumberNumber of documents to take
    estimatedTotalHitsNumberEstimated total number of matches
    totalHitsNumberExhaustive total number of matches
    totalPagesNumberExhaustive total number of search result pages
    hitsPerPageNumberNumber of results on each page
    pageNumberCurrent search results page
    facetDistributionObjectDistribution of the given facets
    facetStatsObjectThe numeric min and max values per facet
    processingTimeMsNumberProcessing time of the query
    queryStringQuery originating the response

    Each result in the hits array contains an additional _federation field with the following fields:

    NameTypeDescription
    indexUidStringIndex of origin for this document
    queriesPositionNumberArray index number of the query in the request's queries array

    Example

    curl \
      -X POST 'http://localhost:7700/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"
          }
        ]
      }'

    Response: 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 'http://localhost:7700/multi-search' \
      -H 'Content-Type: application/json' \
      --data-binary '{
        "federation": {},
        "queries": [
          {
            "indexUid": "movies",
            "q": "batman"
          },
          {
            "indexUid": "comics",
            "q": "batman"
          }
        ]
      }'

    Response: 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
    }