fields
editfields
editIt is often useful to index the same field in different ways for different
purposes. This is the purpose of multi-fields. For instance, a string
field could be mapped as a text field for full-text
search, and as a keyword field for sorting or aggregations:
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)
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
{
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)
}
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);
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"
}
}
}
}
|
The |
|
|
The |
|
|
The |
You can add multi-fields to an existing field using the update mapping API.
If an index (or data stream) contains documents when you add a multi-field, those documents will not have values for the new multi-field. You can populate the new multi-field with the update by query API.
A multi-field mapping is completely separate from the parent field’s mapping. A
multi-field doesn’t inherit any mapping options from its parent field.
Multi-fields don’t change the original _source field.
Multi-fields with multiple analyzers
editAnother use case of multi-fields is to analyze the same field in different
ways for better relevance. For instance we could index a field with the
standard analyzer which breaks text up into
words, and again with the english analyzer
which stems words into their root form:
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)
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
{
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)
}
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);
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"
}
}
}
|
The |
|
|
The |
|
|
Index two documents, one with |
|
|
Query both the |
The text field contains the term fox in the first document and foxes in
the second document. The text.english field contains fox for both
documents, because foxes is stemmed to fox.
The query string is also analyzed by the standard analyzer for the text
field, and by the english analyzer for the text.english field. The
stemmed field allows a query for foxes to also match the document containing
just fox. This allows us to match as many documents as possible. By also
querying the unstemmed text field, we improve the relevance score of the
document which matches foxes exactly.