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

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:

  • maxValuesPerFacet: must be an integer. When specified, indicates the maximum number of returned values for a single facet. Defaults to the value assigned to the maxValuesPerFacet index setting

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": [],

  "facetDistribution": {
    "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.

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
distinctStringnullRestrict search to documents with unique values of specified attribute
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
showRankingScoreDetailsBooleanfalseAdds a detailed global ranking score field
rankingScoreThresholdNumbernullExcludes results with low ranking scores
attributesToSearchOnArray of strings["*"]Restrict search to the specified attributes
hybridObjectnullReturn results based on query keywords and meaning
vectorArray of numbersnullSearch using a custom query vector
retrieveVectorsBooleanfalseReturn document vector data
localesArray of stringsnullExplicitly specify languages used in a query

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:

  • weight: serves as a multiplicative factor to ranking scores of search results in this specific query. If < 1.0, the hits from this query are less likely to appear in the final results list. If > 1.0, the hits from this query are more likely to appear in the final results list. Must be a positive floating-point number. Defaults to 1.0
  • remote experimental: indicates the remote instance where Meilisearch will perform the query. Must be a string corresponding to a remote object. Defaults to null

Response

The response to /multi-search queries may take different shapes depending on the type of query you’re making.

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
hitsArray of objectsResults of the query
offsetNumberNumber of documents skipped
limitNumberNumber of documents to take
estimatedTotalHitsNumberEstimated total number of matches
processingTimeMsNumberProcessing time of the query
facetsByIndexObjectData for facets present in the search results
facetDistributionObjectDistribution of the given facets
facetStatsObjectThe numeric min and max values per facet
remoteErrorsObjectIndicates which remote requests failed and why

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
remoteStringRemote instance of origin for this document
weightedRankingScoreNumberThe product of the _rankingScore of the hit and the weight of the query of origin.

Example

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"
      }
    ]
  }'
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 'MEILISEARCH_URL/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
}
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"
        }
      }
    ]
  }'
Response: 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"
    }
  }
}

Was this page helpful?