diff --git a/src/Nest/CommonAbstractions/ConnectionSettings/ClrPropertyMapping.cs b/src/Nest/CommonAbstractions/ConnectionSettings/ClrPropertyMapping.cs new file mode 100644 index 00000000000..4db5de2a669 --- /dev/null +++ b/src/Nest/CommonAbstractions/ConnectionSettings/ClrPropertyMapping.cs @@ -0,0 +1,43 @@ +using System; +using System.Linq.Expressions; + +namespace Nest +{ + public abstract class ClrPropertyMappingBase : IClrPropertyMapping + where TDocument : class + { + Expression> IClrPropertyMapping.Property { get; set; } + bool IClrPropertyMapping.Ignore { get; set; } + string IClrPropertyMapping.NewName { get; set; } + + protected IClrPropertyMapping Self => this; + + protected ClrPropertyMappingBase(Expression> property) => Self.Property = property; + + IPropertyMapping IClrPropertyMapping.ToPropertyMapping() => Self.Ignore + ? PropertyMapping.Ignored + : new PropertyMapping {Name = Self.NewName}; + } + + public interface IClrPropertyMapping where TDocument : class + { + Expression> Property { get; set; } + bool Ignore { get; set; } + string NewName { get; set; } + IPropertyMapping ToPropertyMapping(); + } + + public class IgnoreClrPropertyMapping : ClrPropertyMappingBase where TDocument : class + { + public IgnoreClrPropertyMapping(Expression> property) : base(property) => Self.Ignore = true; + } + + public class RenameClrPropertyMapping : ClrPropertyMappingBase where TDocument : class + { + public RenameClrPropertyMapping(Expression> property, string newName) : base(property) + { + newName.ThrowIfNull(nameof(newName)); + Self.NewName = newName; + } + } +} diff --git a/src/Nest/CommonAbstractions/ConnectionSettings/ClrTypeMapping.cs b/src/Nest/CommonAbstractions/ConnectionSettings/ClrTypeMapping.cs index 537d77fc502..f11ec67604d 100644 --- a/src/Nest/CommonAbstractions/ConnectionSettings/ClrTypeMapping.cs +++ b/src/Nest/CommonAbstractions/ConnectionSettings/ClrTypeMapping.cs @@ -1,155 +1,149 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using Elasticsearch.Net; namespace Nest { - public interface IClrTypeMapping where T : class + public interface IClrTypeMapping { - Type Type { get; } + /// + /// The CLR type the mapping relates to + /// + Type ClrType { get; } /// - /// When specified dictates the default Elasticsearch index name for + /// The default Elasticsearch index name for /// string IndexName { get; set; } /// - /// When specified dictates the default Elasticsearch type name for + /// The default Elasticsearch type name for /// string TypeName { get; set; } /// - /// When specified dictates the relation name for to resolve to. + /// The relation name for to resolve to. /// string RelationName { get; set; } + } + public interface IClrTypeMapping : IClrTypeMapping where TDocument : class + { /// - /// Allows you to set a default Id property on that NEST will evaluate + /// Set a default Id property on CLR type that NEST will evaluate /// - Expression> IdProperty { get; set; } + Expression> IdProperty { get; set; } /// - /// When specified allows you to ignore or rename certain properties of clr type + /// Ignore or rename certain properties of CLR type /// - IList> Properties { get; set; } + IList> Properties { get; set; } } - public class ClrTypeMapping : IClrTypeMapping where T : class + public class ClrTypeMapping : IClrTypeMapping { - public Type Type { get; } = typeof (T); - /// - /// When specified dictates the default Elasticsearch index name for + /// Initializes a new instance of /// + public ClrTypeMapping(Type type) => ClrType = type; + + /// + public Type ClrType { get; } + + /// public string IndexName { get; set; } - /// - /// When specified dictates the default Elasticsearch type name for - /// + /// public string TypeName { get; set; } - /// - /// When specified dictates the relation name for to resolve to. - /// + /// public string RelationName { get; set; } - /// - /// Allows you to set a default Id property on that NEST will evaluate - /// - public Expression> IdProperty { get; set; } + } + public class ClrTypeMapping : ClrTypeMapping, IClrTypeMapping where TDocument : class + { + public ClrTypeMapping() : base(typeof(TDocument)) { } + + /// + public Expression> IdProperty { get; set; } - public IList> Properties { get; set; } + /// + public IList> Properties { get; set; } } - public class ClrTypeMappingDescriptor : DescriptorBase,IClrTypeMapping> , IClrTypeMapping - where T : class + public class ClrTypeMappingDescriptor : DescriptorBase , IClrTypeMapping { - Type IClrTypeMapping.Type { get; } = typeof (T); - string IClrTypeMapping.IndexName { get; set; } - string IClrTypeMapping.TypeName { get; set; } - string IClrTypeMapping.RelationName { get; set; } - Expression> IClrTypeMapping.IdProperty { get; set; } - IList> IClrTypeMapping.Properties { get; set; } = new List>(); + private readonly Type _type; /// - /// When specified dictates the default Elasticsearch index name for + /// Instantiates a new instance of /// - public ClrTypeMappingDescriptor IndexName(string indexName) => Assign(a => a.IndexName = indexName); + /// The CLR type to map + public ClrTypeMappingDescriptor(Type type) => _type = type; - /// - /// When specified dictates the default Elasticsearch type name for - /// - public ClrTypeMappingDescriptor TypeName(string typeName) => Assign(a => a.TypeName = typeName); + Type IClrTypeMapping.ClrType => _type; + string IClrTypeMapping.IndexName { get; set; } + string IClrTypeMapping.TypeName { get; set; } + string IClrTypeMapping.RelationName { get; set; } /// - /// When specified dictates the relation name for to resolve to. + /// The default Elasticsearch index name for the CLR type /// - public ClrTypeMappingDescriptor RelationName(string relationName) => Assign(a => a.RelationName = relationName); + public ClrTypeMappingDescriptor IndexName(string indexName) => Assign(a => a.IndexName = indexName); /// - /// Allows you to set a default Id property on that NEST will evaluate + /// The default Elasticsearch type name for the CLR type /// - public ClrTypeMappingDescriptor IdProperty(Expression> property) => Assign(a => a.IdProperty = property); + public ClrTypeMappingDescriptor TypeName(string typeName) => Assign(a => a.TypeName = typeName); /// - /// When specified allows you to ignore on clr type + /// The relation name for the CLR type to resolve to. /// - public ClrTypeMappingDescriptor Ignore(Expression> property) => - Assign(a => a.Properties.Add(new IgnorePropertyMapping(property))); - - /// - /// When specified allows you to rename on clr type - /// - public ClrTypeMappingDescriptor Rename(Expression> property, string newName) => - Assign(a => a.Properties.Add(new RenamePropertyMapping(property, newName))); - + public ClrTypeMappingDescriptor RelationName(string relationName) => Assign(a => a.RelationName = relationName); } - public interface IClrTypePropertyMapping where T : class + public class ClrTypeMappingDescriptor + : DescriptorBase,IClrTypeMapping>, IClrTypeMapping + where TDocument : class { - Expression> Property { get; set; } - bool Ignore { get; set; } - string NewName { get; set; } - IPropertyMapping ToPropertyMapping(); - } - - public abstract class ClrPropertyMappingBase : IClrTypePropertyMapping - where T : class - { - protected IClrTypePropertyMapping Self => this; + Type IClrTypeMapping.ClrType { get; } = typeof (TDocument); + string IClrTypeMapping.IndexName { get; set; } + string IClrTypeMapping.TypeName { get; set; } + string IClrTypeMapping.RelationName { get; set; } + Expression> IClrTypeMapping.IdProperty { get; set; } + IList> IClrTypeMapping.Properties { get; set; } = new List>(); - Expression> IClrTypePropertyMapping.Property { get; set; } + /// + /// The default Elasticsearch index name for + /// + public ClrTypeMappingDescriptor IndexName(string indexName) => Assign(a => a.IndexName = indexName); - bool IClrTypePropertyMapping.Ignore { get; set; } + /// + /// The default Elasticsearch type name for + /// + public ClrTypeMappingDescriptor TypeName(string typeName) => Assign(a => a.TypeName = typeName); - string IClrTypePropertyMapping.NewName { get; set; } + /// + /// The relation name for to resolve to. + /// + public ClrTypeMappingDescriptor RelationName(string relationName) => Assign(a => a.RelationName = relationName); - protected ClrPropertyMappingBase(Expression> property) - { - Self.Property = property; - } + /// + /// Set a default Id property on CLR type that NEST will evaluate + /// + public ClrTypeMappingDescriptor IdProperty(Expression> property) => Assign(a => a.IdProperty = property); - IPropertyMapping IClrTypePropertyMapping.ToPropertyMapping() => Self.Ignore ? PropertyMapping.Ignored : new PropertyMapping {Name = Self.NewName}; - } + /// + /// Ignore on CLR type + /// + public ClrTypeMappingDescriptor Ignore(Expression> property) => + Assign(a => a.Properties.Add(new IgnoreClrPropertyMapping(property))); - public class IgnorePropertyMapping : ClrPropertyMappingBase where T : class - { - public IgnorePropertyMapping(Expression> property) : base(property) - { - Self.Ignore = true; - } - } + /// + /// Rename on CLR type + /// + public ClrTypeMappingDescriptor Rename(Expression> property, string newName) => + Assign(a => a.Properties.Add(new RenameClrPropertyMapping(property, newName))); - public class RenamePropertyMapping : ClrPropertyMappingBase where T : class - { - public RenamePropertyMapping(Expression> property, string newName) : base(property) - { - newName.ThrowIfNull(nameof(newName)); - Self.NewName = newName; - } } - - - } diff --git a/src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettingsBase.cs b/src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettingsBase.cs index 3fb5d92d13b..edc225eb158 100644 --- a/src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettingsBase.cs +++ b/src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettingsBase.cs @@ -20,10 +20,12 @@ public ConnectionSettings(Uri uri = null) : this(new SingleNodeConnectionPool(uri ?? new Uri("http://localhost:9200"))) { } public ConnectionSettings(IConnectionPool connectionPool) : this(connectionPool, null, null) { } + public ConnectionSettings(IConnectionPool connectionPool, SourceSerializerFactory sourceSerializer) : this(connectionPool, null, sourceSerializer) { } public ConnectionSettings(IConnectionPool connectionPool, IConnection connection) : this(connectionPool, connection, null) { } + public ConnectionSettings(IConnectionPool connectionPool, IConnection connection, SourceSerializerFactory sourceSerializer) : this(connectionPool, connection, sourceSerializer, null) { } @@ -33,7 +35,6 @@ public ConnectionSettings( SourceSerializerFactory sourceSerializer, IPropertyMappingProvider propertyMappingProvider) : base(connectionPool, connection, sourceSerializer, propertyMappingProvider) { } - } /// @@ -85,7 +86,7 @@ protected ConnectionSettingsBase( IConnection connection, ConnectionSettings.SourceSerializerFactory sourceSerializerFactory, IPropertyMappingProvider propertyMappingProvider - ) + ) : base(connectionPool, connection, null) { var defaultSerializer = new JsonNetSerializer(this); @@ -113,7 +114,7 @@ IPropertyMappingProvider propertyMappingProvider public TConnectionSettings PluralizeTypeNames() { this._defaultTypeNameInferrer = this.LowerCaseAndPluralizeTypeNameInferrer; - return (TConnectionSettings)this; + return (TConnectionSettings) this; } /// @@ -125,7 +126,7 @@ public TConnectionSettings PluralizeTypeNames() public TConnectionSettings DefaultIndex(string defaultIndex) { this._defaultIndex = defaultIndex; - return (TConnectionSettings)this; + return (TConnectionSettings) this; } private string LowerCaseAndPluralizeTypeNameInferrer(Type type) @@ -143,7 +144,7 @@ private string LowerCaseAndPluralizeTypeNameInferrer(Type type) public TConnectionSettings DefaultFieldNameInferrer(Func fieldNameInferrer) { this._defaultFieldNameInferrer = fieldNameInferrer; - return (TConnectionSettings)this; + return (TConnectionSettings) this; } /// @@ -155,17 +156,17 @@ public TConnectionSettings DefaultTypeNameInferrer(Func typeNameIn { typeNameInferrer.ThrowIfNull(nameof(typeNameInferrer)); this._defaultTypeNameInferrer = typeNameInferrer; - return (TConnectionSettings)this; + return (TConnectionSettings) this; } - /// - /// Specify which property on a given POCO should be used to infer the id of the document when - /// indexed in Elasticsearch. - /// - /// The type of the document. - /// The object path. - /// - private TConnectionSettings MapIdPropertyFor(Expression> objectPath) + /// + /// Specify which property on a given POCO should be used to infer the id of the document when + /// indexed in Elasticsearch. + /// + /// The type of the document. + /// The object path. + /// + private TConnectionSettings MapIdPropertyFor(Expression> objectPath) { objectPath.ThrowIfNull(nameof(objectPath)); @@ -175,17 +176,18 @@ private TConnectionSettings MapIdPropertyFor(Expression(IList> mappings) + private void ApplyPropertyMappings(IList> mappings) where TDocument : class { foreach (var mapping in mappings) @@ -207,34 +209,35 @@ private void ApplyPropertyMappings(IList - /// Specify how the mapping is inferred for a given POCO type. - /// Can be used to infer the index, type, id property and properties for the POCO. - /// - /// The type of the document. - /// The selector. - /// - public TConnectionSettings InferMappingFor(Func, IClrTypeMapping> selector) + /// + /// Specify how the mapping is inferred for a given POCO type. Can be used to infer the index, type and relation names. + /// The generic version also allows you to set a default id property and control serialization behavior for properties for the POCO. + /// + /// The type of the document. + /// The selector. + public TConnectionSettings InferMappingFor(Func, IClrTypeMapping> selector) where TDocument : class { var inferMapping = selector(new ClrTypeMappingDescriptor()); if (!inferMapping.IndexName.IsNullOrEmpty()) - this._defaultIndices.Add(inferMapping.Type, inferMapping.IndexName); + this._defaultIndices.Add(inferMapping.ClrType, inferMapping.IndexName); if (!inferMapping.TypeName.IsNullOrEmpty()) - this._defaultTypeNames.Add(inferMapping.Type, inferMapping.TypeName); + this._defaultTypeNames.Add(inferMapping.ClrType, inferMapping.TypeName); if (!inferMapping.RelationName.IsNullOrEmpty()) - this._defaultRelationNames.Add(inferMapping.Type, inferMapping.RelationName); + this._defaultRelationNames.Add(inferMapping.ClrType, inferMapping.RelationName); if (inferMapping.IdProperty != null) this.MapIdPropertyFor(inferMapping.IdProperty); @@ -242,8 +245,50 @@ public TConnectionSettings InferMappingFor(Func(inferMapping.Properties); - return (TConnectionSettings)this; + return (TConnectionSettings) this; } + /// + /// Specify how the mapping is inferred for a given POCO type. Can be used to infer the index, type, and relation names. + /// + /// The type of the POCO you wish to configure + /// describe the POCO configuration + public TConnectionSettings InferMappingFor(Type documentType, Func selector) + { + var inferMapping = selector(new ClrTypeMappingDescriptor(documentType)); + if (!inferMapping.IndexName.IsNullOrEmpty()) + this._defaultIndices.Add(inferMapping.ClrType, inferMapping.IndexName); + + if (!inferMapping.TypeName.IsNullOrEmpty()) + this._defaultTypeNames.Add(inferMapping.ClrType, inferMapping.TypeName); + + if (!inferMapping.RelationName.IsNullOrEmpty()) + this._defaultRelationNames.Add(inferMapping.ClrType, inferMapping.RelationName); + + return (TConnectionSettings) this; + } + + /// + /// Specify how the mapping is inferred for a given POCO type. Can be used to infer the index, type, and relation names. + /// + /// The type of the POCO you wish to configure + /// describe the POCO configuration + public TConnectionSettings InferMappings(IEnumerable typeMappings) + { + if (typeMappings == null) return (TConnectionSettings) this; + foreach (var inferMapping in typeMappings) + { + if (!inferMapping.IndexName.IsNullOrEmpty()) + this._defaultIndices.Add(inferMapping.ClrType, inferMapping.IndexName); + + if (!inferMapping.TypeName.IsNullOrEmpty()) + this._defaultTypeNames.Add(inferMapping.ClrType, inferMapping.TypeName); + + if (!inferMapping.RelationName.IsNullOrEmpty()) + this._defaultRelationNames.Add(inferMapping.ClrType, inferMapping.RelationName); + } + + return (TConnectionSettings) this; + } } } diff --git a/src/Nest/CommonAbstractions/SerializationBehavior/PropertyMapping.cs b/src/Nest/CommonAbstractions/SerializationBehavior/PropertyMapping.cs index a2b2b772283..a6bbc5a01af 100644 --- a/src/Nest/CommonAbstractions/SerializationBehavior/PropertyMapping.cs +++ b/src/Nest/CommonAbstractions/SerializationBehavior/PropertyMapping.cs @@ -4,20 +4,20 @@ namespace Nest { - /// This class allows a serializer to report back on a properties behavior + /// Determines how a POCO property maps to the property on a JSON object when serialized public interface IPropertyMapping { - /// Override the json property name of a type + /// Override the property name serialized to JSON for this property string Name { get; set; } /// /// Ignore this property completely - ///
- When mapping automatically using AutoMap()
- ///
- When Indexing this type do not serialize whatever this value hold
+ /// - When mapping automatically using + /// - When Indexing this type do not serialize this property and its value ///
bool Ignore { get; set; } } - /// This class allows a serializer to report back on a properties behavior + /// public class PropertyMapping : IPropertyMapping { public static PropertyMapping Ignored = new PropertyMapping { Ignore = true }; @@ -29,15 +29,23 @@ public class PropertyMapping : IPropertyMapping public bool Ignore { get; set; } } + /// + /// Provides mappings for POCO properties + /// public interface IPropertyMappingProvider { + /// + /// Creates an for a + /// IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo); } + /// public class PropertyMappingProvider : IPropertyMappingProvider { protected readonly ConcurrentDictionary Properties = new ConcurrentDictionary(); + /// public virtual IPropertyMapping CreatePropertyMapping(MemberInfo memberInfo) { var memberInfoString = $"{memberInfo.DeclaringType?.FullName}.{memberInfo.Name}"; diff --git a/src/Nest/Mapping/PropertyMapping.cs b/src/Nest/Mapping/PropertyMapping.cs index eda010ddd6a..c3d81e05d75 100644 --- a/src/Nest/Mapping/PropertyMapping.cs +++ b/src/Nest/Mapping/PropertyMapping.cs @@ -8,20 +8,20 @@ namespace Nest public class PropertyMappingDescriptor : DescriptorBase, IDescriptor> where TDocument : class { - internal IList> Mappings { get; } = new List>(); + internal IList> Mappings { get; } = new List>(); public PropertyMappingDescriptor Rename(Expression> property, string field) { property.ThrowIfNull(nameof(property)); field.ThrowIfNullOrEmpty(nameof(field)); - this.Mappings.Add(new RenamePropertyMapping(property, field)); + this.Mappings.Add(new RenameClrPropertyMapping(property, field)); return this; } public PropertyMappingDescriptor Ignore(Expression> property) { property.ThrowIfNull(nameof(property)); - this.Mappings.Add(new IgnorePropertyMapping(property)); + this.Mappings.Add(new IgnoreClrPropertyMapping(property)); return this; } }