Elasticsearch IDs Query: Fetch Documents by _id - Syntax, Example, and Tips

The Elasticsearch ids query returns documents whose _id metadata field matches any value in a supplied list. It works against the internal _id field on every index, so no mapping is required. Use it for ad-hoc lookups when you already know the document identifiers but need to apply scoring, highlighting, aggregations, or filters that the multi-get API does not support.

Syntax

{
  "query": {
    "ids": {
      "values": ["id1", "id2", "id3"]
    }
  }
}

The values array accepts strings. There are no other parameters on the ids query itself.

Parameters

Parameter Type Required Description
values array of strings yes One or more _id values to match.

Examples

Basic lookup of three documents:

GET /my-index/_search
{
  "query": {
    "ids": { "values": ["1", "4", "100"] }
  }
}

Combine with a filter and source filtering:

GET /products/_search
{
  "_source": ["name", "price"],
  "query": {
    "bool": {
      "must":   [ { "ids": { "values": ["sku-001", "sku-002", "sku-003"] } } ],
      "filter": [ { "term": { "in_stock": true } } ]
    }
  }
}

Cross-index lookup (the same ids are searched across both indices):

GET /orders-2024,orders-2025/_search
{
  "query": { "ids": { "values": ["a1b2", "c3d4"] } }
}

Use with aggregations - the ids query reduces the working set, then the aggregation runs on the matched documents:

GET /events/_search
{
  "size": 0,
  "query": { "ids": { "values": ["e1", "e2", "e3", "e4"] } },
  "aggs":  { "by_type": { "terms": { "field": "type" } } }
}

Performance and Use Notes

The ids query is internally rewritten to a TermInSetQuery over the _id field, which is fast for small to mid-size value lists. For pure point-lookup workloads where scoring, highlighting, and aggregations are not needed, the multi-get API (_mget) is the canonical choice - it skips the query phase entirely. The ids query is the right tool when you want id-based selection to participate in a regular search request.

Keep the values list bounded. Lists of thousands of ids inflate the request body, the term dictionary lookup cost, and the per-shard fetch. If you find yourself passing tens of thousands of ids, the data model is usually the problem: a terms query over an indexed key field is typically faster and more cacheable.

Misused ids lookups - especially in hot paths driven by application code - show up as elevated search latency without obvious cause. Pulse monitors Elasticsearch query patterns and flags inefficient id-based access patterns, so teams can replace them with _mget or a terms query before they show up as user-facing latency.

Common Mistakes

  1. Using ids for bulk retrieval of hundreds of documents when _mget would be faster.
  2. Assuming the response order matches the input array order - it does not; add sort if order matters.
  3. Expecting an error for missing ids; the query silently skips ids that do not exist.
  4. Forgetting that _id is always a string in the query, even if your application treats it as numeric.
  5. Pairing ids with a routing value that points to the wrong shard, causing zero hits.

Frequently Asked Questions

Q: How is the Elasticsearch ids query different from the multi-get API?
A: The ids query runs through the search pipeline and supports scoring, highlighting, aggregations, and source filtering across multiple indices. The multi-get API (_mget) skips the query phase and goes directly to the document store, making it faster for pure point lookups.

Q: Is there a hard limit on the number of ids in an ids query?
A: There is no fixed limit, but the request size is bounded by http.max_content_length (default 100 MB) and practical performance considerations. Lists above a few thousand ids typically perform better as a terms query against an indexed key field.

Q: Does the ids query work across multiple indices?
A: Yes. Targeting my-index-* or a comma-separated list of indices searches the same id values across all of them. If the same _id exists in more than one index, all matches are returned.

Q: Does the ids query return results in the order of the values array?
A: No. The ids query does not preserve input order. To return documents in a specific order, sort by a field, or post-process the response in the application.

Q: Can the ids query be used in a filter context?
A: Yes. Wrapping ids in bool.filter keeps it out of scoring and lets the result set be cached as a bitset, which is the recommended pattern when score is irrelevant.

Q: Why does my ids query return fewer documents than ids supplied?
A: Missing documents are silently skipped. Either the id never existed, the document was deleted (and the deletion has been merged away), or the request is hitting a routing alias that excludes the shard holding the document.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.