diff --git a/docs/client-concepts/high-level/mapping/visitor-pattern-mapping.asciidoc b/docs/client-concepts/high-level/mapping/visitor-pattern-mapping.asciidoc index 1102e78b394..dd791430f6a 100644 --- a/docs/client-concepts/high-level/mapping/visitor-pattern-mapping.asciidoc +++ b/docs/client-concepts/high-level/mapping/visitor-pattern-mapping.asciidoc @@ -17,8 +17,8 @@ please modify the original csharp file found at the link and submit the PR with It is also possible to apply a transformation on all or specific properties. -`.AutoMap()` internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. -The default visitor, `NoopPropertyVisitor`, does nothing and acts as a blank canvas for you +`.AutoMap()` internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[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 @@ -134,7 +134,7 @@ var expected = new ==== Visiting on PropertyInfo You can even take the visitor approach a step further, and instead of visiting on `IProperty` types, visit -directly on your POCO reflected `PropertyInfo` properties. +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`). @@ -184,3 +184,43 @@ var descriptor = new CreateIndexDescriptor("myindex") } ---- +==== Skip properties + +Through implementing `SkipProperty` on the visitor you can prevent certain properties from being mapped + +[source,csharp] +---- +public class DictionaryDocument : SortedDictionary +{ + public int Id { get; set; } +} + +public class IgnoreInheritedPropertiesVisitor : NoopPropertyVisitor +{ + public override bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + return propertyInfo?.DeclaringType != typeof(T); + } +} + +var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(new IgnoreInheritedPropertiesVisitor())) + ); +---- + +[source,javascript] +---- +{ + "mappings": { + "dictionarydocument": { + "properties": { + "id": { + "type": "integer" + } + } + } + } +} +---- + diff --git a/src/Nest/Mapping/Visitor/IPropertyVisitor.cs b/src/Nest/Mapping/Visitor/IPropertyVisitor.cs index c7a4471f5b2..3a9931d2f67 100644 --- a/src/Nest/Mapping/Visitor/IPropertyVisitor.cs +++ b/src/Nest/Mapping/Visitor/IPropertyVisitor.cs @@ -25,5 +25,6 @@ public interface IPropertyVisitor void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute); IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute); + bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute); } } diff --git a/src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs b/src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs index 1bced83334a..73c1bdb1923 100644 --- a/src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs +++ b/src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs @@ -68,62 +68,50 @@ public virtual void Visit(IStringProperty type, PropertyInfo propertyInfo, Elast public virtual IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => null; + public virtual bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => false; + public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { - var nestedType = type as INestedProperty; - if (nestedType != null) + if (type is INestedProperty nestedType) Visit(nestedType, propertyInfo, attribute); - var objectType = type as IObjectProperty; - if (objectType != null) + if (type is IObjectProperty objectType) Visit(objectType, propertyInfo, attribute); - var binaryType = type as IBinaryProperty; - if (binaryType != null) + if (type is IBinaryProperty binaryType) Visit(binaryType, propertyInfo, attribute); - var booleanType = type as IBooleanProperty; - if (booleanType != null) + if (type is IBooleanProperty booleanType) Visit(booleanType, propertyInfo, attribute); - var dateType = type as IDateProperty; - if (dateType != null) + if (type is IDateProperty dateType) Visit(dateType, propertyInfo, attribute); - var numberType = type as INumberProperty; - if (numberType != null) + if (type is INumberProperty numberType) Visit(numberType, propertyInfo, attribute); - var textType = type as ITextProperty; - if (textType != null) + if (type is ITextProperty textType) Visit(textType, propertyInfo, attribute); - var keywordType = type as IKeywordProperty; - if (keywordType != null) + if (type is IKeywordProperty keywordType) Visit(keywordType, propertyInfo, attribute); - var geoShapeType = type as IGeoShapeProperty; - if (geoShapeType != null) + if (type is IGeoShapeProperty geoShapeType) Visit(geoShapeType, propertyInfo, attribute); - var geoPointType = type as IGeoPointProperty; - if (geoPointType != null) + if (type is IGeoPointProperty geoPointType) Visit(geoPointType, propertyInfo, attribute); - var completionType = type as ICompletionProperty; - if (completionType != null) + if (type is ICompletionProperty completionType) Visit(completionType, propertyInfo, attribute); - var ipType = type as IIpProperty; - if (ipType != null) + if (type is IIpProperty ipType) Visit(ipType, propertyInfo, attribute); - var murmurType = type as IMurmur3HashProperty; - if (murmurType != null) + if (type is IMurmur3HashProperty murmurType) Visit(murmurType, propertyInfo, attribute); - var tokenCountType = type as ITokenCountProperty; - if (tokenCountType != null) + if (type is ITokenCountProperty tokenCountType) Visit(tokenCountType, propertyInfo, attribute); } } diff --git a/src/Nest/Mapping/Visitor/PropertyWalker.cs b/src/Nest/Mapping/Visitor/PropertyWalker.cs index 9ff5afaf0e1..a17eff8ec02 100644 --- a/src/Nest/Mapping/Visitor/PropertyWalker.cs +++ b/src/Nest/Mapping/Visitor/PropertyWalker.cs @@ -39,8 +39,8 @@ public IProperties GetProperties(ConcurrentDictionary seenTypes = nul foreach (var propertyInfo in _type.AllPropertiesCached()) { var attribute = ElasticsearchPropertyAttributeBase.From(propertyInfo); - if (attribute != null && attribute.Ignore) - continue; + if (attribute != null && attribute.Ignore) continue; + if (_visitor.SkipProperty(propertyInfo, attribute)) continue; var property = GetProperty(propertyInfo, attribute); if (property is IPropertyWithClrOrigin withCLrOrigin) diff --git a/src/Tests/ClientConcepts/HighLevel/Mapping/VisitorPatternMapping.doc.cs b/src/Tests/ClientConcepts/HighLevel/Mapping/VisitorPatternMapping.doc.cs index 38bd36a2f21..9c432d20c80 100644 --- a/src/Tests/ClientConcepts/HighLevel/Mapping/VisitorPatternMapping.doc.cs +++ b/src/Tests/ClientConcepts/HighLevel/Mapping/VisitorPatternMapping.doc.cs @@ -12,8 +12,8 @@ namespace Tests.ClientConcepts.HighLevel.Mapping * === Applying conventions through the Visitor pattern * It is also possible to apply a transformation on all or specific properties. * - * `.AutoMap()` internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[visitor pattern]. - * The default visitor, `NoopPropertyVisitor`, does nothing and acts as a blank canvas for you + * `.AutoMap()` internally implements the https://en.wikipedia.org/wiki/Visitor_pattern[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 @@ -121,8 +121,8 @@ public void UsingACustomPropertyVisitor() /** * ==== Visiting on PropertyInfo * You can even take the visitor approach a step further, and instead of visiting on `IProperty` types, visit - * directly on your POCO reflected `PropertyInfo` properties. - * + * 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 @@ -172,7 +172,7 @@ public void UsingACustomPropertyVisitorOnPropertyInfo() salary = new { type = "text" - }, + }, hours = new { type = "text" @@ -182,6 +182,55 @@ public void UsingACustomPropertyVisitorOnPropertyInfo() } }; + // hide + Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); + } + /** + * ==== Skip properties + * + * Through implementing `SkipProperty` on the visitor you can prevent certain properties from being mapped + * + */ + public class DictionaryDocument : SortedDictionary + { + public int Id { get; set; } + } + + public class IgnoreInheritedPropertiesVisitor : NoopPropertyVisitor + { + public override bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) + { + return propertyInfo?.DeclaringType != typeof(T); + } + } + + [U] public void HidesInheritedMembers() + { + var descriptor = new CreateIndexDescriptor("myindex") + .Mappings(ms => ms + .Map(m => m.AutoMap(new IgnoreInheritedPropertiesVisitor())) + ); + + /** + */ + // json + var expected = new + { + mappings = new + { + dictionarydocument = new + { + properties = new + { + id = new + { + type = "integer" + } + } + } + } + }; + // hide Expect(expected).WhenSerializing((ICreateIndexRequest) descriptor); }