Multi-match query

Multi-match query #

Returns documents that match a provided text across several fields — like the match query, with per-field boosts and multi-field scoring strategies.

Inside a nested query: supported — fields under the nested path are matched per array element.

How it works #

multi_match is expanded before execution (Query::simplify) into a tree the segment executors already know:

  1. Each entry in fields — after splitting off a ^boost suffix — becomes one match query over that field, carrying the query-level boost multiplied by the field boost ("title^3" → per-field boost 3).
  2. For type: "phrase" and type: "phrase_prefix" each field instead becomes a phrase query with slop: 0. The prefix part is not implemented: phrase_prefix currently behaves as an exact phrase and does not expand its last term as a prefix.
  3. Two or more fields are wrapped in a bool whose should clauses are the per-field queries, with at least one field required; a single field collapses to that field’s query — a plain match.

Scores: should clauses add their per-document scores (the bool default). The type additionally picks the combination used when one field name resolves to several indexed sub-fields — best_fields keeps the maximum, most_fields and cross_fields sum. cross_fields does not blend term statistics across fields; each field scores independently and the results merge.

operator and analyzer are forwarded to every per-field match unchanged. tie_breaker and the string form of minimum_should_match are accepted on the wire but not yet applied by the expansion — it always requires at least one field and combines by sum.

Examples #

POST /my-collection/_search
{
  "query": {
    "multi_match": {
      "query": "search engine",
      "fields": ["title^3", "description"]
    }
  }
}

Use cases #

  • One search box, several fields. title^3 plus body is the classic relevance shape: matches in the title outrank the same words in the body, without excluding body-only matches.
  • Log triage across columns. "search error" over ["message", "level"] matches lines whose message mentions search or whose level is error — 25 of the 150 logs documents (the same 25: every /search line is an error-level line).
  • Analyzed plus keyword variants. Listing both a text field and its keyword sub-field catches prose matches and exact-label matches with one query.
  • Phrases everywhere. type: "phrase" with several fields runs the same exact-phrase constraint over each field independently.

Parameters for multi_match #

  • query
    (Required, string) The query text to search for.
  • fields
    (Required, array of strings) Fields to search, with optional per-field boosts via the field^boost syntax (e.g. "title^3").
  • type
    (Optional, string) Match type / multi-field scoring strategy: best_fields (default), most_fields, cross_fields, phrase or phrase_prefix. See How it works for what each strategy actually computes here.
  • operator
    (Optional, string, default: or) Boolean operator joining terms within each field: or or and. Forwarded to every per-field match.
  • minimum_should_match
    (Optional, string) Accepted but not yet applied: the expansion always requires at least one field to match.
  • analyzer
    (Optional, string) Analyzer override forwarded to the per-field match queries.
  • tie_breaker
    (Optional, float, default: 0) Accepted but not yet applied by the expansion — per-field scores currently combine by sum.
  • boost
    (Optional, float, default: 1.0) Boost applied to the overall query; multiplied with each field’s ^boost (carried by the per-field match queries — the phrase types carry no boost).
  • match — the per-field query that multi_match expands into.
  • phrase — type: "phrase" runs one phrase query per field.
  • bool — the should-clause skeleton the expansion targets.
  • Analyzers — per-field analysis of the query text.
  • API conventions.
Calendar October 6, 2026
Edit Edit this page