Nested queryedit

Wraps another query to search nested fields.

The nested query searches nested field objects as if they were indexed as separate documents. If an object matches the search, the nested query returns the root parent document.

Example requestedit

Index setupedit

To use the nested query, your index must include a nested field mapping. For example:

resp = client.indices.create(
    index="my_index",
    body={"mappings": {"properties": {"obj1": {"type": "nested"}}}},
)
print(resp)
response = client.indices.create(
  index: 'my_index',
  body: {
    mappings: {
      properties: {
        "obj1": {
          type: 'nested'
        }
      }
    }
  }
)
puts response
res, err := es.Indices.Create(
	"my_index",
	es.Indices.Create.WithBody(strings.NewReader(`{
	  "mappings": {
	    "properties": {
	      "obj1": {
	        "type": "nested"
	      }
	    }
	  }
	}`)),
)
fmt.Println(res, err)
const response = await client.indices.create({
  index: 'my_index',
  body: {
    mappings: {
      properties: {
        obj1: {
          type: 'nested'
        }
      }
    }
  }
})
console.log(response)
PUT /my_index
{
    "mappings" : {
        "properties" : {
            "obj1" : {
                "type" : "nested"
            }
        }
    }
}

Example queryedit

resp = client.search(
    index="my_index",
    body={
        "query": {
            "nested": {
                "path": "obj1",
                "query": {
                    "bool": {
                        "must": [
                            {"match": {"obj1.name": "blue"}},
                            {"range": {"obj1.count": {"gt": 5}}},
                        ]
                    }
                },
                "score_mode": "avg",
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_index',
  body: {
    query: {
      nested: {
        path: 'obj1',
        query: {
          bool: {
            must: [
              {
                match: {
                  "obj1.name": 'blue'
                }
              },
              {
                range: {
                  "obj1.count": {
                    gt: 5
                  }
                }
              }
            ]
          }
        },
        score_mode: 'avg'
      }
    }
  }
)
puts response
res, err := es.Search(
	es.Search.WithIndex("my_index"),
	es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "nested": {
	      "path": "obj1",
	      "query": {
	        "bool": {
	          "must": [
	            {
	              "match": {
	                "obj1.name": "blue"
	              }
	            },
	            {
	              "range": {
	                "obj1.count": {
	                  "gt": 5
	                }
	              }
	            }
	          ]
	        }
	      },
	      "score_mode": "avg"
	    }
	  }
	}`)),
	es.Search.WithPretty(),
)
fmt.Println(res, err)
const response = await client.search({
  index: 'my_index',
  body: {
    query: {
      nested: {
        path: 'obj1',
        query: {
          bool: {
            must: [
              {
                match: {
                  'obj1.name': 'blue'
                }
              },
              {
                range: {
                  'obj1.count': {
                    gt: 5
                  }
                }
              }
            ]
          }
        },
        score_mode: 'avg'
      }
    }
  }
})
console.log(response)
GET /my_index/_search
{
    "query":  {
        "nested" : {
            "path" : "obj1",
            "query" : {
                "bool" : {
                    "must" : [
                    { "match" : {"obj1.name" : "blue"} },
                    { "range" : {"obj1.count" : {"gt" : 5}} }
                    ]
                }
            },
            "score_mode" : "avg"
        }
    }
}

Top-level parameters for nestededit

path
(Required, string) Path to the nested object you wish to search.
query

(Required, query object) Query you wish to run on nested objects in the path. If an object matches the search, the nested query returns the root parent document.

You can search nested fields using dot notation that includes the complete path, such as obj1.name.

Multi-level nesting is automatically supported, and detected, resulting in an inner nested query to automatically match the relevant nesting level, rather than root, if it exists within another nested query.

See Multi-level nested queries for an example.

score_mode

(Optional, string) Indicates how scores for matching child objects affect the root parent document’s relevance score. Valid values are:

avg (Default)
Use the mean relevance score of all matching child objects.
max
Uses the highest relevance score of all matching child objects.
min
Uses the lowest relevance score of all matching child objects.
none
Do not use the relevance scores of matching child objects. The query assigns parent documents a score of 0.
sum
Add together the relevance scores of all matching child objects.
ignore_unmapped

(Optional, boolean) Indicates whether to ignore an unmapped path and not return any documents instead of an error. Defaults to false.

If false, Elasticsearch returns an error if the path is an unmapped field.

You can use this parameter to query multiple indices that may not contain the field path.

Notesedit

Multi-level nested queriesedit

To see how multi-level nested queries work, first you need an index that has nested fields. The following request defines mappings for the drivers index with nested make and model fields.

resp = client.indices.create(
    index="drivers",
    body={
        "mappings": {
            "properties": {
                "driver": {
                    "type": "nested",
                    "properties": {
                        "last_name": {"type": "text"},
                        "vehicle": {
                            "type": "nested",
                            "properties": {
                                "make": {"type": "text"},
                                "model": {"type": "text"},
                            },
                        },
                    },
                }
            }
        }
    },
)
print(resp)
response = client.indices.create(
  index: 'drivers',
  body: {
    mappings: {
      properties: {
        driver: {
          type: 'nested',
          properties: {
            last_name: {
              type: 'text'
            },
            vehicle: {
              type: 'nested',
              properties: {
                make: {
                  type: 'text'
                },
                model: {
                  type: 'text'
                }
              }
            }
          }
        }
      }
    }
  }
)
puts response
res, err := es.Indices.Create(
	"drivers",
	es.Indices.Create.WithBody(strings.NewReader(`{
	  "mappings": {
	    "properties": {
	      "driver": {
	        "type": "nested",
	        "properties": {
	          "last_name": {
	            "type": "text"
	          },
	          "vehicle": {
	            "type": "nested",
	            "properties": {
	              "make": {
	                "type": "text"
	              },
	              "model": {
	                "type": "text"
	              }
	            }
	          }
	        }
	      }
	    }
	  }
	}`)),
)
fmt.Println(res, err)
const response = await client.indices.create({
  index: 'drivers',
  body: {
    mappings: {
      properties: {
        driver: {
          type: 'nested',
          properties: {
            last_name: {
              type: 'text'
            },
            vehicle: {
              type: 'nested',
              properties: {
                make: {
                  type: 'text'
                },
                model: {
                  type: 'text'
                }
              }
            }
          }
        }
      }
    }
  }
})
console.log(response)
PUT /drivers
{
    "mappings" : {
        "properties" : {
            "driver" : {
                "type" : "nested",
                "properties" : {
                    "last_name" : {
                        "type" : "text"
                    },
                    "vehicle" : {
                        "type" : "nested",
                        "properties" : {
                            "make" : {
                                "type" : "text"
                            },
                            "model" : {
                                "type" : "text"
                            }
                        }
                    }
                }
            }
        }
    }
}

Next, index some documents to the drivers index.

resp = client.index(
    index="drivers",
    id="1",
    body={
        "driver": {
            "last_name": "McQueen",
            "vehicle": [
                {"make": "Powell Motors", "model": "Canyonero"},
                {"make": "Miller-Meteor", "model": "Ecto-1"},
            ],
        }
    },
)
print(resp)

resp = client.index(
    index="drivers",
    id="2",
    refresh=True,
    body={
        "driver": {
            "last_name": "Hudson",
            "vehicle": [
                {"make": "Mifune", "model": "Mach Five"},
                {"make": "Miller-Meteor", "model": "Ecto-1"},
            ],
        }
    },
)
print(resp)
response = client.index(
  index: 'drivers',
  id: 1,
  body: {
    driver: {
      last_name: 'McQueen',
      vehicle: [
        {
          make: 'Powell Motors',
          model: 'Canyonero'
        },
        {
          make: 'Miller-Meteor',
          model: 'Ecto-1'
        }
      ]
    }
  }
)
puts response

response = client.index(
  index: 'drivers',
  id: 2,
  refresh: true,
  body: {
    driver: {
      last_name: 'Hudson',
      vehicle: [
        {
          make: 'Mifune',
          model: 'Mach Five'
        },
        {
          make: 'Miller-Meteor',
          model: 'Ecto-1'
        }
      ]
    }
  }
)
puts response
{
	res, err := es.Index(
		"drivers",
		strings.NewReader(`{
	  "driver": {
	    "last_name": "McQueen",
	    "vehicle": [
	      {
	        "make": "Powell Motors",
	        "model": "Canyonero"
	      },
	      {
	        "make": "Miller-Meteor",
	        "model": "Ecto-1"
	      }
	    ]
	  }
	}`),
		es.Index.WithDocumentID("1"),
		es.Index.WithPretty(),
	)
	fmt.Println(res, err)
}

{
	res, err := es.Index(
		"drivers",
		strings.NewReader(`{
	  "driver": {
	    "last_name": "Hudson",
	    "vehicle": [
	      {
	        "make": "Mifune",
	        "model": "Mach Five"
	      },
	      {
	        "make": "Miller-Meteor",
	        "model": "Ecto-1"
	      }
	    ]
	  }
	}`),
		es.Index.WithDocumentID("2"),
		es.Index.WithRefresh("true"),
		es.Index.WithPretty(),
	)
	fmt.Println(res, err)
}
const response0 = await client.index({
  index: 'drivers',
  id: '1',
  body: {
    driver: {
      last_name: 'McQueen',
      vehicle: [
        {
          make: 'Powell Motors',
          model: 'Canyonero'
        },
        {
          make: 'Miller-Meteor',
          model: 'Ecto-1'
        }
      ]
    }
  }
})
console.log(response0)

const response1 = await client.index({
  index: 'drivers',
  id: '2',
  refresh: true,
  body: {
    driver: {
      last_name: 'Hudson',
      vehicle: [
        {
          make: 'Mifune',
          model: 'Mach Five'
        },
        {
          make: 'Miller-Meteor',
          model: 'Ecto-1'
        }
      ]
    }
  }
})
console.log(response1)
PUT /drivers/_doc/1
{
  "driver" : {
        "last_name" : "McQueen",
        "vehicle" : [
            {
                "make" : "Powell Motors",
                "model" : "Canyonero"
            },
            {
                "make" : "Miller-Meteor",
                "model" : "Ecto-1"
            }
        ]
    }
}

PUT /drivers/_doc/2?refresh
{
  "driver" : {
        "last_name" : "Hudson",
        "vehicle" : [
            {
                "make" : "Mifune",
                "model" : "Mach Five"
            },
            {
                "make" : "Miller-Meteor",
                "model" : "Ecto-1"
            }
        ]
    }
}

You can now use a multi-level nested query to match documents based on the make and model fields.

resp = client.search(
    index="drivers",
    body={
        "query": {
            "nested": {
                "path": "driver",
                "query": {
                    "nested": {
                        "path": "driver.vehicle",
                        "query": {
                            "bool": {
                                "must": [
                                    {
                                        "match": {
                                            "driver.vehicle.make": "Powell Motors"
                                        }
                                    },
                                    {
                                        "match": {
                                            "driver.vehicle.model": "Canyonero"
                                        }
                                    },
                                ]
                            }
                        },
                    }
                },
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'drivers',
  body: {
    query: {
      nested: {
        path: 'driver',
        query: {
          nested: {
            path: 'driver.vehicle',
            query: {
              bool: {
                must: [
                  {
                    match: {
                      "driver.vehicle.make": 'Powell Motors'
                    }
                  },
                  {
                    match: {
                      "driver.vehicle.model": 'Canyonero'
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
)
puts response
res, err := es.Search(
	es.Search.WithIndex("drivers"),
	es.Search.WithBody(strings.NewReader(`{
	  "query": {
	    "nested": {
	      "path": "driver",
	      "query": {
	        "nested": {
	          "path": "driver.vehicle",
	          "query": {
	            "bool": {
	              "must": [
	                {
	                  "match": {
	                    "driver.vehicle.make": "Powell Motors"
	                  }
	                },
	                {
	                  "match": {
	                    "driver.vehicle.model": "Canyonero"
	                  }
	                }
	              ]
	            }
	          }
	        }
	      }
	    }
	  }
	}`)),
	es.Search.WithPretty(),
)
fmt.Println(res, err)
const response = await client.search({
  index: 'drivers',
  body: {
    query: {
      nested: {
        path: 'driver',
        query: {
          nested: {
            path: 'driver.vehicle',
            query: {
              bool: {
                must: [
                  {
                    match: {
                      'driver.vehicle.make': 'Powell Motors'
                    }
                  },
                  {
                    match: {
                      'driver.vehicle.model': 'Canyonero'
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
})
console.log(response)
GET /drivers/_search
{
    "query" : {
        "nested" : {
            "path" : "driver",
            "query" : {
                "nested" : {
                    "path" :  "driver.vehicle",
                    "query" :  {
                        "bool" : {
                            "must" : [
                                { "match" : { "driver.vehicle.make" : "Powell Motors" } },
                                { "match" : { "driver.vehicle.model" : "Canyonero" } }
                            ]
                        }
                    }
                }
            }
        }
    }
}

The search request returns the following response:

{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 3.7349272,
    "hits" : [
      {
        "_index" : "drivers",
        "_id" : "1",
        "_score" : 3.7349272,
        "_source" : {
          "driver" : {
            "last_name" : "McQueen",
            "vehicle" : [
              {
                "make" : "Powell Motors",
                "model" : "Canyonero"
              },
              {
                "make" : "Miller-Meteor",
                "model" : "Ecto-1"
              }
            ]
          }
        }
      }
    ]
  }
}