NEW

Pulse 2025 Product Roundup: From Monitoring to AI-Native Control Plane

Elasticsearch Nested Query: Syntax, Parameters, and Examples - Syntax, Example, and Tips

The Elasticsearch nested query runs a subquery against objects stored under a nested field, treating each element of the nested array as its own indexed document. This preserves the relationship between fields inside the same object - a constraint that is lost when arrays of objects are stored with the default flat (object) mapping. Use the nested query when you need to match multiple conditions on the same array element, e.g. a comment with author=alice AND rating=5.

Syntax

GET /index/_search
{
  "query": {
    "nested": {
      "path": "path_to_nested_field",
      "query": { /* any query, scoped to path.* fields */ },
      "score_mode": "avg",
      "ignore_unmapped": false,
      "inner_hits": {}
    }
  }
}

Parameters

Parameter Description Required Default
path Path of the nested field to search. Yes -
query Query to run against the nested objects. Field references must be prefixed with path.. Yes -
score_mode How to combine matching nested object scores into the parent score: avg, max, min, sum, none. No avg
ignore_unmapped If true, ignores indices that lack the nested mapping instead of erroring. No false
inner_hits Return the matching nested sub-documents alongside the parent hits. No -

The target field must be mapped with "type": "nested". The query will not work on a plain object mapping; field relationships flatten and you will get false positives.

Examples

Find books that have a comment with rating greater than 4:

GET /books/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "range": { "comments.rating": { "gt": 4 } }
      }
    }
  }
}

Multiple conditions on the same nested element:

GET /books/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "must": [
            { "match": { "comments.author": "alice" } },
            { "range": { "comments.rating": { "gte": 5 } } }
          ]
        }
      },
      "score_mode": "max"
    }
  }
}

Return the matching nested objects via inner_hits:

GET /books/_search
{
  "query": {
    "nested": {
      "path":  "comments",
      "query": { "match": { "comments.body": "excellent" } },
      "inner_hits": { "size": 3 }
    }
  }
}

Multi-level nesting (orders.items, items as nested under orders):

GET /customers/_search
{
  "query": {
    "nested": {
      "path": "orders",
      "query": {
        "nested": {
          "path": "orders.items",
          "query": {
            "bool": {
              "must": [
                { "term":  { "orders.items.sku":      "AX-100" } },
                { "range": { "orders.items.quantity": { "gte": 2 } } }
              ]
            }
          }
        }
      }
    }
  }
}

Performance and Use Notes

Nested mappings cost more than object mappings. Each nested element is indexed as a hidden Lucene document under the same parent, so an index with 1 million parents and 10 nested elements per parent stores 11 million documents internally. This affects every operation that scans documents: search, aggregation, segment merging, and shard size all grow accordingly. The index.mapping.nested_fields.limit default is 50, and index.mapping.nested_objects.limit defaults to 10000 (per parent document).

Score combination is controlled by score_mode. The default avg averages all matching nested-object scores into one parent score; max keeps the best, min the worst, sum adds them, and none discards them. Choose none when you only need a filter and want to skip score arithmetic. Wrap nested queries in bool.filter whenever scoring is unneeded.

Hidden nested-document growth is a frequent source of unexpected shard size and slow aggregations. Manually correlating nested doc counts against shard size and slow-log entries to find the mapping that is silently dominating cluster cost is exactly the loop Pulse runs continuously.

Common Mistakes

  1. Querying an array of objects without mapping the field as nested. With the default object mapping, all comments.author values flatten and author=alice AND rating=5 will match if any element has each value separately - even on different elements.
  2. Forgetting the path prefix in the inner query: write comments.rating, not just rating.
  3. Indexing many small nested elements per parent. Each one is a hidden Lucene document - watch index size and merge time.
  4. Deeply nested mappings (3+ levels). Query syntax becomes unwieldy and cost compounds. Consider parent/child or denormalization.
  5. Treating inner_hits as free. It runs a second query under the hood per parent hit; cap it with size and pagination.

Find Slow Nested Queries with Pulse

Pulse is an AI DBA for Elasticsearch and OpenSearch that continuously profiles production query traffic. For nested queries specifically, Pulse:

  • Identifies nested queries running against large hidden-document sets where scoring is computed across every matching child, plus those issued in query context when score_mode: none inside bool.filter would skip score arithmetic entirely
  • Surfaces indices where hidden nested document count is dominating shard size, plus mappings approaching index.mapping.nested_fields.limit (default 50) or index.mapping.nested_objects.limit (default 10000 per parent)
  • Flags inner_hits blocks without size caps, where a secondary per-parent query is multiplying latency
  • Traces each slow nested query back to the calling service via slow-log and APM correlation
  • Recommends concrete rewrites: wrap the nested clause in bool.filter with score_mode: none, denormalize when child cardinality outgrows the parent, replace 3+ level nesting with parent/child join or denormalized fields, and cap inner_hits.size
  • Tracks latency and shard-size impact after the mapping or query change ships

This converts the manual nested-mapping diagnosis loop into a continuous optimization workflow.

Try Pulse on your cluster.

Frequently Asked Questions

Q: When should I use a nested query instead of a flat object query?
A: Use a nested query whenever you need multiple conditions to match on the same element of an array of objects. The default object mapping flattens arrays, so comments.author=alice AND comments.rating=5 will return documents where one comment is by Alice and a different comment has rating 5.

Q: What does score_mode do in a nested query?
A: score_mode decides how scores from matching nested objects are combined into a single score for the parent document. avg (the default) averages them, max and min take the best/worst, sum adds them, none discards them entirely.

Q: How do I retrieve the matching nested objects?
A: Add an inner_hits block to the nested query. The response then includes a inner_hits section per parent hit, listing the nested sub-documents that matched the query, with their own _score and offset.

Q: Are nested queries expensive?
A: They are more expensive than queries against flat objects, because each nested element is a hidden Lucene document. A 1M-parent index with 10 nested elements per parent stores 11M internal documents. Keep nested arrays small and prefer denormalization for high-cardinality children.

Q: Can I aggregate across nested fields?
A: Yes, with the nested aggregation. Wrap your metric or bucket aggregation under a nested aggregation pointing at the same path. Otherwise the aggregation treats each parent as one document and you lose per-element grouping.

Q: How deeply can I nest objects?
A: Elasticsearch enforces index.mapping.depth.limit (default 20) and index.mapping.nested_fields.limit (default 50). Practical performance falls off fast beyond 2-3 levels; consider denormalization or the parent/child join field instead.

Q: How do I find which nested queries are causing slow searches?
A: Pulse profiles Elasticsearch and OpenSearch slow logs, isolates nested queries scoring across large hidden-document sets and those with uncapped inner_hits, attributes each to the calling service, and recommends score_mode: none in bool.filter, denormalization when child cardinality is high, and concrete inner_hits.size caps.

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.