嵌套查询
编辑嵌套查询编辑
包装另一个查询以搜索嵌套字段。
nested
查询将嵌套字段对象搜索为单独的文档,就像它们被索引一样。如果一个对象匹配搜索,nested
查询将返回根父文档。
示例请求编辑
索引设置编辑
要使用nested
查询,您的索引必须包含一个嵌套字段映射。例如
resp = client.indices.create( index="my-index-000001", body={"mappings": {"properties": {"obj1": {"type": "nested"}}}}, ) print(resp)
response = client.indices.create( index: 'my-index-000001', body: { mappings: { properties: { "obj1": { type: 'nested' } } } } ) puts response
res, err := es.Indices.Create( "my-index-000001", es.Indices.Create.WithBody(strings.NewReader(`{ "mappings": { "properties": { "obj1": { "type": "nested" } } } }`)), ) fmt.Println(res, err)
PUT /my-index-000001 { "mappings": { "properties": { "obj1": { "type": "nested" } } } }
示例查询编辑
resp = client.search( index="my-index-000001", 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-000001', 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-000001"), 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)
GET /my-index-000001/_search { "query": { "nested": { "path": "obj1", "query": { "bool": { "must": [ { "match": { "obj1.name": "blue" } }, { "range": { "obj1.count": { "gt": 5 } } } ] } }, "score_mode": "avg" } } }
nested
的顶级参数编辑
-
path
- (必需,字符串) 您要搜索的嵌套对象的路径。
-
query
-
(必需,查询对象) 您希望在
path
中的嵌套对象上运行的查询。如果一个对象匹配搜索,nested
查询将返回根父文档。您可以使用包括完整路径的点符号来搜索嵌套字段,例如
obj1.name
。多级嵌套会自动支持和检测,从而导致内部嵌套查询自动匹配相关的嵌套级别,而不是根级别,如果它存在于另一个嵌套查询中。
有关示例,请参阅多级嵌套查询。
-
score_mode
-
(可选,字符串) 指示匹配子对象的得分如何影响根父文档的相关性得分。有效值为
-
avg
(默认) - 使用所有匹配子对象的平均相关性得分。
-
max
- 使用所有匹配子对象的最高相关性得分。
-
min
- 使用所有匹配子对象的最低相关性得分。
-
none
- 不要使用匹配子对象的相关性得分。查询将为父文档分配
0
的得分。 -
sum
- 将所有匹配子对象的相关性得分加在一起。
-
-
ignore_unmapped
-
(可选,布尔值) 指示是否忽略未映射的
path
,并且不返回任何文档,而不是错误。默认为false
。如果为
false
,则 Elasticsearch 会在path
是未映射字段时返回错误。您可以使用此参数查询可能不包含字段
path
的多个索引。
注意事项编辑
多级嵌套查询编辑
要了解多级嵌套查询的工作原理,首先您需要一个具有嵌套字段的索引。以下请求定义了具有嵌套make
和model
字段的drivers
索引的映射。
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)
PUT /drivers { "mappings": { "properties": { "driver": { "type": "nested", "properties": { "last_name": { "type": "text" }, "vehicle": { "type": "nested", "properties": { "make": { "type": "text" }, "model": { "type": "text" } } } } } } } }
接下来,将一些文档索引到drivers
索引中。
$params = [ 'index' => 'drivers', 'id' => '1', 'body' => [ 'driver' => [ 'last_name' => 'McQueen', 'vehicle' => [ [ 'make' => 'Powell Motors', 'model' => 'Canyonero', ], [ 'make' => 'Miller-Meteor', 'model' => 'Ecto-1', ], ], ], ], ]; $response = $client->index($params); $params = [ 'index' => 'drivers', 'id' => '2', 'body' => [ 'driver' => [ 'last_name' => 'Hudson', 'vehicle' => [ [ 'make' => 'Mifune', 'model' => 'Mach Five', ], [ 'make' => 'Miller-Meteor', 'model' => 'Ecto-1', ], ], ], ], ]; $response = $client->index($params);
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" } ] } }
现在,您可以使用多级嵌套查询根据make
和model
字段匹配文档。
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)
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" } } ] } } } } } } }
搜索请求返回以下响应
{ "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" } ] } } } ] } }
must_not
子句和nested
查询编辑
如果nested
查询匹配文档中的一个或多个嵌套对象,它将返回该文档作为命中。即使文档中的其他嵌套对象不匹配查询,这也适用。在使用包含内部must_not
子句的nested
查询时,请牢记这一点。
使用inner_hits
参数查看哪些嵌套对象匹配nested
查询。
例如,以下搜索使用带有内部must_not
子句的外部nested
查询。
resp = client.indices.create( index="my-index", body={"mappings": {"properties": {"comments": {"type": "nested"}}}}, ) print(resp) resp = client.index( index="my-index", id="1", refresh=True, body={"comments": [{"author": "kimchy"}]}, ) print(resp) resp = client.index( index="my-index", id="2", refresh=True, body={"comments": [{"author": "kimchy"}, {"author": "nik9000"}]}, ) print(resp) resp = client.index( index="my-index", id="3", refresh=True, body={"comments": [{"author": "nik9000"}]}, ) print(resp) resp = client.search( index="my-index", body={ "query": { "nested": { "path": "comments", "query": { "bool": { "must_not": [ {"term": {"comments.author": "nik9000"}} ] } }, } } }, ) print(resp)
response = client.indices.create( index: 'my-index', body: { mappings: { properties: { comments: { type: 'nested' } } } } ) puts response response = client.index( index: 'my-index', id: 1, refresh: true, body: { comments: [ { author: 'kimchy' } ] } ) puts response response = client.index( index: 'my-index', id: 2, refresh: true, body: { comments: [ { author: 'kimchy' }, { author: 'nik9000' } ] } ) puts response response = client.index( index: 'my-index', id: 3, refresh: true, body: { comments: [ { author: 'nik9000' } ] } ) puts response response = client.search( index: 'my-index', body: { query: { nested: { path: 'comments', query: { bool: { must_not: [ { term: { 'comments.author' => 'nik9000' } } ] } } } } } ) puts response
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" } } ] } } } } }
搜索返回
{ ... "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" }, { "author" : "nik9000" } ] } } ] } }
要排除任何嵌套对象匹配nested
查询的文档,请使用外部must_not
子句。
resp = client.search( index="my-index", body={ "query": { "bool": { "must_not": [ { "nested": { "path": "comments", "query": { "term": {"comments.author": "nik9000"} }, } } ] } } }, ) print(resp)
response = client.search( index: 'my-index', body: { query: { bool: { must_not: [ { nested: { path: 'comments', query: { term: { 'comments.author' => 'nik9000' } } } } ] } } } ) puts response
POST my-index/_search { "query": { "bool": { "must_not": [ { "nested": { "path": "comments", "query": { "term": { "comments.author": "nik9000" } } } } ] } } }
搜索返回
{ ... "hits" : { ... "hits" : [ { "_index" : "my-index", "_id" : "1", "_score" : 0.0, "_source" : { "comments" : [ { "author" : "kimchy" } ] } } ] } }