Match vs Term — Analysed or Exact
A developer writes {"term": {"title": "Quiet Garden"}} and gets zero hits, even though "The Quiet Garden" is right there. Swap term for match and it appears. Understanding why is the single most useful thing to know about Elasticsearch queries.
The rule
Match analyses your words like the field did; term looks up your value untouched.
Recall that the title text field was indexed as lower-cased words: the, quiet, garden.
match runs your query text through the same analyzer the field used, then looks up each resulting word:
GET /books/_search
{ "query": { "match": { "title": "Quiet Garden" } } }"Quiet Garden" becomes quiet, garden. Both exist, so the book matches. By default the words are joined with OR — a book with only "garden" in its title also matches, just with a lower score. To require every word:
{ "query": { "match": { "title": { "query": "quiet garden", "operator": "and" } } } }term skips analysis. It looks for the exact value Quiet Garden — capital letters, space and all — as a single term. The text field holds no such term, so nothing matches.
term is built for keyword, number, date and boolean fields, where values are stored whole:
GET /books/_search
{ "query": { "term": { "genre": "fiction" } } }genre is a keyword field holding exactly fiction, so this is a precise, fast lookup. To match any of several exact values, use terms: {"terms": {"genre": ["fiction", "hobby"]}}.
The shortcut
Look at the field type, not the query: text field → match; keyword, number, date or boolean → term. If you must match a text field exactly, use its keyword sub-field with term.
A shopper types "garden busy"
titleis text →match. It finds Gardening for Busy People (through "busy") and The Quiet Garden (through "garden").
Notice that "gardening" did not match "garden": the standard analyzer does not reduce words to their stems, so they are different terms. An English analyzer with stemming would link them; you will meet analyzers later.
Drills
Answer fast — trust the rule.
Why does {"term": {"title": "Quiet Garden"}} find nothing?
Which query should you use on the keyword field genre?
{"match": {"title": "quiet train"}} runs against our books. Which match?
How do you make a match query require every word?
Remember
- Match analyses your words like the field did; term looks up your value untouched.
- Text → match; keyword, number, date, boolean → term.
- match uses OR by default; set
operatortoandto require all words.
