Nested query

The nested query acts as a wrapper for other queries to search nested fields. The nested field objects are searched as though they were indexed as separate documents. If an object matches the search, the nested query returns the parent document at the root level.

Example

Before you can run a nested query, your index must contain a nested field.

To configure an example index containing nested fields, send the following request:

  1. PUT /testindex
  2. {
  3. "mappings": {
  4. "properties": {
  5. "patient": {
  6. "type": "nested",
  7. "properties": {
  8. "name": {
  9. "type": "text"
  10. },
  11. "age": {
  12. "type": "integer"
  13. }
  14. }
  15. }
  16. }
  17. }
  18. }

copy

Next, index a document into the example index:

  1. PUT /testindex/_doc/1
  2. {
  3. "patient": {
  4. "name": "John Doe",
  5. "age": 56
  6. }
  7. }

copy

To search the nested patient field, wrap your query in a nested query and provide the path to the nested field:

  1. GET /testindex/_search
  2. {
  3. "query": {
  4. "nested": {
  5. "path": "patient",
  6. "query": {
  7. "match": {
  8. "patient.name": "John"
  9. }
  10. }
  11. }
  12. }
  13. }

copy

The query returns the matching document:

  1. {
  2. "took": 3,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": {
  12. "value": 1,
  13. "relation": "eq"
  14. },
  15. "max_score": 0.2876821,
  16. "hits": [
  17. {
  18. "_index": "testindex",
  19. "_id": "1",
  20. "_score": 0.2876821,
  21. "_source": {
  22. "patient": {
  23. "name": "John Doe",
  24. "age": 56
  25. }
  26. }
  27. }
  28. ]
  29. }
  30. }

Retrieving inner hits

To return inner hits that matched the query, provide the inner_hits parameter:

  1. GET /testindex/_search
  2. {
  3. "query": {
  4. "nested": {
  5. "path": "patient",
  6. "query": {
  7. "match": {
  8. "patient.name": "John"
  9. }
  10. },
  11. "inner_hits": {}
  12. }
  13. }
  14. }

copy

The response contains the additional inner_hits field. The _nested field identifies the specific inner object from which the inner hit originated. It contains the nested hit and the offset relative to its position in the _source. Because of sorting and scoring, the position of the hit objects in inner_hits often differs from their original location in the nested object.

By default, the _source of the hit objects within inner_hits is returned relative to the _nested field. In this example, the _source within inner_hits contains the name and age fields as opposed to the top-level _source, which contains the whole patient object:

  1. {
  2. "took": 38,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": {
  12. "value": 1,
  13. "relation": "eq"
  14. },
  15. "max_score": 0.2876821,
  16. "hits": [
  17. {
  18. "_index": "testindex",
  19. "_id": "1",
  20. "_score": 0.2876821,
  21. "_source": {
  22. "patient": {
  23. "name": "John Doe",
  24. "age": 56
  25. }
  26. },
  27. "inner_hits": {
  28. "patient": {
  29. "hits": {
  30. "total": {
  31. "value": 1,
  32. "relation": "eq"
  33. },
  34. "max_score": 0.2876821,
  35. "hits": [
  36. {
  37. "_index": "testindex",
  38. "_id": "1",
  39. "_nested": {
  40. "field": "patient",
  41. "offset": 0
  42. },
  43. "_score": 0.2876821,
  44. "_source": {
  45. "name": "John Doe",
  46. "age": 56
  47. }
  48. }
  49. ]
  50. }
  51. }
  52. }
  53. }
  54. ]
  55. }
  56. }

You can disable returning _source by configuring the _source field in the mappings. For more information, see Source.

For more information about retrieving inner hits, see Inner hits.

Multi-level nested queries

You can search documents that have nested objects inside other nested objects using multi-level nested queries. In this example, you’ll query multiple layers of nested fields by specifying a nested query for each level of the hierarchy.

First, create an index with multi-level nested fields:

  1. PUT /patients
  2. {
  3. "mappings": {
  4. "properties": {
  5. "patient": {
  6. "type": "nested",
  7. "properties": {
  8. "name": {
  9. "type": "text"
  10. },
  11. "contacts": {
  12. "type": "nested",
  13. "properties": {
  14. "name": {
  15. "type": "text"
  16. },
  17. "relationship": {
  18. "type": "text"
  19. },
  20. "phone": {
  21. "type": "keyword"
  22. }
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }
  29. }

copy

Next, index a document into the example index:

  1. PUT /patients/_doc/1
  2. {
  3. "patient": {
  4. "name": "John Doe",
  5. "contacts": [
  6. {
  7. "name": "Jane Doe",
  8. "relationship": "mother",
  9. "phone": "5551111"
  10. },
  11. {
  12. "name": "Joe Doe",
  13. "relationship": "father",
  14. "phone": "5552222"
  15. }
  16. ]
  17. }
  18. }

copy

To search the nested patient field, use a multi-level nested query. The following query searches for patients whose contact information includes a person named Jane with a relationship of mother:

  1. GET /patients/_search
  2. {
  3. "query": {
  4. "nested": {
  5. "path": "patient",
  6. "query": {
  7. "nested": {
  8. "path": "patient.contacts",
  9. "query": {
  10. "bool": {
  11. "must": [
  12. { "match": { "patient.contacts.relationship": "mother" } },
  13. { "match": { "patient.contacts.name": "Jane" } }
  14. ]
  15. }
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }

copy

The query returns the patient who has a contact entry matching these details:

  1. {
  2. "took": 14,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": {
  12. "value": 1,
  13. "relation": "eq"
  14. },
  15. "max_score": 1.3862942,
  16. "hits": [
  17. {
  18. "_index": "patients",
  19. "_id": "1",
  20. "_score": 1.3862942,
  21. "_source": {
  22. "patient": {
  23. "name": "John Doe",
  24. "contacts": [
  25. {
  26. "name": "Jane Doe",
  27. "relationship": "mother",
  28. "phone": "5551111"
  29. },
  30. {
  31. "name": "Joe Doe",
  32. "relationship": "father",
  33. "phone": "5552222"
  34. }
  35. ]
  36. }
  37. }
  38. }
  39. ]
  40. }
  41. }

Parameters

The following table lists all top-level parameters supported by nested queries.

ParameterRequired/OptionalDescription
pathRequiredSpecifies the path to the nested object that you want to search.
queryRequiredThe query to run on the nested objects within the specified path. If a nested object matches the query, the root parent document is returned. You can search nested fields using dot notation, such as nested_object.subfield. Multi-level nesting is supported and automatically detected. Thus, an inner nested query within another nested query automatically matches the correct nesting level, instead of the root.
ignore_unmappedOptionalIndicates whether to ignore unmapped path fields and not return documents instead of throwing an error. You can provide this parameter when querying multiple indexes, some of which may not contain the path field. Default is false.
score_modeOptionalDefines how scores of matching inner documents influence the parent document’s score. Valid values are:
- avg: Uses the average relevance score of all matching inner documents.
- max: Assigns the highest relevance score from the matching inner documents to the parent.
- min: Assigns the lowest relevance score from the matching inner documents to the parent.
- sum: Sums the relevance scores of all matching inner documents.
- none: Ignores the relevance scores of inner documents and assigns a score of 0 to the parent document.
Default is avg.
inner_hitsOptionalIf provided, returns the underlying hits that matched the query.

Next steps