WARNING: Version 5.x has passed its EOL date.
This documentation is no longer being maintained and may be removed. If you are running this version, we strongly advise you to upgrade. For the latest information, see the current release documentation.
Applying conventions through the Visitor pattern
editApplying conventions through the Visitor pattern
editIt is also possible to apply a transformation on all or specific properties.
.AutoMap()
internally implements the visitor pattern.
The default visitor, NoopPropertyVisitor
, does nothing and acts as a blank canvas for you
to implement your own visiting methods.
For instance, let’s create a custom visitor that disables doc values for numeric and boolean types (Not really a good idea in practice, but let’s do it anyway for the sake of a clear example.)
Using the following two POCOs as in previous examples,
public class Company { public string Name { get; set; } public List<Employee> Employees { get; set; } } public class Employee { public string FirstName { get; set; } public string LastName { get; set; } public int Salary { get; set; } public DateTime Birthday { get; set; } public bool IsManager { get; set; } public List<Employee> Employees { get; set; } public TimeSpan Hours { get; set; } }
We first define a visitor; it’s easiest to inherit from NoopPropertyVisitor
and override
the Visit
methods to implement your conventions
public class DisableDocValuesPropertyVisitor : NoopPropertyVisitor { public override void Visit( INumberProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { type.DocValues = false; } public override void Visit( IBooleanProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { type.DocValues = false; } }
Override the |
|
Similarily, override the |
Now we can pass an instance of our custom visitor to .AutoMap()
var createIndexResponse = client.CreateIndex("myindex", c => c .Mappings(ms => ms .Map<Employee>(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) ) );
and any time the client maps a property of the POCO (Employee in this example) as a number (INumberProperty) or boolean (IBooleanProperty),
it will apply the transformation defined in each Visit()
call respectively, which in this example
disables doc_values.
{ "mappings": { "employee": { "properties": { "birthday": { "type": "date" }, "employees": { "properties": {}, "type": "object" }, "firstName": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "isManager": { "doc_values": false, "type": "boolean" }, "lastName": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "salary": { "doc_values": false, "type": "integer" }, "hours": { "doc_values": false, "type": "long" } } } } }
Visiting on PropertyInfo
editYou can even take the visitor approach a step further, and instead of visiting on IProperty
types, visit
directly on your POCO reflected PropertyInfo
properties.
As an example, let’s create a visitor that maps all CLR types to an Elasticsearch text datatype (ITextProperty
).
public class EverythingIsATextPropertyVisitor : NoopPropertyVisitor { public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => new TextProperty(); } var createIndexResponse = client.CreateIndex("myindex", c => c .Mappings(ms => ms .Map<Employee>(m => m.AutoMap(new EverythingIsATextPropertyVisitor())) ) );
{ "mappings": { "employee": { "properties": { "birthday": { "type": "text" }, "employees": { "type": "text" }, "firstName": { "type": "text" }, "isManager": { "type": "text" }, "lastName": { "type": "text" }, "salary": { "type": "text" }, "hours": { "type": "text" } } } } }
Skip properties
editThrough implementing SkipProperty
on the visitor, you can prevent certain properties from being mapped.
In this example, we skip the inherited properties of the type from which DictionaryDocument
is derived
public class DictionaryDocument : SortedDictionary<string, dynamic> { public int Id { get; set; } } public class IgnoreInheritedPropertiesVisitor<T> : NoopPropertyVisitor { public override bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { return propertyInfo?.DeclaringType != typeof(T); } } var createIndexResponse = client.CreateIndex("myindex", c => c .Mappings(ms => ms .Map<DictionaryDocument>(m => m.AutoMap(new IgnoreInheritedPropertiesVisitor<DictionaryDocument>())) ) );
{ "mappings": { "dictionarydocument": { "properties": { "id": { "type": "integer" } } } } }