At the time of this writing, Nest does not offer a way to map a property in your class to multiple fields when matching documents using built-in attributes. However, it does provide the tools you need for something, with your mappings, which you could do if you yourself wrote JSON.
Here is the solution I put together for my needs. It should not be difficult to use as a starting point for everything you need to do.
Firstly, here is a display example that I want to generate
{ "product":{ "properties":{ "name":{ "type":"string", "index":"not_analyzed", "fields":{ "standard":{ "type":"string", "analyzer":"standard" } } } } } }
The product document will have a name field that is indexed but not parsed, and a name.standard field that uses a standard parser.
The C # class I create looks like this:
[ElasticsearchType] public class Product { [WantsStandardAnalysisField] public string Name { get; set; } }
Note the WantsStandardAnalysisField attribute. This is a custom attribute added without special properties. Literally simple:
public class WantsStandardAnalysisField : Attribute {}
If I used AutoMap as-is, my custom attribute would be ignored and I would get a mapping to the name field, but not name.standard . Fortunately, AutoMap accepts an instance of IPropertyVisitor . A base class called NoopPropertyVisitor implements the interface and does nothing, so you can subclass it and override only the methods you need. When you use the property visitor using AutoMap, it will create a document mapping for you, but it will give you the opportunity to change it before it is submitted to Elastic Search. All we need to do is find the properties marked with our custom attribute and add a field to them.
Here is an example that does this:
public class ProductPropertyVisitor : NoopPropertyVisitor { public override void Visit(IStringProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { base.Visit(type, propertyInfo, attribute); var wsaf = propertyInfo.GetCustomAttribute<WantsStandardAnalysisField>(); if (wsaf != null) { type.Index = FieldIndexOption.NotAnalyzed; type.Fields = new Properties { { "standard", new StringProperty { Index = FieldIndexOption.Analyzed, Analyzer = "standard" } } }; } } }
As you can see, we can do whatever we want with the generated property, including disabling the analysis for the main property and adding a new field with its own settings. For fun, you can add a couple of properties to a custom attribute to specify the name of the field and the analyzer. You can even change the code to see if the attribute has been added multiple times, allowing you to add as many fields as you want.
If you must run this using any method that generates a mapping using AutoMap, for example:
new TypeMappingDescriptor<Product>().AutoMap(new ProductPropertyVisitor())
You will get the required multi-field mapping. Now you can configure the mappings for your heart content. Enjoy it!