ネストされたクエリ
別のクエリをラップしてnestedフィールドを検索します。
## 例のリクエスト
### インデックス設定
`````nested`````クエリを使用するには、インデックスに[nested](/read/elasticsearch-8-15/5ccf197014f16687.md)フィールドマッピングが含まれている必要があります。例えば:
#### Python
``````python
resp = client.indices.create(
index="my-index-000001",
mappings={
"properties": {
"obj1": {
"type": "nested"
}
}
},
)
print(resp)
`
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
properties: {
"obj1": {
type: 'nested'
}
}
}
}
)
puts response
Go
res, err := es.Indices.Create(
"my-index-000001",
es.Indices.Create.WithBody(strings.NewReader(`{
"mappings": {
"properties": {
"obj1": {
"type": "nested"
}
}
}
}`)),
)
fmt.Println(res, err)
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
properties: {
obj1: {
type: "nested",
},
},
},
});
console.log(response);
コンソール
PUT /my-index-000001
{
"mappings": {
"properties": {
"obj1": {
"type": "nested"
}
}
}
}
例のクエリ
Python
resp = client.search(
index="my-index-000001",
query={
"nested": {
"path": "obj1",
"query": {
"bool": {
"must": [
{
"match": {
"obj1.name": "blue"
}
},
{
"range": {
"obj1.count": {
"gt": 5
}
}
}
]
}
},
"score_mode": "avg"
}
},
)
print(resp)
Ruby
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
Go
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)
Js
const response = await client.search({
index: "my-index-000001",
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-000001/_search
{
"query": {
"nested": {
"path": "obj1",
"query": {
"bool": {
"must": [
{ "match": { "obj1.name": "blue" } },
{ "range": { "obj1.count": { "gt": 5 } } }
]
}
},
"score_mode": "avg"
}
}
}
ネストされたためのトップレベルパラメータ
path
- (必須、文字列) 検索したいネストされたオブジェクトへのパス。
query
- (必須、クエリオブジェクト)
path
内のネストされたオブジェクトに対して実行したいクエリ。オブジェクトが検索に一致する場合、nested
クエリはルート親ドキュメントを返します。
完全なパスを含むドット表記を使用してネストされたフィールドを検索できます。例えばobj1.name
。
マルチレベルのネストは自動的にサポートされ、検出され、関連するネストレベルに自動的に一致する内部ネストクエリが生成されます。別のネストされたクエリ内に存在する場合は、ルートではなく、ネストされたレベルに一致します。
例についてはマルチレベルネストクエリを参照してください。 score_mode
- (オプション、文字列) 一致する子オブジェクトのスコアがルート親ドキュメントの関連スコアにどのように影響するかを示します。有効な値は次のとおりです:
avg
(デフォルト)- 一致するすべての子オブジェクトの平均関連スコアを使用します。
max
- 一致するすべての子オブジェクトの最高関連スコアを使用します。
min
- 一致するすべての子オブジェクトの最低関連スコアを使用します。
none
- 一致する子オブジェクトの関連スコアを使用しません。クエリは親ドキュメントに
0
のスコアを割り当てます。 sum
- 一致するすべての子オブジェクトの関連スコアを合計します。
ignore_unmapped
- (オプション、ブール値) マッピングされていない
path
を無視し、エラーの代わりにドキュメントを返さないかどうかを示します。デフォルトはfalse
です。false
の場合、Elasticsearchはpath
がマッピングされていないフィールドである場合にエラーを返します。
このパラメータを使用して、path
フィールドを含まない可能性のある複数のインデックスをクエリできます。
ノート
スクリプトクエリのコンテキスト
ネストされたクエリ内でscript
クエリを実行すると、親またはルートドキュメントではなく、ネストされたドキュメントからのdoc値にのみアクセスできます。
マルチレベルネストクエリ
マルチレベルネストクエリがどのように機能するかを確認するには、まずネストされたフィールドを持つインデックスが必要です。次のリクエストは、ネストされたmake
およびmodel
フィールドを持つdrivers
インデックスのマッピングを定義します。
Python
resp = client.indices.create(
index="drivers",
mappings={
"properties": {
"driver": {
"type": "nested",
"properties": {
"last_name": {
"type": "text"
},
"vehicle": {
"type": "nested",
"properties": {
"make": {
"type": "text"
},
"model": {
"type": "text"
}
}
}
}
}
}
},
)
print(resp)
Ruby
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
Go
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)
Js
const response = await client.indices.create({
index: "drivers",
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"
}
}
}
}
}
}
}
}
次に、drivers
インデックスにいくつかのドキュメントをインデックスします。
Php
$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);
Python
resp = client.index(
index="drivers",
id="1",
document={
"driver": {
"last_name": "McQueen",
"vehicle": [
{
"make": "Powell Motors",
"model": "Canyonero"
},
{
"make": "Miller-Meteor",
"model": "Ecto-1"
}
]
}
},
)
print(resp)
resp1 = client.index(
index="drivers",
id="2",
refresh=True,
document={
"driver": {
"last_name": "Hudson",
"vehicle": [
{
"make": "Mifune",
"model": "Mach Five"
},
{
"make": "Miller-Meteor",
"model": "Ecto-1"
}
]
}
},
)
print(resp1)
Ruby
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
Go
{
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)
}
Js
const response = await client.index({
index: "drivers",
id: 1,
document: {
driver: {
last_name: "McQueen",
vehicle: [
{
make: "Powell Motors",
model: "Canyonero",
},
{
make: "Miller-Meteor",
model: "Ecto-1",
},
],
},
},
});
console.log(response);
const response1 = await client.index({
index: "drivers",
id: 2,
refresh: "true",
document: {
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
フィールドに基づいてドキュメントを一致させるためにマルチレベルネストクエリを使用できます。
Python
resp = client.search(
index="drivers",
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)
Ruby
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
Go
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)
Js
const response = await client.search({
index: "drivers",
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" } }
]
}
}
}
}
}
}
}
コンソール-結果
{
"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句とネストクエリ
[`````inner_hits`````](/read/elasticsearch-8-15/4bfa3660dc6a8b2b.md)パラメータを使用して、`````nested`````クエリに一致したネストされたオブジェクトを確認できます。
例えば、次の検索は、外部`````nested`````クエリと内部`````must_not`````句を使用します。
#### Python
``````python
resp = client.indices.create(
index="my-index",
mappings={
"properties": {
"comments": {
"type": "nested"
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index",
id="1",
refresh=True,
document={
"comments": [
{
"author": "kimchy"
}
]
},
)
print(resp1)
resp2 = client.index(
index="my-index",
id="2",
refresh=True,
document={
"comments": [
{
"author": "kimchy"
},
{
"author": "nik9000"
}
]
},
)
print(resp2)
resp3 = client.index(
index="my-index",
id="3",
refresh=True,
document={
"comments": [
{
"author": "nik9000"
}
]
},
)
print(resp3)
resp4 = client.search(
index="my-index",
query={
"nested": {
"path": "comments",
"query": {
"bool": {
"must_not": [
{
"term": {
"comments.author": "nik9000"
}
}
]
}
}
}
},
)
print(resp4)
`
Ruby
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
Js
const response = await client.indices.create({
index: "my-index",
mappings: {
properties: {
comments: {
type: "nested",
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index",
id: 1,
refresh: "true",
document: {
comments: [
{
author: "kimchy",
},
],
},
});
console.log(response1);
const response2 = await client.index({
index: "my-index",
id: 2,
refresh: "true",
document: {
comments: [
{
author: "kimchy",
},
{
author: "nik9000",
},
],
},
});
console.log(response2);
const response3 = await client.index({
index: "my-index",
id: 3,
refresh: "true",
document: {
comments: [
{
author: "nik9000",
},
],
},
});
console.log(response3);
const response4 = await client.search({
index: "my-index",
query: {
nested: {
path: "comments",
query: {
bool: {
must_not: [
{
term: {
"comments.author": "nik9000",
},
},
],
},
},
},
},
});
console.log(response4);
コンソール
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"
}
]
}
}
]
}
}
このネストされたオブジェクトはクエリに一致します。その結果、検索はオブジェクトの親ドキュメントをヒットとして返します。 | |
このネストされたオブジェクトはクエリに一致しません。同じドキュメント内の別のネストされたオブジェクトがクエリに一致するため、検索は依然として親ドキュメントをヒットとして返します。 |
#### Python
``````python
resp = client.search(
index="my-index",
query={
"bool": {
"must_not": [
{
"nested": {
"path": "comments",
"query": {
"term": {
"comments.author": "nik9000"
}
}
}
}
]
}
},
)
print(resp)
`
Ruby
response = client.search(
index: 'my-index',
body: {
query: {
bool: {
must_not: [
{
nested: {
path: 'comments',
query: {
term: {
'comments.author' => 'nik9000'
}
}
}
}
]
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index",
query: {
bool: {
must_not: [
{
nested: {
path: "comments",
query: {
term: {
"comments.author": "nik9000",
},
},
},
},
],
},
},
});
console.log(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"
}
]
}
}
]
}
}