Skip to content

Commit ce1c37f

Browse files
Update settings for type mappings (#6383) (#6384)
* Move inference types to their own files * Extract some types into files * Rename and restructure Descriptor base types * Support use of DefaultFieldNameInferrer setting with STJ * Update playground * Fix BOM and file cleanup * Fix BOMs * Nullable attributes for infer methods * Remove commented code Co-authored-by: Steve Gordon <sgordon@hotmail.co.uk>
1 parent 980c428 commit ce1c37f

File tree

378 files changed

+1578
-1992
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

378 files changed

+1578
-1992
lines changed

src/Elastic.Clients.Elasticsearch/Client/ElasticsearchClient-Manual.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ public IndexResponse Index<TDocument>(TDocument document, Action<IndexRequestDes
1717
return DoRequest<IndexRequestDescriptor<TDocument>, IndexResponse>(descriptor);
1818
}
1919

20+
public Task<IndexResponse> IndexAsync<TDocument>(TDocument document, CancellationToken cancellationToken = default)
21+
{
22+
var descriptor = new IndexRequestDescriptor<TDocument>(documentWithId: document);
23+
return DoRequestAsync<IndexRequestDescriptor<TDocument>, IndexResponse>(descriptor);
24+
}
25+
2026
public Task<IndexResponse> IndexAsync<TDocument>(TDocument document, Action<IndexRequestDescriptor<TDocument>> configureRequest, CancellationToken cancellationToken = default)
2127
{
2228
var descriptor = new IndexRequestDescriptor<TDocument>(documentWithId: document);

src/Elastic.Clients.Elasticsearch/Common/Configuration/ClrTypeDefaults.cs

Lines changed: 36 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,57 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6-
using System.Collections.Generic;
76
using System.Linq.Expressions;
8-
using System.Text.Json;
97

108
namespace Elastic.Clients.Elasticsearch
119
{
1210
public class ClrTypeMapping
1311
{
1412
/// <summary>
15-
/// Initializes a new instance of <see cref="ClrTypeMapping" />
13+
/// Initializes a new instance of <see cref="ClrTypeMapping" />.
1614
/// </summary>
1715
public ClrTypeMapping(Type type) => ClrType = type;
1816

19-
/// <inheritdoc />
17+
/// <summary>
18+
/// The CLR type the mapping relates to.
19+
/// </summary>
2020
public Type ClrType { get; }
2121

22-
/// <inheritdoc />
22+
/// <summary>
23+
/// The property for the given <see cref="ClrType" /> to resolve IDs from.
24+
/// </summary>
2325
public string IdPropertyName { get; set; }
2426

25-
/// <inheritdoc />
27+
/// <summary>
28+
/// The default Elasticsearch index name for the given <see cref="ClrType" />.
29+
/// </summary>
2630
public string IndexName { get; set; }
2731

28-
/// <inheritdoc />
32+
/// <summary>
33+
/// The relation name for the given <see cref="ClrType" /> to resolve to.
34+
/// </summary>
2935
public string RelationName { get; set; }
3036

31-
/// <inheritdoc />
37+
/// <summary>
38+
/// Disables ID inference for the given <see cref="ClrType"/>.
39+
/// By default, the _id value for a document is inferred from a property named Id,
40+
/// or from the property named by <see cref="IdPropertyName"/>, if set.
41+
/// </summary>
3242
public bool DisableIdInference { get; set; }
3343
}
3444

35-
public sealed class ClrTypeMapping<TDocument> : ClrTypeMapping where TDocument : class
45+
public sealed class ClrTypeMapping<TDocument> : ClrTypeMapping
3646
{
3747
public ClrTypeMapping() : base(typeof(TDocument)) { }
3848

39-
/// <inheritdoc />
49+
/// <summary>
50+
/// Set a default Id property on CLR type <typeparamref name="TDocument" /> that NEST will evaluate
51+
/// </summary>
4052
public Expression<Func<TDocument, object>> IdProperty { get; set; }
4153

42-
/// <inheritdoc />
43-
public IList<IClrPropertyMapping<TDocument>> Properties { get; set; }
44-
45-
/// <inheritdoc />
54+
/// <summary>
55+
/// Provide a default routing parameter lookup based on <typeparamref name="TDocument" />
56+
/// </summary>
4657
public Expression<Func<TDocument, object>> RoutingProperty { get; set; }
4758
}
4859

@@ -54,34 +65,26 @@ public sealed class ClrTypeMappingDescriptor : DescriptorBase<ClrTypeMappingDesc
5465
internal string _idProperty;
5566
internal bool _disableIdInference;
5667

57-
// TODO - XML Comments
58-
5968
/// <summary>
6069
/// Instantiates a new instance of <see cref="ClrTypeMappingDescriptor" />
6170
/// </summary>
6271
/// <param name="type">The CLR type to map</param>
6372
public ClrTypeMappingDescriptor(Type type) => _clrType = type;
6473

65-
///// <inheritdoc cref="IClrTypeMapping.IndexName"/>
74+
/// <inheritdoc cref="ClrTypeMapping.IndexName"/>
6675
public ClrTypeMappingDescriptor IndexName(string indexName) => Assign(indexName, (a, v) => a._indexName = v);
6776

68-
///// <inheritdoc cref="IClrTypeMapping.RelationName"/>
77+
/// <inheritdoc cref="ClrTypeMapping.RelationName"/>
6978
public ClrTypeMappingDescriptor RelationName(string relationName) => Assign(relationName, (a, v) => a._relationName = v);
7079

71-
/// <summary>
72-
/// The property for the given <see cref="Type" /> to resolve IDs from.
73-
/// </summary>
80+
/// <inheritdoc cref="ClrTypeMapping{T}.IdProperty"/>
7481
public ClrTypeMappingDescriptor IdProperty(string idProperty) => Assign(idProperty, (a, v) => a._idProperty = v);
7582

76-
///// <inheritdoc cref="IClrTypeMapping.DisableIdInference"/>
83+
/// <inheritdoc cref="ClrTypeMapping.DisableIdInference"/>
7784
public ClrTypeMappingDescriptor DisableIdInference(bool disable = true) => Assign(disable, (a, v) => a._disableIdInference = v);
78-
79-
protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) => throw new NotImplementedException();
8085
}
8186

82-
public sealed class ClrTypeMappingDescriptor<TDocument>
83-
: DescriptorBase<ClrTypeMappingDescriptor<TDocument>>
84-
where TDocument : class
87+
public sealed class ClrTypeMappingDescriptor<TDocument> : DescriptorBase<ClrTypeMappingDescriptor<TDocument>>
8588
{
8689
internal Type _clrType = typeof(TDocument);
8790
internal string _indexName;
@@ -91,47 +94,24 @@ public sealed class ClrTypeMappingDescriptor<TDocument>
9194

9295
internal Expression<Func<TDocument, object>> _idPropertyExpression;
9396
internal Expression<Func<TDocument, object>> _routingPropertyExpression;
94-
internal IList<IClrPropertyMapping<TDocument>> _properties = new List<IClrPropertyMapping<TDocument>>();
9597

96-
/// <summary>
97-
/// The default Elasticsearch index name for <typeparamref name="TDocument" />
98-
/// </summary>
98+
/// <inheritdoc cref="ClrTypeMapping.IndexName"/>
9999
public ClrTypeMappingDescriptor<TDocument> IndexName(string indexName) => Assign(indexName, (a, v) => a._indexName = v);
100100

101-
/// <summary>
102-
/// The relation name for <typeparamref name="TDocument" /> to resolve to.
103-
/// </summary>
101+
/// <inheritdoc cref="ClrTypeMapping.RelationName"/>
104102
public ClrTypeMappingDescriptor<TDocument> RelationName(string relationName) => Assign(relationName, (a, v) => a._relationName = v);
105103

106-
/// <summary>
107-
/// Set a default Id property on CLR type <typeparamref name="TDocument" /> that Elastic.Clients.Elasticsearch will evaluate
108-
/// </summary>
104+
/// <inheritdoc cref="ClrTypeMapping{T}.IdProperty"/>
109105
public ClrTypeMappingDescriptor<TDocument> IdProperty(Expression<Func<TDocument, object>> property) => Assign(property, (a, v) => a._idPropertyExpression = v);
110106

111-
/// <summary>
112-
/// Set a default Id property on CLR type <typeparamref name="TDocument" /> that Elastic.Clients.Elasticsearch will evaluate
113-
/// </summary>
107+
/// <inheritdoc cref="ClrTypeMapping{T}.IdProperty"/>
114108
public ClrTypeMappingDescriptor<TDocument> IdProperty(string property) => Assign(property, (a, v) => a._idProperty = v);
115109

116-
/// <summary> Provide a default routing parameter lookup based on <typeparamref name="TDocument" /> </summary>
110+
/// <inheritdoc cref="ClrTypeMapping{T}.RoutingProperty"/>
117111
public ClrTypeMappingDescriptor<TDocument> RoutingProperty(Expression<Func<TDocument, object>> property) =>
118112
Assign(property, (a, v) => a._routingPropertyExpression = v);
119113

120-
/// <summary>
121-
/// Ignore <paramref name="property" /> on CLR type <typeparamref name="TDocument" />
122-
/// </summary>
123-
public ClrTypeMappingDescriptor<TDocument> Ignore(Expression<Func<TDocument, object>> property) =>
124-
Assign(property, (a, v) => a._properties.Add(new IgnoreClrPropertyMapping<TDocument>(v)));
125-
126-
/// <summary>
127-
/// Rename <paramref name="property" /> on CLR type <typeparamref name="TDocument" />
128-
/// </summary>
129-
public ClrTypeMappingDescriptor<TDocument> PropertyName(Expression<Func<TDocument, object>> property, string newName) =>
130-
Assign(new RenameClrPropertyMapping<TDocument>(property, newName), (a, v) => a._properties.Add(v));
131-
132-
///// <inheritdoc cref="IClrTypeMapping.DisableIdInference"/>
114+
/// <inheritdoc cref="ClrTypeMapping.DisableIdInference"/>
133115
public ClrTypeMappingDescriptor<TDocument> DisableIdInference(bool disable = true) => Assign(disable, (a, v) => a._disableIdInference = v);
134-
135-
protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) => throw new NotImplementedException();
136116
}
137117
}

src/Elastic.Clients.Elasticsearch/Common/Configuration/ElasticsearchClientSettings.cs

Lines changed: 13 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ protected ElasticsearchClientSettingsBase(
112112
IPropertyMappingProvider propertyMappingProvider)
113113
: base(nodePool, connection, null, ElasticsearchClientProductRegistration.DefaultForElasticsearchClientsElasticsearch)
114114
{
115-
var defaultSerializer = new DefaultRequestResponseSerializer(this);
116-
var sourceSerializer = sourceSerializerFactory?.Invoke(defaultSerializer, this) ?? new DefaultSourceSerializer(this);
115+
var requestResponseSerializer = new DefaultRequestResponseSerializer(this);
116+
var sourceSerializer = sourceSerializerFactory?.Invoke(requestResponseSerializer, this) ?? new DefaultSourceSerializer(this);
117117

118118
// TODO - Is the second condition ever true?
119119
_propertyMappingProvider = propertyMappingProvider ?? sourceSerializer as IPropertyMappingProvider ?? new PropertyMappingProvider();
@@ -124,7 +124,7 @@ protected ElasticsearchClientSettingsBase(
124124
_sourceSerializer = sourceSerializer;
125125

126126
//UseThisRequestResponseSerializer = new DiagnosticsSerializerProxy(defaultSerializer);
127-
UseThisRequestResponseSerializer = defaultSerializer;
127+
UseThisRequestResponseSerializer = requestResponseSerializer;
128128

129129
_defaultFieldNameInferrer = p => p.ToCamelCase();
130130
_defaultIndices = new FluentDictionary<Type, string>();
@@ -134,7 +134,7 @@ protected ElasticsearchClientSettingsBase(
134134
UserAgent(ElasticsearchClientSettings.DefaultUserAgent);
135135
}
136136

137-
public Serializer SourceSerializer { get; }
137+
public Serializer SourceSerializer => _sourceSerializer;
138138

139139
bool IElasticsearchClientSettings.DefaultDisableIdInference => _defaultDisableAllInference;
140140
Func<string, string> IElasticsearchClientSettings.DefaultFieldNameInferrer => _defaultFieldNameInferrer;
@@ -171,8 +171,15 @@ public TConnectionSettings DefaultIndex(string defaultIndex) =>
171171
/// <example>
172172
/// CLR property EmailAddress will be inferred as "emailAddress" Elasticsearch document field name
173173
/// </example>
174-
public TConnectionSettings DefaultFieldNameInferrer(Func<string, string> fieldNameInferrer) =>
175-
Assign(fieldNameInferrer, (a, v) => a._defaultFieldNameInferrer = v);
174+
public TConnectionSettings DefaultFieldNameInferrer(Func<string, string> fieldNameInferrer)
175+
{
176+
if (_sourceSerializer is DefaultSourceSerializer dss)
177+
{
178+
dss.Options.PropertyNamingPolicy = new CustomizedNamingPolicy(fieldNameInferrer);
179+
}
180+
181+
return Assign<Func<string, string>>(fieldNameInferrer, (a, v) => a._defaultFieldNameInferrer = v);
182+
}
176183

177184
public TConnectionSettings ExperimentalEnableSerializeNullInferredValues(bool enabled = true) =>
178185
Assign(enabled, (a, v) => a._experimentalEnableSerializeNullInferredValues = v);
@@ -230,42 +237,6 @@ private void MapRoutePropertyFor<TDocument>(Expression<Func<TDocument, object>>
230237
_routeProperties.Add(typeof(TDocument), fieldName);
231238
}
232239

233-
private void ApplyPropertyMappings<TDocument>(IList<IClrPropertyMapping<TDocument>> mappings)
234-
where TDocument : class
235-
{
236-
foreach (var mapping in mappings)
237-
{
238-
var e = mapping.Property;
239-
var memberInfoResolver = new MemberInfoResolver(e);
240-
if (memberInfoResolver.Members.Count > 1)
241-
throw new ArgumentException($"{nameof(ApplyPropertyMappings)} can only map direct properties");
242-
243-
if (memberInfoResolver.Members.Count == 0)
244-
throw new ArgumentException($"Expression {e} does contain any member access");
245-
246-
var memberInfo = memberInfoResolver.Members[0];
247-
248-
if (_propertyMappings.TryGetValue(memberInfo, out var propertyMapping))
249-
{
250-
var newName = mapping.NewName;
251-
var mappedAs = propertyMapping.Name;
252-
var typeName = typeof(TDocument).Name;
253-
if (mappedAs.IsNullOrEmpty() && newName.IsNullOrEmpty())
254-
throw new ArgumentException($"Property mapping '{e}' on type is already ignored");
255-
if (mappedAs.IsNullOrEmpty())
256-
throw new ArgumentException(
257-
$"Property mapping '{e}' on type {typeName} can not be mapped to '{newName}' it already has an ignore mapping");
258-
if (newName.IsNullOrEmpty())
259-
throw new ArgumentException(
260-
$"Property mapping '{e}' on type {typeName} can not be ignored it already has a mapping to '{mappedAs}'");
261-
262-
throw new ArgumentException(
263-
$"Property mapping '{e}' on type {typeName} can not be mapped to '{newName}' already mapped as '{mappedAs}'");
264-
}
265-
_propertyMappings[memberInfo] = mapping.ToPropertyMapping();
266-
}
267-
}
268-
269240
/// <summary>
270241
/// Specify how the mapping is inferred for a given CLR type.
271242
/// The mapping can infer the index, id and relation name for a given CLR type, as well as control
@@ -293,9 +264,6 @@ public TConnectionSettings DefaultMappingFor<TDocument>(
293264
if (inferMapping._routingPropertyExpression != null)
294265
MapRoutePropertyFor(inferMapping._routingPropertyExpression);
295266

296-
if (inferMapping._properties != null)
297-
ApplyPropertyMappings(inferMapping._properties);
298-
299267
if (inferMapping._disableIdInference)
300268
_disableIdInference.Add(inferMapping._clrType);
301269
else

src/Elastic.Clients.Elasticsearch/Common/Configuration/IElasticsearchClientSettings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ public interface IElasticsearchClientSettings : ITransportConfiguration
101101
bool ExperimentalEnableSerializeNullInferredValues { get; }
102102

103103
/// <summary>
104-
/// TODO
104+
/// Experimental settings.
105105
/// </summary>
106106
ExperimentalSettings Experimental { get; }
107107
}
108108

109109
public sealed class ExperimentalSettings
110110
{
111111
/// <summary>
112-
/// When enabled, the parameters for a script will be serialised using the SourceSerializer
112+
/// When enabled, the parameters for a script will be serialised using the SourceSerializer.
113113
/// </summary>
114114
public bool UseSourceSerializerForScriptParameters { get; set; }
115115
}

src/Elastic.Clients.Elasticsearch/Common/Containers/VariantDescriptorBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Elastic.Clients.Elasticsearch;
66

7-
public abstract class VariantDescriptorBase<T> : DescriptorBase<T> where T : DescriptorBase<T>
7+
public abstract class VariantDescriptorBase<T> : SerializableDescriptorBase<T> where T : SerializableDescriptorBase<T>
88
{
99
internal string VariantName { get; private set; }
1010

src/Elastic.Clients.Elasticsearch/Common/Fluent/DescriptorBase.cs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,13 @@
77
using System.Runtime.CompilerServices;
88
using System.Runtime.Serialization;
99
using System.Text.Json;
10+
using System.Text.Json.Serialization;
1011

1112
namespace Elastic.Clients.Elasticsearch;
1213

13-
/// <summary>
14-
/// Internal marker for descriptors.
15-
/// </summary>
16-
internal interface IDescriptor { }
17-
18-
public abstract class DescriptorBase<TDescriptor> : IDescriptor, ISelfSerializable
19-
where TDescriptor : DescriptorBase<TDescriptor>
14+
public abstract class Descriptor
2015
{
21-
private readonly TDescriptor _self;
22-
23-
internal DescriptorBase() => _self = (TDescriptor)this;
24-
25-
[IgnoreDataMember]
26-
protected TDescriptor Self => _self;
27-
28-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
29-
protected TDescriptor Assign<TValue>(TValue value, Action<TDescriptor, TValue> assign) => Fluent.Assign(_self, value, assign);
30-
31-
protected abstract void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings);
16+
internal Descriptor() { }
3217

3318
/// <summary>
3419
/// Hides the <see cref="Equals" /> method.
@@ -45,7 +30,7 @@ public abstract class DescriptorBase<TDescriptor> : IDescriptor, ISelfSerializab
4530
[Browsable(false)]
4631
[EditorBrowsable(EditorBrowsableState.Never)]
4732
// ReSharper disable once BaseObjectGetHashCodeCallInGetHashCode
48-
//only used to hide by default
33+
// only used to hide by default
4934
public override int GetHashCode() => base.GetHashCode();
5035

5136
/// <summary>
@@ -54,7 +39,29 @@ public abstract class DescriptorBase<TDescriptor> : IDescriptor, ISelfSerializab
5439
[Browsable(false)]
5540
[EditorBrowsable(EditorBrowsableState.Never)]
5641
public override string ToString() => base.ToString();
42+
}
5743

58-
void ISelfSerializable.Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) => Serialize(writer, options, settings);
44+
public abstract class DescriptorBase<TDescriptor> : Descriptor
45+
where TDescriptor : DescriptorBase<TDescriptor>
46+
{
47+
private readonly TDescriptor _self;
48+
49+
internal DescriptorBase() : base() => _self = (TDescriptor)this;
50+
51+
[JsonIgnore]
52+
[IgnoreDataMember]
53+
protected TDescriptor Self => _self;
54+
55+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
56+
protected TDescriptor Assign<TValue>(TValue value, Action<TDescriptor, TValue> assign) => Fluent.Assign(_self, value, assign);
5957
}
6058

59+
public abstract class SerializableDescriptorBase<TDescriptor> : DescriptorBase<TDescriptor>, ISelfSerializable
60+
where TDescriptor : SerializableDescriptorBase<TDescriptor>
61+
{
62+
internal SerializableDescriptorBase(): base() { }
63+
64+
void ISelfSerializable.Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) => Serialize(writer, options, settings);
65+
66+
protected abstract void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings);
67+
}

0 commit comments

Comments
 (0)