What Is a Term Query in Elasticsearch?
The exact-match building block behind every filter, facet, and precise lookup in Elasticsearch — and the query type that trips up more beginners than any other.
Ask most beginners why their “term” query for “New York” returns nothing, and they’ll swear it should have matched. It’s one of the most common early stumbling blocks in Elasticsearch — and understanding exactly why reveals one of the most important ideas in the entire system: the difference between text that has been broken apart for searching and a value that hasn’t been touched at all. The term query sits right at the center of that distinction. This article explains exactly what it is, how it behaves internally, and when to actually reach for it.
1Core Concepts
A term query finds documents that contain an exact value in a specified field. Not “similar to,” not “contains the word somewhere within it” — exact, byte-for-byte match. It’s the simplest possible query Elasticsearch offers: you give it a field name and a value, and it returns every document where that field holds precisely that value.
Think of a vending machine’s product code lookup. You type in “B4,” and it returns exactly the item behind slot B4 — not “B” items in general, not anything similar-sounding, just the one exact match. A term query works the same way: it’s a precise lookup, not a fuzzy search.
What it is: a query clause that matches documents where a field’s stored value is exactly equal to the value you provide, with no text processing applied to your input.
Why it exists: many real-world lookups genuinely need exact matching — a status code, a category ID, a country code — where “close enough” isn’t good enough and full-text relevance scoring would actively get in the way.
Where it’s used: filters in e-commerce facets, exact status/category lookups, matching structured identifiers, and as a building block inside more complex boolean queries.
A term query does not analyze your input text at all — no lowercasing, no splitting into words, nothing. Whatever value you supply is compared exactly against whatever is stored in the field’s index, which is why term queries are almost always paired with “keyword” fields rather than “text” fields.
The Classic Beginner Trap
Here’s exactly why “New York” so often fails to match. If “city” is mapped as a “text” field, Elasticsearch’s analyzer breaks “New York” into two separate tokens at index time: “new” and “york” (both lowercased). A term query searching for the exact string “New York” is looking for that precise, unbroken, capitalized phrase in the index — but that phrase was never stored as a single token; only “new” and “york” were. The term query for “New York” fails, while a term query for “new” would succeed, since that’s literally what got indexed.
2Architecture & Components
Elasticsearch’s query language broadly splits into two families: full-text queries (like “match,” which analyze your input the same way the field was analyzed) and term-level queries (like “term,” “terms,” and “range,” which operate on exact, unanalyzed values). The term query is the flagship member of the term-level family.
| Query | Behavior | Typical Field Type |
|---|---|---|
| term | Exact match on a single value, no analysis of input | keyword, numeric, boolean, date |
| terms | Exact match against any value in a supplied list | keyword, numeric |
| match | Analyzes input the same way as the field, matches individual words | text |
| range | Exact match within a numeric or date range | numeric, date |
| prefix | Exact match on values starting with a given string | keyword |
Field
The specific field being matched against — the term query’s behavior depends entirely on how that field was mapped and indexed.
Value
The exact value to look for — compared as-is, with no lowercasing, stemming, or tokenizing applied by the query itself.
Boost
An optional relevance multiplier, useful when the term query is combined with others inside a boolean query and you want to weight it more or less heavily.
Case Insensitivity
An optional setting that allows the term query to ignore letter case specifically, without requiring full text analysis of the input.
graph TD
A["term query: field='status', value='SHIPPED'"] --> B{Field mapped as
keyword?}
B -- Yes --> C[Compare 'SHIPPED' exactly
against stored values]
B -- No, mapped as text --> D[Compare against individual
lowercased tokens - likely mismatch]
C --> E[Matching documents returned]
D --> F[Few or no matches - classic beginner trap]
3Internal Working
No Analysis Step
Unlike a “match” query, a term query skips the analyzer entirely for the value you provided — it is passed through exactly as-is into the search.
Inverted Index Lookup
Elasticsearch looks up your exact value directly in the field’s inverted index dictionary — essentially checking, “does this precise value exist as a stored term at all?”
Document Set Retrieval
If the exact value exists in the dictionary, Elasticsearch retrieves the list of every document that contains it — this list was built once, at index time, making the lookup extremely fast.
Filter Context vs. Query Context
When used inside a “filter” clause (rather than a scored “query” clause), Elasticsearch skips relevance scoring entirely, and the result can even be cached, making repeated identical filters near-instant on subsequent searches.
Running a term query is like checking a guest list at the door with an exact name spelling — the bouncer doesn’t guess at close variations or nicknames; either “Jonathan Smith” is written on the list exactly as given, or it isn’t, and the answer is instant either way.
Because keyword fields store values exactly as submitted, a term query for “shipped” will not match a stored value of “Shipped” unless case-insensitive matching is explicitly enabled, or the source data was normalized (for example, lowercased) before indexing.
4Data Flow & Lifecycle
Step 1 — Query Submitted
A client sends a search request containing a term query, either standalone or nested inside a larger boolean query alongside other clauses.
Step 2 — Query Parsing & Shard Routing
The coordinating node parses the request and forwards it to every shard that needs to be searched (or a targeted subset, if routing narrows it).
Step 3 — Per-Shard Execution
Each shard independently performs the exact-value lookup against its own local inverted index and returns its matching document IDs.
Step 4 — Result Merging
The coordinating node combines results from all shards, applies any requested sorting, and returns the final combined result set to the client.
A related but distinct query, “terms,” extends this same exact-match behavior to a whole list of values at once — for example, matching any document where “status” equals “shipped,” “delivered,” or “returned” — internally running the same kind of dictionary lookup, just for multiple values in a single pass.
5Advantages, Disadvantages & Trade-offs
Advantages
- Extremely fast, especially when used in a filter context where results can be cached.
- Predictable, unambiguous behavior — no surprises from stemming, synonyms, or fuzzy matching.
- Ideal for structured, exact-value data like IDs, status codes, categories, and flags.
Disadvantages
- Unforgiving of case, punctuation, or whitespace differences unless explicitly configured otherwise.
- Useless for genuine free-text search — it cannot find “running shoes” inside a longer product description.
- A frequent source of “silent zero results” bugs when accidentally used against an analyzed text field.
The trade-off is precision versus flexibility. A term query gives you rigid, exact, and very fast matching — perfect when your data genuinely has discrete exact values, but the wrong tool the moment you actually need to search natural language.
6Security
Filter-Based Role Restrictions
Document-level security is commonly implemented internally using term (or terms) queries baked into a role — for example, restricting a user to only documents where “department” exactly equals their own department.
No Injection Risk from Analysis
Because term queries skip analysis, there’s no risk of an analyzer unexpectedly transforming sensitive lookup values (like an exact account ID) in a way that broadens or narrows results unpredictably.
Careful Field Choice
Because a term query relies on an exact stored value, exposing a raw sensitive keyword field (like a full ID or token) to end-user-controlled queries can make targeted enumeration easier if access controls aren’t independently enforced.
Using a term query for document-level security is like a keycard reader that checks your badge number against an exact allow-list for a particular floor — no partial matches, no “close enough,” just a precise yes or no before the door unlocks.
7Monitoring, Logging & Metrics
Term queries are simple, but they still leave useful operational signals worth watching, especially at scale:
- High zero-hit rate: a sudden spike in term queries returning zero results often signals a mapping mismatch (querying a text field) or a data formatting change upstream (like inconsistent casing).
- Filter cache effectiveness: since term queries used in filter context are cacheable, monitoring cache hit rates helps confirm the cluster is actually benefiting from that caching, rather than repeatedly recomputing identical filters.
- Slow query logs: although term queries are normally fast, an unusually slow one can indicate an oversized “terms” list or a field with an excessive number of unique values.
8Design Patterns & Anti-patterns
Pattern: Term Query in Filter Context
Whenever exact matching doesn’t need relevance scoring — like filtering by category or status — placing the term query inside a “filter” clause (rather than a scored “must” clause) skips unnecessary scoring work and enables caching.
Pattern: Pair with Keyword Multi-Fields
When a field is primarily “text” for search but occasionally needs exact filtering too, adding a “.keyword” multi-field gives you a dedicated, exact-match target for term queries without changing the primary field’s behavior.
Pattern: Combine with Boolean Queries
Term queries are frequently combined inside a “bool” query’s “filter” array alongside a full-text “match” clause — narrowing results to an exact category while still relevance-ranking by a free-text search phrase.
Running a Term Query Against an Analyzed Text Field
Sending a full phrase or mixed-case value as a term query against a “text” field almost always silently returns zero or unexpected results, because the stored tokens don’t match the unanalyzed input.
Using Term Queries for Free-Text Search
Trying to use term queries to power a general search box leads to a frustrating, rigid experience — users expect typo tolerance and partial matching, which term queries deliberately do not provide.
9Best Practices & Common Mistakes
Best Practices
- Always confirm the target field is mapped as keyword, numeric, boolean, or date before writing a term query.
- Use “filter” context, not “must,” when relevance scoring isn’t needed — it’s faster and cacheable.
- Normalize casing at index time (or enable case-insensitive matching) if user input casing can’t be trusted.
- Use “terms” instead of chaining multiple “term” queries when matching against a list of acceptable values.
Common Mistakes
- Assuming a term query behaves like a case-insensitive “contains” search — it does neither by default.
- Forgetting that multi-word phrases won’t match a term query against a text-analyzed field.
- Placing term queries in scored “must” clauses when a non-scored “filter” clause would be faster and cacheable.
- Not validating that user-supplied filter values actually correspond to real, existing keyword values in the index.
10Real-World & Industry Examples
Category & Brand Filters
Retail search pages use term queries behind facet filters like “Brand: Nike” or “Category: Shoes,” combined with a full-text match clause for the user’s actual search phrase.
Exact Log-Level Filtering
Log dashboards use term queries to filter precisely on “log.level: ERROR” or “service.name: payments-api,” where exact matching is essential and any fuzziness would return misleading results.
Document-Level Access Rules
Security platforms often implement tenant or department isolation using a term query filter baked directly into a role definition, guaranteeing exact-match enforcement on every search.
Exact Flight or Booking Codes
Travel booking systems use term queries to look up an exact confirmation code or flight number, where even a single-character difference must correctly return no result.
11Frequently Asked Questions
12Summary and Key Takeaways
Key Takeaways
- A term query matches documents where a field’s exact, unanalyzed value equals the value you provide.
- It applies no text analysis to your input — no lowercasing, splitting, or stemming — unlike a “match” query.
- Term queries pair naturally with keyword, numeric, boolean, and date fields, not analyzed “text” fields.
- The classic beginner mistake is running a term query against a “text” field, causing silent, confusing zero-result matches.
- Using term queries in filter context (instead of scored “must” clauses) is faster and enables caching.
- Document-level security rules are frequently implemented internally using term or terms queries.
- Term queries excel at precise, structured lookups — status codes, IDs, categories — never at free-text search.