NEW

Pulse 2025 Product Roundup: From Monitoring to AI-Native Control Plane

Elasticsearch Multi-Match Query: Syntax, Types, and Examples - Syntax, Example, and Tips

The Elasticsearch multi_match query runs a single piece of input text against multiple fields and combines the results according to a chosen type. It is the standard query for searches that span title, body, tags, and other text fields with different weights. The type parameter (default best_fields) controls how per-field scores combine; field boosts (field^2) and tie_breaker tune relevance further.

Syntax

GET /index/_search
{
  "query": {
    "multi_match": {
      "query": "search text",
      "fields": ["title^3", "summary^2", "body"],
      "type": "best_fields",
      "tie_breaker": 0.3,
      "operator": "and"
    }
  }
}

Parameters

Parameter Description Required Default
query Text to search for. Yes -
fields Array of fields to search. Supports field^boost and wildcards (name.*). No All fields enabled for the query (*).
type best_fields, most_fields, cross_fields, phrase, phrase_prefix, bool_prefix. No best_fields
tie_breaker Weight applied to non-best-matching fields' scores. Only used by best_fields and most_fields. No 0.0 (only best field counts)
operator or or and, applied per field. No or
minimum_should_match Minimum optional clauses that must match. No -
analyzer Override analyzer for the query string. No Search analyzer of each field
fuzziness Maximum edit distance (AUTO, 0, 1, 2). Ignored for phrase/phrase_prefix/cross_fields. No -
prefix_length Common prefix kept fixed in fuzzy matching. No 0
max_expansions Max term expansions for fuzzy and prefix matching. No 50
slop Tokens allowed between phrase terms (phrase/phrase_prefix only). No 0
zero_terms_query none or all when the analyzer removes all tokens. No none
auto_generate_synonyms_phrase_query Build phrase queries for multi-term synonyms. No true
lenient Ignore type-conversion errors per field. No false
boost Score multiplier for the whole query. No 1.0

Examples

best_fields (default) - one field dominates the score:

GET /articles/_search
{
  "query": {
    "multi_match": {
      "query":  "quick brown fox",
      "fields": ["title^3", "summary^2", "content"],
      "tie_breaker": 0.3
    }
  }
}

cross_fields - treats sibling fields as one logical field. Useful for name-like data spread across first_name, last_name, email:

GET /users/_search
{
  "query": {
    "multi_match": {
      "query":    "will smith",
      "type":     "cross_fields",
      "fields":   ["first_name", "last_name", "email"],
      "operator": "and"
    }
  }
}

phrase_prefix - autocomplete on the last term of a phrase:

GET /products/_search
{
  "query": {
    "multi_match": {
      "query":  "wireless head",
      "type":   "phrase_prefix",
      "fields": ["title", "description"]
    }
  }
}

Wildcard field selector with fuzziness:

GET /products/_search
{
  "query": {
    "multi_match": {
      "query":     "headphons",
      "fields":    ["name.*"],
      "fuzziness": "AUTO"
    }
  }
}

Performance and Use Notes

best_fields and most_fields run as one query per field and combine the per-field scores. cross_fields requires that the fields share the same search_analyzer; mismatched analyzers fall back to per-field scoring with a warning. phrase and phrase_prefix are far more expensive because they retain positional information and re-check term order on each candidate.

Wildcards in fields are resolved at query time. Patterns like * or name.* are cheap on schemas with a small mapped field count but expensive on indices with hundreds of fields - each resolved field becomes its own subquery. Combining a wildcard field selector with fuzziness multiplies cost: each field generates up to max_expansions candidate terms (default 50).

Multi-match queries are the workhorse of search APIs and a frequent slow-query offender when field lists or fuzziness are not bounded. Pulse monitors Elasticsearch latency, flags multi_match queries with unbounded field wildcards or excessive expansion, and suggests concrete type/fields rewrites.

Common Mistakes

  1. Using cross_fields with fields that have different analyzers - the query silently rewrites to per-field scoring and behaves like most_fields.
  2. Adding fuzziness: AUTO on cross_fields, phrase, or phrase_prefix - fuzziness is ignored for those types.
  3. Searching fields: ["*"] on a wide mapping. Restrict to known text fields to keep per-shard work bounded.
  4. Forgetting that phrase_prefix only does prefix matching on the last term of the phrase; earlier terms must match exactly.
  5. Relying on the default tie_breaker: 0, which makes best_fields look like a single-field query - set 0.2-0.4 if you want non-best fields to contribute.

Frequently Asked Questions

Q: What is the difference between multi_match and query_string?
A: multi_match takes plain text and runs it against multiple fields with predictable scoring rules. `query_string` parses Lucene's mini-language (operators, field selectors, regex). Use multi_match for typical user input; use query_string only when callers need full Lucene syntax.

Q: When should I use best_fields vs most_fields vs cross_fields?
A: best_fields wins when the same phrase tends to appear in one field at a time (title or body, not both). most_fields is good when multiple analyzers of the same field contribute evidence (e.g. title + title.stemmed). cross_fields is for name-like data fragmented across siblings with the same analyzer.

Q: What does tie_breaker do in multi_match?
A: With best_fields and most_fields, the final score is best_field_score + tie_breaker * sum(other_field_scores). A value of 0 ignores all but the best field; 1.0 makes the query behave like most_fields. Typical values fall between 0.2 and 0.4.

Q: Can I use wildcards in the fields parameter?
A: Yes. fields: ["name.*"] expands to every sub-field of name at query time. Keep the pattern narrow on indices with hundreds of fields; each matched field becomes its own subquery.

Q: Why is fuzziness ignored in my multi_match query?
A: fuzziness is silently ignored for type: cross_fields, phrase, and phrase_prefix. Switch to best_fields or most_fields (or add an explicit match clause with fuzziness) if you need edit-distance tolerance.

Q: How do I boost one field over others?
A: Append ^N to the field name: "title^3". The boost multiplies that field's contribution to the score. Combine with tie_breaker so non-boosted fields still contribute.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.