Skip to content
ExponaBLOG
ELASTICSEARCH & SEARCH ENGINEERING · DAY 015 / 100

multi_match queries in Elasticsearch & Search Engineering

Search across several fields.

Expona Admin6 min read

Multi_match queries in Elasticsearch & Search Engineering

When you're building a search box for your e-commerce platform or SaaS product, users expect to find results whether they search by product name, description, tags, or category. Single-field queries fall short—you need a way to search across multiple fields simultaneously. Multi_match queries in Elasticsearch solve this problem elegantly, letting your team build powerful search experiences that match user intent across your entire document structure.

Search title, description and tags at once

The most common use case for multi_match queries is the classic search box: a single input field that needs to return relevant results from several document fields. Imagine you're building a product search for an e-commerce platform with products containing a title, detailed description, and multiple tags.

Here's a basic multi_match query that searches across all three fields:

json
{
  "query": {
    "multi_match": {
      "query": "wireless headphones",
      "fields": ["title", "description", "tags"]
    }
  }
}

This query will find documents where "wireless headphones" appears in any of the three fields. The results include documents where both terms appear together, or where either term matches individually across any field.

In a real-world scenario, you're running this query hundreds of times per second as users type or search. The multi_match approach is more efficient than running three separate match queries and aggregating results—Elasticsearch optimizes the execution internally. We typically see this pattern in production when the search term might legitimately belong in multiple fields, and there's no clear hierarchy about which field should match first.

Boost fields with ^ syntax

Not all fields are equally important. A match in the product title should probably rank higher than a match in the description or tags. This is where the boost syntax comes in—you can use the ^ character to weight certain fields more heavily.

Here's how you'd boost the title field:

json
{
  "query": {
    "multi_match": {
      "query": "wireless headphones",
      "fields": ["title^3", "description^2", "tags"]
    }
  }
}

The boost numbers are multipliers applied to the relevance score. A boost of 3 on title means matches there are scored 3 times higher than baseline. Description gets a boost of 2, and tags get the default boost of 1. This ensures that when "wireless headphones" appears in the title, that document ranks much higher than one where it only appears in the description.

Choosing the right boost values requires testing with real search queries and measuring click-through rates or conversion metrics. We often start with simple ratios (3:2:1 or 2:1:1) and adjust based on user behavior data. Too aggressive boosting makes field-specific matches irrelevant; too subtle, and you're not leveraging your document structure.

Decimal boosts work too—you might use title^2.5 and description^1.2 for finer control, though this is usually unnecessary complexity until you've validated that basic integer boosts aren't sufficient.

Best_fields vs most_fields vs cross_fields

The type parameter in multi_match queries changes how Elasticsearch combines scores across fields. Understanding these three strategies is essential for tuning relevance in complex search scenarios.

Best_fields (default)

Best_fields returns the highest score from any single field. Use this when you expect the search term to appear primarily in one field at a time.

json
{
  "query": {
    "multi_match": {
      "query": "wireless headphones",
      "fields": ["title", "description", "tags"],
      "type": "best_fields"
    }
  }
}

If a document has "wireless headphones" in the title, it scores well. If another document has both words scattered across the description, best_fields only uses the best match score. This works well for product searches where a title match is typically more relevant than a description match.

Most_fields

Most_fields sums scores from all matching fields. Use this when you want documents that match across multiple fields to rank higher than documents matching in just one field.

json
{
  "query": {
    "multi_match": {
      "query": "wireless headphones",
      "fields": ["title", "description", "tags"],
      "type": "most_fields"
    }
  }
}

Most_fields is particularly useful when you have the same logical content in multiple representations—for example, a product name in English and translated names in other languages. A document matching in both languages would score higher, which is often the desired behavior.

Cross_fields

Cross_fields treats the query terms as if they could appear in any field, and requires that all query terms be present across the field set. This is the strategy for "person search" scenarios where a name might be split across first_name and last_name fields.

json
{
  "query": {
    "multi_match": {
      "query": "john smith",
      "fields": ["first_name", "last_name"],
      "type": "cross_fields"
    }
  }
}

This query finds documents where "john" appears in first_name or last_name, AND "smith" appears in first_name or last_name. Without cross_fields, you might miss matches where the first term is in one field and the second in another. In production, we've found this essential for people search, company search, and address matching.

Each strategy has performance implications. Best_fields is fastest; cross_fields is slower because it needs to coordinate matching across fields. Most_fields falls in between. Profile your queries with real data before optimizing for raw speed—relevance usually matters more than a few milliseconds of latency in search scenarios.

Use for search boxes

The typical search box implementation sends a user's input directly into a multi_match query. This is where the flexibility of multi_match shines. Here's a simplified product search implementation:

json
{
  "query": {
    "multi_match": {
      "query": "noise cancelling",
      "fields": ["title^3", "category^2", "description", "brand"],
      "type": "best_fields",
      "operator": "or"
    }
  }
}

The operator parameter controls how multiple search terms are combined. With "operator": "or" (the default), documents matching any term are returned. With "operator": "and", documents must match all terms. For broad search boxes, "or" usually provides better recall; for narrower searches, "and" reduces noise.

In a real SaaS application, you might build progressive filtering: first return everything matching "or" logic, then let users refine with additional filters or sort by relevance. For travel platforms, we've seen success with "or" logic on the main query combined with must-have filters on critical fields like dates or price range.

Add a fuzziness parameter for typo tolerance:

json
{
  "query": {
    "multi_match": {
      "query": "nois canelling",
      "fields": ["title^3", "description"],
      "type": "best_fields",
      "fuzziness": "AUTO"
    }
  }
}

Fuzziness AUTO enables Levenshtein distance matching with sensible defaults based on term length—short terms allow fewer edits than long terms. This catches common typos without the performance cost of aggressive fuzzy matching on every query.

Common mistakes

  • Boosting too aggressively: Setting boost values like 10 or 100 without testing often backfires. Boosts are relative to your other fields and query structure. Start with small integers and measure impact on real user behavior metrics.
  • Wrong type for your use case: Defaulting to best_fields for every scenario means you miss matches where the intent spans multiple fields. Think through whether you want the single best match or combinations across fields.
  • Not accounting for analyzers: Multi_match queries use the same analyzer as the fields being searched. If your fields have different analyzers (one lowercases, one stems, one keeps stop words), behavior becomes unpredictable. Define explicit analyzers and test field combinations.
  • Ignoring score impact of optional fields: Adding irrelevant fields to the multi_match list dilutes scores and reduces relevance. Be intentional about which fields are searchable.
  • Neglecting query performance at scale: Multi_match queries searching many fields across large indices can slow down significantly. Monitor query latency and consider denormalizing search data into dedicated fields if performance degrades.

Key takeaways

  • Multi_match queries let you search across multiple fields in a single request, essential for building modern search boxes that handle user intent naturally.
  • Use the ^ boost syntax to weight important fields higher—title matches should typically rank above description matches.
  • Choose your type strategy based on your data structure: best_fields for single-field dominance, most_fields for multi-field validation, cross_fields for split data like names.
  • Implement search boxes with operator control (or/and) and consider fuzziness for typo tolerance to improve user experience.
  • Test boost values and type settings with production-like search volumes and real user queries before finalizing your configuration.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles