The Core Distinction
The match query and the term query are the two leaf queries beginners confuse most often, and the distinction comes down to analysis. A match query runs the input text through the same analyzer configured on the target field at index time — lowercasing, tokenizing, removing stop words, stemming — before searching, making it the right tool for text fields where 'Running Shoes' should match a search for 'running shoe'. A term query does no analysis at all: it looks for the exact value you provide against the exact terms stored in the inverted index, which is correct for keyword, numeric, boolean, and date fields but almost always wrong against analyzed text fields, since the stored tokens have already been lowercased and stemmed.
Cricket analogy: A match query is like a bowling coach who accepts a slightly different grip or run-up as long as the delivery type matches — an off-cutter is an off-cutter — while a term query is like a strict scorer who only logs it if the exact recorded delivery code matches character for character.
// text field: analyzed, tokenized search
GET /articles/_search
{ "query": { "match": { "body": "elasticsearch performance tuning" } } }
// keyword field: exact, unanalyzed lookup
GET /articles/_search
{ "query": { "term": { "status.keyword": "published" } } }match_phrase and multi_match
Plain match treats the query string as a bag of tokens and by default matches documents containing any of them (an implicit OR), scoring higher for documents containing more. When word order and adjacency matter — like requiring 'new york times' to appear as a consecutive phrase rather than three scattered words — match_phrase is the right tool, and it accepts a slop parameter to allow a bounded number of intervening or transposed terms. When the same query text should be checked across several fields at once, such as searching both title and description for a product, multi_match wraps that logic in one clause and supports strategies like best_fields, most_fields, and cross_fields to control how scores from multiple fields are combined.
Cricket analogy: Plain match is like a highlights reel showing any clip containing 'six' or 'wicket' in any order, while match_phrase is like requiring the exact commentary line 'six, out of the park' to appear verbatim and in sequence.
multi_match with type: best_fields is the default and works well when a single field is expected to contain the full match (e.g., title). Use most_fields when the same analyzed text is indexed differently across fields (e.g., a stemmed and an unstemmed copy) to combine signal from both.
Operator, Fuzziness, and Analyzer Mismatches
By default, match uses operator: OR, so a query for 'red leather jacket' matches any document containing at least one of those terms, ranked by how many it contains; setting operator: AND requires every term to be present, which is stricter and often more precise for short, deliberate queries. The fuzziness parameter on match enables typo tolerance using Levenshtein edit distance, so 'jaket' can still match 'jacket' within one or two edits — useful for user-typed search boxes but risky for precise lookups. A frequent source of confusing zero-result bugs is an analyzer mismatch: if a field uses a custom analyzer with synonyms or stemming at index time but the query analyzer differs, or if you accidentally query the .keyword sub-field with match, results silently come back empty or wrong.
Cricket analogy: operator: AND on a match query is like a strict fielding drill requiring a player to complete catching, throwing, and stumping all correctly, while OR is like a drill graded on completing any one of the three.
A query returning zero results even though the data looks right is almost always an analyzer mismatch — check whether you're querying a .keyword sub-field with match, or whether the field's index-time analyzer (stemmer, synonym filter, language analyzer) differs from what you expect at query time using the _analyze API.
- match analyzes query text using the field's analyzer; term performs an exact, unanalyzed lookup.
- Use match/match_phrase/multi_match on text fields; use term/terms on keyword, numeric, boolean, and date fields.
- match_phrase requires terms to appear in the given order and adjacency, with slop allowing bounded flexibility.
- multi_match searches multiple fields at once using strategies like best_fields, most_fields, and cross_fields.
- operator: AND requires every query term to be present; the default OR requires at least one.
- fuzziness enables Levenshtein-based typo tolerance but should be used cautiously for precise queries.
- Zero-result bugs are frequently caused by analyzer mismatches between index time and query time.
Practice what you learned
1. Why does a term query typically fail when run against an analyzed text field?
2. What does match_phrase require that plain match does not?
3. What does setting operator: AND on a match query change?
4. A query returns zero results even though matching documents clearly exist. What is the most likely cause?
Was this page helpful?
You May Also Like
The Query DSL
A guide to Elasticsearch's JSON-based Query DSL, the request language used to build every search, filter, and aggregation.
Bool Queries
How the bool compound query combines must, should, must_not, and filter clauses to express complex search logic in Elasticsearch.
Full-Text Search Relevance and Scoring: TF-IDF & BM25
How Elasticsearch computes the _score for full-text matches, from the classic TF-IDF intuition to the BM25 algorithm used by default today.