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 } } } } } }