Multi fields
editMulti fields
editIt is often useful to index the same field in Elasticsearch in different ways, to
serve different purposes, for example, mapping a POCO string property as a
text datatype for full text search as well as mapping as a keyword datatype for
structured search, sorting and aggregations. Another example is mapping a POCO string
property to use different analyzers, to serve different full text search needs.
Let’s look at a few examples. for each, we use the following simple POCO
public class Person
{
public string Name { get; set; }
}
Default mapping for String properties
editWhen using Auto Mapping, the inferred mapping for a string
POCO type is a text datatype with multi fields including a keyword sub field
var createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<Person>(m => m
.AutoMap()
)
);
This results in the following JSON request
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
This is useful because the property can be used for both full text search as well as for structured search, sorting and aggregations
var searchResponse = _client.Search<Person>(s => s
.Query(q => q
.Match(m => m
.Field(f => f.Name)
.Query("Russ")
)
)
.Sort(ss => ss
.Descending(f => f.Name.Suffix("keyword"))
)
.Aggregations(a => a
.Terms("peoples_names", t => t
.Field(f => f.Name.Suffix("keyword"))
)
)
);
{
"query": {
"match": {
"name": {
"query": "Russ"
}
}
},
"sort": [
{
"name.keyword": {
"order": "desc"
}
}
],
"aggs": {
"peoples_names": {
"terms": {
"field": "name.keyword"
}
}
}
}
Multi fields do not change the original _source field in Elasticsearch; they affect only how
a field is indexed.
New multi fields can be added to existing fields using the Put Mapping API.
Creating Multi fields
editMulti fields can be created on a mapping using the .Fields() method within a field mapping
var createIndexResponse = _client.Indices.Create("myindex", c => c
.Map<Person>(m => m
.Properties(p => p
.Text(t => t
.Name(n => n.Name)
.Fields(ff => ff
.Text(tt => tt
.Name("stop")
.Analyzer("stop")
)
.Text(tt => tt
.Name("shingles")
.Analyzer("name_shingles")
)
.Keyword(k => k
.Name("keyword")
.IgnoreAbove(256)
)
)
)
)
)
);
|
Use the stop analyzer on this sub field |
|
|
Use a custom analyzer named "named_shingles" that is configured in the index |
|
|
Index as not analyzed |
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"stop": {
"type": "text",
"analyzer": "stop"
},
"shingles": {
"type": "text",
"analyzer": "name_shingles"
},
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}