fields
異なる目的のために同じフィールドを異なる方法でインデックスすることはしばしば有用です。これが multi-fields の目的です。たとえば、string
フィールドは、全文検索のために text
フィールドとしてマッピングされ、ソートや集計のために keyword
フィールドとしてマッピングされる可能性があります。
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index-000001",
id="1",
document={
"city": "New York"
},
)
print(resp1)
resp2 = client.index(
index="my-index-000001",
id="2",
document={
"city": "York"
},
)
print(resp2)
resp3 = client.search(
index="my-index-000001",
query={
"match": {
"city": "york"
}
},
sort={
"city.raw": "asc"
},
aggs={
"Cities": {
"terms": {
"field": "city.raw"
}
}
},
)
print(resp3)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
properties: {
city: {
type: 'text',
fields: {
raw: {
type: 'keyword'
}
}
}
}
}
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 1,
body: {
city: 'New York'
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 2,
body: {
city: 'York'
}
)
puts response
response = client.search(
index: 'my-index-000001',
body: {
query: {
match: {
city: 'york'
}
},
sort: {
'city.raw' => 'asc'
},
aggregations: {
"Cities": {
terms: {
field: 'city.raw'
}
}
}
}
)
puts response
Go
{
res, err := es.Indices.Create(
"my-index-000001",
es.Indices.Create.WithBody(strings.NewReader(`{
"mappings": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}`)),
)
fmt.Println(res, err)
}
{
res, err := es.Index(
"my-index-000001",
strings.NewReader(`{
"city": "New York"
}`),
es.Index.WithDocumentID("1"),
es.Index.WithPretty(),
)
fmt.Println(res, err)
}
{
res, err := es.Index(
"my-index-000001",
strings.NewReader(`{
"city": "York"
}`),
es.Index.WithDocumentID("2"),
es.Index.WithPretty(),
)
fmt.Println(res, err)
}
{
res, err := es.Search(
es.Search.WithIndex("my-index-000001"),
es.Search.WithBody(strings.NewReader(`{
"query": {
"match": {
"city": "york"
}
},
"sort": {
"city.raw": "asc"
},
"aggs": {
"Cities": {
"terms": {
"field": "city.raw"
}
}
}
}`)),
es.Search.WithPretty(),
)
fmt.Println(res, err)
}
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
properties: {
city: {
type: "text",
fields: {
raw: {
type: "keyword",
},
},
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index-000001",
id: 1,
document: {
city: "New York",
},
});
console.log(response1);
const response2 = await client.index({
index: "my-index-000001",
id: 2,
document: {
city: "York",
},
});
console.log(response2);
const response3 = await client.search({
index: "my-index-000001",
query: {
match: {
city: "york",
},
},
sort: {
"city.raw": "asc",
},
aggs: {
Cities: {
terms: {
field: "city.raw",
},
},
},
});
console.log(response3);
Console
PUT my-index-000001
{
"mappings": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
PUT my-index-000001/_doc/1
{
"city": "New York"
}
PUT my-index-000001/_doc/2
{
"city": "York"
}
GET my-index-000001/_search
{
"query": {
"match": {
"city": "york"
}
},
"sort": {
"city.raw": "asc"
},
"aggs": {
"Cities": {
"terms": {
"field": "city.raw"
}
}
}
}
city.raw フィールドは keyword バージョンの city フィールドです。 |
|
city フィールドは全文検索に使用できます。 |
|
city.raw フィールドはソートと集計に使用できます。 |
既存のフィールドに multi-fields を追加するには、update mapping API を使用できます。
multi-field を追加するときにインデックス(またはデータストリーム)にドキュメントが含まれている場合、それらのドキュメントには新しい multi-field の値がありません。新しい multi-field を update by query API で埋めることができます。
multi-field マッピングは親フィールドのマッピングとは完全に独立しています。multi-field は親フィールドからマッピングオプションを継承しません。multi-fields は元の _source
フィールドを変更しません。
Multi-fields with multiple analyzers
multi-fields の別の使用例は、同じフィールドを異なる方法で分析して関連性を高めることです。たとえば、テキストを単語に分割する standard
analyzer でフィールドをインデックスし、さらに単語をそのルート形に変換する english
analyzer でインデックスすることができます。
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"properties": {
"text": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index-000001",
id="1",
document={
"text": "quick brown fox"
},
)
print(resp1)
resp2 = client.index(
index="my-index-000001",
id="2",
document={
"text": "quick brown foxes"
},
)
print(resp2)
resp3 = client.search(
index="my-index-000001",
query={
"multi_match": {
"query": "quick brown foxes",
"fields": [
"text",
"text.english"
],
"type": "most_fields"
}
},
)
print(resp3)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
properties: {
text: {
type: 'text',
fields: {
english: {
type: 'text',
analyzer: 'english'
}
}
}
}
}
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 1,
body: {
text: 'quick brown fox'
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 2,
body: {
text: 'quick brown foxes'
}
)
puts response
response = client.search(
index: 'my-index-000001',
body: {
query: {
multi_match: {
query: 'quick brown foxes',
fields: [
'text',
'text.english'
],
type: 'most_fields'
}
}
}
)
puts response
Go
{
res, err := es.Indices.Create(
"my-index-000001",
es.Indices.Create.WithBody(strings.NewReader(`{
"mappings": {
"properties": {
"text": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}`)),
)
fmt.Println(res, err)
}
{
res, err := es.Index(
"my-index-000001",
strings.NewReader(`{
"text": "quick brown fox"
} `),
es.Index.WithDocumentID("1"),
es.Index.WithPretty(),
)
fmt.Println(res, err)
}
{
res, err := es.Index(
"my-index-000001",
strings.NewReader(`{
"text": "quick brown foxes"
} `),
es.Index.WithDocumentID("2"),
es.Index.WithPretty(),
)
fmt.Println(res, err)
}
{
res, err := es.Search(
es.Search.WithIndex("my-index-000001"),
es.Search.WithBody(strings.NewReader(`{
"query": {
"multi_match": {
"query": "quick brown foxes",
"fields": [
"text",
"text.english"
],
"type": "most_fields"
}
}
}`)),
es.Search.WithPretty(),
)
fmt.Println(res, err)
}
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
properties: {
text: {
type: "text",
fields: {
english: {
type: "text",
analyzer: "english",
},
},
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index-000001",
id: 1,
document: {
text: "quick brown fox",
},
});
console.log(response1);
const response2 = await client.index({
index: "my-index-000001",
id: 2,
document: {
text: "quick brown foxes",
},
});
console.log(response2);
const response3 = await client.search({
index: "my-index-000001",
query: {
multi_match: {
query: "quick brown foxes",
fields: ["text", "text.english"],
type: "most_fields",
},
},
});
console.log(response3);
Console
PUT my-index-000001
{
"mappings": {
"properties": {
"text": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}
PUT my-index-000001/_doc/1
{ "text": "quick brown fox" }
PUT my-index-000001/_doc/2
{ "text": "quick brown foxes" }
GET my-index-000001/_search
{
"query": {
"multi_match": {
"query": "quick brown foxes",
"fields": [
"text",
"text.english"
],
"type": "most_fields"
}
}
}
text フィールドは standard analyzer を使用します。 |
|
text.english フィールドは english analyzer を使用します。 |
|
fox で1つのドキュメントを、foxes で別のドキュメントをインデックスします。 |
|
text と text.english フィールドの両方をクエリし、スコアを組み合わせます。 |
text
フィールドは最初のドキュメントに fox
を含み、2番目のドキュメントに foxes
を含みます。text.english
フィールドは両方のドキュメントに fox
を含みます。なぜなら foxes
が fox
にステムされるからです。
クエリ文字列は standard
analyzer によって text
フィールドのために分析され、english
analyzer によって text.english
フィールドのために分析されます。ステムされたフィールドは、foxes
のクエリが fox
のみを含むドキュメントにも一致することを可能にします。これにより、できるだけ多くのドキュメントに一致させることができます。また、非ステムの text
フィールドをクエリすることで、foxes
に正確に一致するドキュメントの関連性スコアを向上させます。