mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-04-25 07:37:19 -04:00
464 lines
8.9 KiB
Text
464 lines
8.9 KiB
Text
[[query-dsl-nested-query]]
|
|
=== Nested query
|
|
++++
|
|
<titleabbrev>Nested</titleabbrev>
|
|
++++
|
|
|
|
Wraps another query to search <<nested,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.
|
|
|
|
[[nested-query-ex-request]]
|
|
==== Example request
|
|
|
|
[[nested-query-index-setup]]
|
|
===== Index setup
|
|
|
|
To use the `nested` query, your index must include a <<nested,nested>> field
|
|
mapping. For example:
|
|
|
|
[source,console]
|
|
----
|
|
PUT /my-index-000001
|
|
{
|
|
"mappings": {
|
|
"properties": {
|
|
"obj1": {
|
|
"type": "nested"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
----
|
|
|
|
[[nested-query-ex-query]]
|
|
===== Example query
|
|
|
|
[source,console]
|
|
----
|
|
GET /my-index-000001/_search
|
|
{
|
|
"query": {
|
|
"nested": {
|
|
"path": "obj1",
|
|
"query": {
|
|
"bool": {
|
|
"must": [
|
|
{ "match": { "obj1.name": "blue" } },
|
|
{ "range": { "obj1.count": { "gt": 5 } } }
|
|
]
|
|
}
|
|
},
|
|
"score_mode": "avg"
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[continued]
|
|
|
|
[[nested-top-level-params]]
|
|
==== Top-level parameters for `nested`
|
|
|
|
`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-query-ex>> for an example.
|
|
--
|
|
|
|
`score_mode`::
|
|
+
|
|
--
|
|
(Optional, string) Indicates how scores for matching child objects affect the
|
|
root parent document's <<relevance-scores,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`, {es} 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`.
|
|
--
|
|
|
|
[[nested-query-notes]]
|
|
==== Notes
|
|
|
|
[[nested-query-script-notes]]
|
|
===== Context of script queries
|
|
If you run a <<query-dsl-script-query,`script` query>> within a nested query,
|
|
you can only access doc values from the nested document, not the parent
|
|
or root document.
|
|
|
|
[[multi-level-nested-query-ex]]
|
|
===== Multi-level nested queries
|
|
|
|
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.
|
|
|
|
[source,console]
|
|
----
|
|
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.
|
|
|
|
[source,console]
|
|
----
|
|
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"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
----
|
|
// TEST[continued]
|
|
|
|
You can now use a multi-level nested query
|
|
to match documents based on the `make` and `model` fields.
|
|
|
|
[source,console]
|
|
----
|
|
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" } }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[continued]
|
|
|
|
The search request returns the following response:
|
|
|
|
[source,console-result]
|
|
----
|
|
{
|
|
"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"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
----
|
|
// TESTRESPONSE[s/"took" : 5/"took": $body.took/]
|
|
|
|
[[must-not-clauses-and-nested-queries]]
|
|
===== `must_not` clauses and `nested` queries
|
|
|
|
If a `nested` query matches one or more nested objects in a document, it returns
|
|
the document as a hit. This applies even if other nested objects in the document
|
|
don't match the query. Keep this in mind when using a `nested` query that
|
|
contains an inner <<query-dsl-bool-query,`must_not` clause>>.
|
|
|
|
TIP: Use the <<inner-hits,`inner_hits`>> parameter to see which nested objects
|
|
matched a `nested` query.
|
|
|
|
For example, the following search uses an outer `nested` query with an inner
|
|
`must_not` clause.
|
|
|
|
[source,console]
|
|
----
|
|
PUT my-index
|
|
{
|
|
"mappings": {
|
|
"properties": {
|
|
"comments": {
|
|
"type": "nested"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PUT my-index/_doc/1?refresh
|
|
{
|
|
"comments": [
|
|
{
|
|
"author": "kimchy"
|
|
}
|
|
]
|
|
}
|
|
|
|
PUT my-index/_doc/2?refresh
|
|
{
|
|
"comments": [
|
|
{
|
|
"author": "kimchy"
|
|
},
|
|
{
|
|
"author": "nik9000"
|
|
}
|
|
]
|
|
}
|
|
|
|
PUT my-index/_doc/3?refresh
|
|
{
|
|
"comments": [
|
|
{
|
|
"author": "nik9000"
|
|
}
|
|
]
|
|
}
|
|
|
|
POST my-index/_search
|
|
{
|
|
"query": {
|
|
"nested": {
|
|
"path": "comments",
|
|
"query": {
|
|
"bool": {
|
|
"must_not": [
|
|
{
|
|
"term": {
|
|
"comments.author": "nik9000"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[s/_search/_search?filter_path=hits.hits/]
|
|
|
|
The search returns:
|
|
|
|
[source,console]
|
|
----
|
|
{
|
|
...
|
|
"hits" : {
|
|
...
|
|
"hits" : [
|
|
{
|
|
"_index" : "my-index",
|
|
"_id" : "1",
|
|
"_score" : 0.0,
|
|
"_source" : {
|
|
"comments" : [
|
|
{
|
|
"author" : "kimchy"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"_index" : "my-index",
|
|
"_id" : "2",
|
|
"_score" : 0.0,
|
|
"_source" : {
|
|
"comments" : [
|
|
{
|
|
"author" : "kimchy" <1>
|
|
},
|
|
{
|
|
"author" : "nik9000" <2>
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
----
|
|
// TESTRESPONSE[s/\.\.\.//]
|
|
|
|
<1> This nested object matches the query. As a result, the search returns the
|
|
object's parent document as a hit.
|
|
|
|
<2> This nested object doesn't match the query. Since another nested object in
|
|
the same document does match the query, the search still returns the parent
|
|
document as a hit.
|
|
|
|
To exclude documents with any nested objects that match the `nested` query,
|
|
use an outer `must_not` clause.
|
|
|
|
[source,console]
|
|
----
|
|
POST my-index/_search
|
|
{
|
|
"query": {
|
|
"bool": {
|
|
"must_not": [
|
|
{
|
|
"nested": {
|
|
"path": "comments",
|
|
"query": {
|
|
"term": {
|
|
"comments.author": "nik9000"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[continued]
|
|
// TEST[s/_search/_search?filter_path=hits.hits/]
|
|
|
|
The search returns:
|
|
|
|
[source,console]
|
|
----
|
|
{
|
|
...
|
|
"hits" : {
|
|
...
|
|
"hits" : [
|
|
{
|
|
"_index" : "my-index",
|
|
"_id" : "1",
|
|
"_score" : 0.0,
|
|
"_source" : {
|
|
"comments" : [
|
|
{
|
|
"author" : "kimchy"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
----
|
|
// TESTRESPONSE[s/\.\.\.//]
|