Terms query

Terms query #

Returns documents that contain one or more exact terms in a provided field. Equivalent to a boolean should of individual term queries — a document matches if it contains any of the values.

Inside a nested query: not supported yet — the clause is rejected with an HTTP 400 naming the offending clause. Expand into a bool should of term clauses instead.

How it works #

The planner expands the query before execution: each value becomes a term clause inside a BooleanQuery with minimum_should_match: 1, and a single-value terms collapses straight into one bare term query. Everything said on the term page about verbatim lookup, index routing (dictionary for keyword/text, BKD for numeric/date, Bool column for boolean) and BM25 scoring therefore applies per value here, with the per-value scores OR-ed together.

Like term, the values are matched as exact terms — no analysis is applied. Note the engine’s terms has no case_insensitive knob (its term sibling does); fold case yourself before sending if you need it.

One internal fast path is worth knowing about: when a terms set was produced by a join rewrite (the _ref payload) rather than hand-written, the executor may run it as a sorted-intersect over the value-sorted doc-values column instead of one iterator per value. Scores are irrelevant on that path; hand-written queries keep the per-term scoring semantics described above.

Examples #

The following search matches the two noisiest levels together — 50 of the 150 documents in the logs dataset (25 error + 25 warn).

POST /my-collection/_search
{
  "query": {
    "terms": {
      "field": "status",
      "values": ["published", "pending"]
    }
  }
}

Use cases #

  • Multi-select facets. A dashboard checkbox set (“error + warn”, three of four sales statuses) maps one-to-one onto a values array — the SQL twin is an IN (...) list.
  • Cohort sets. terms on customers.tier = ["gold","silver"] returns 12 of the 20 customers; on articles.tags = ["search","storage"] it returns the 4 articles carrying either tag.
  • Host shards. terms on logs.host = ["web-01","web-02"] scopes an investigation to 100 of the 150 log lines.
  • Filter step of a two-phase search. A bool.filter terms narrowing candidates before a scored full-text clause — the cheapest possible shape since per-value scoring is discarded anyway.

Parameters for terms #

  • field
    (Required, string) The field to match.
  • values
    (Required, array) List of terms to match. A document matches if it contains any of these values.
  • boost
    (Optional, float, default: 1.0) Decrease or increase the relevance scores of the query.

Notes #

The values are matched as exact terms — no analysis is applied. To match analyzed text, use the match query.

  • term — the single-value original this expands into.
  • bool — what the expansion becomes; write it by hand when you need must_not or per-clause boosts around the values.
  • range — the contiguous-family alternative when the values form an interval.
  • terms aggregation — count documents per value of the same keyword field a terms query filters on; the pair powers faceted navigation.
Calendar October 6, 2026
Edit Edit this page