通过访问者模式,可以对所有或者特定的属性进行应用转换。
.AutoMap() 方法内部实现了 Visitor Pattern ,默认访问者 NoopPropertyVisitor 不执行任何操作,并允许你实现自己的访问方法。
常规使用:
示例:自定义一个访问者,以禁用数字和布尔类型的 doc 值:
1 2 3 4 5 6 7 8 9 10 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 ; } }
定义一个访问者:最简单的是实现一个 NoopPropertyVisitor 派生类,并重写 Visit 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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 ; } }
使用上面自定义的属性访问者来映射一个索引
1 2 3 var createIndexResponse = client.Indices.Create("myindex" , c => c .Map<Employee>(m => m.AutoMap(new DisableDocValuesPropertyVisitor())) );
结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 { "myindex" : { "mappings" : { "properties" : { "birthday" : { "type" : "date" } , "employees" : { "type" : "object" } , "firstName" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 256 } } } , "hours" : { "type" : "long" , "doc_values" : false } , "isManager" : { "type" : "boolean" , "doc_values" : false } , "lastName" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 256 } } } , "salary" : { "type" : "integer" , "doc_values" : false } } } } }
在 PropertyInfo 上的应用
示例:将所有 CLR 类型映射成 ES 的 text 数据类型
自定义 EverythingIsATextPropertyVisitor
1 2 3 4 public class EverythingIsATextPropertyVisitor : NoopPropertyVisitor { public override IProperty Visit (PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute ) => new TextProperty(); }
使用:
1 2 3 var createIndexResponse = client.Indices.Create("myindex" , c => c .Map<Employee>(m => m.AutoMap(new EverythingIsATextPropertyVisitor())) );
结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 { "myindex" : { "mappings" : { "properties" : { "birthday" : { "type" : "text" } , "employees" : { "type" : "text" } , "firstName" : { "type" : "text" } , "hours" : { "type" : "text" } , "isManager" : { "type" : "text" } , "lastName" : { "type" : "text" } , "salary" : { "type" : "text" } } } } }
跳过某些属性
示例:仅包含派生类中的属性(忽略父类中的属性,这里为 SortedDictionary)
1 2 3 4 5 6 7 8 9 10 11 12 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); } }
创建索引:
1 2 3 var createIndexResponse = client.Indices.Create("myindex" , c => c .Map<DictionaryDocument>(m => m.AutoMap(new IgnoreInheritedPropertiesVisitor<DictionaryDocument>())) );
结果如下:
1 2 3 4 5 6 7 8 9 10 11 { "myindex" : { "mappings" : { "properties" : { "id" : { "type" : "integer" } } } } }