From 6ee58c07f7ce982be1581fe8a039d98532c9019a Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Mon, 4 Jan 2021 16:10:22 +0000 Subject: [PATCH 1/3] Add support for mapping runtime fields --- .../PutMapping/PutMappingRequest.cs | 8 + src/Nest/Mapping/Mappings.cs | 2 + .../Mapping/RuntimeFields/RuntimeField.cs | 59 ++++++ .../Mapping/RuntimeFields/RuntimeFields.cs | 36 ++++ src/Nest/Mapping/TypeMapping.cs | 14 ++ .../PutMapping/PutMappingApiTest.cs | 57 ++++++ .../RuntimeFields/RuntimeFieldsTests.cs | 178 ++++++++++++++++++ 7 files changed, 354 insertions(+) create mode 100644 src/Nest/Mapping/RuntimeFields/RuntimeField.cs create mode 100644 src/Nest/Mapping/RuntimeFields/RuntimeFields.cs create mode 100644 tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs diff --git a/src/Nest/Indices/MappingManagement/PutMapping/PutMappingRequest.cs b/src/Nest/Indices/MappingManagement/PutMapping/PutMappingRequest.cs index 19e0e4b1a8d..5133a051e03 100644 --- a/src/Nest/Indices/MappingManagement/PutMapping/PutMappingRequest.cs +++ b/src/Nest/Indices/MappingManagement/PutMapping/PutMappingRequest.cs @@ -56,6 +56,9 @@ public partial class PutMappingRequest /// public IRoutingField RoutingField { get; set; } + /// + public IRuntimeFields RuntimeFields { get; set; } + /// public ISizeField SizeField { get; set; } @@ -82,6 +85,7 @@ public partial class PutMappingDescriptor where TDocument : class bool? ITypeMapping.NumericDetection { get; set; } IProperties ITypeMapping.Properties { get; set; } IRoutingField ITypeMapping.RoutingField { get; set; } + IRuntimeFields ITypeMapping.RuntimeFields { get; set; } ISizeField ITypeMapping.SizeField { get; set; } ISourceField ITypeMapping.SourceField { get; set; } @@ -150,6 +154,10 @@ public PutMappingDescriptor SourceField(Func RoutingField(Func, IRoutingField> routingFieldSelector) => Assign(routingFieldSelector, (a, v) => a.RoutingField = v?.Invoke(new RoutingFieldDescriptor())); + /// + public PutMappingDescriptor RuntimeFields(Func> runtimeFieldsSelector) => + Assign(runtimeFieldsSelector, (a, v) => a.RuntimeFields = v?.Invoke(new RuntimeFieldsDescriptor())?.Value); + /// public PutMappingDescriptor FieldNamesField(Func, IFieldNamesField> fieldNamesFieldSelector) => Assign(fieldNamesFieldSelector, (a, v) => a.FieldNamesField = v.Invoke(new FieldNamesFieldDescriptor())); diff --git a/src/Nest/Mapping/Mappings.cs b/src/Nest/Mapping/Mappings.cs index 694d69578a0..396c78981e9 100644 --- a/src/Nest/Mapping/Mappings.cs +++ b/src/Nest/Mapping/Mappings.cs @@ -57,6 +57,8 @@ public abstract class ObsoleteMappingsBase : ITypeMapping IProperties ITypeMapping.Properties { get => Wrapped.Properties; set => Wrapped.Properties = value; } [DataMember(Name = "_routing")] IRoutingField ITypeMapping.RoutingField { get => Wrapped.RoutingField; set => Wrapped.RoutingField = value; } + [DataMember(Name = "runtime")] + IRuntimeFields ITypeMapping.RuntimeFields { get => Wrapped.RuntimeFields; set => Wrapped.RuntimeFields = value; } [DataMember(Name = "_size")] ISizeField ITypeMapping.SizeField { get => Wrapped.SizeField; set => Wrapped.SizeField = value; } [DataMember(Name = "_source")] diff --git a/src/Nest/Mapping/RuntimeFields/RuntimeField.cs b/src/Nest/Mapping/RuntimeFields/RuntimeField.cs new file mode 100644 index 00000000000..0e8eb0630f0 --- /dev/null +++ b/src/Nest/Mapping/RuntimeFields/RuntimeField.cs @@ -0,0 +1,59 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Runtime.Serialization; +using Elasticsearch.Net.Utf8Json; + +namespace Nest +{ + [InterfaceDataContract] + [ReadAs(typeof(RuntimeField))] + public interface IRuntimeField + { + /// + /// Runtime fields with a type of date can accept the format parameter exactly as the date field type. + /// + /// + [DataMember(Name = "format")] + string Format { get; set; } + + /// + /// The script to be evaluated for field calculation at search time. + /// + [DataMember(Name = "script")] + IStoredScript Script { get; set; } + + /// + /// The datatype of the runtime field. + /// + [DataMember(Name = "type")] + FieldType Type { get; set; } + } + + public class RuntimeField : IRuntimeField + { + /// + public string Format { get; set; } + /// + public IStoredScript Script { get; set; } + /// + public FieldType Type { get; set; } + } + + public class RuntimeFieldDescriptor + : DescriptorBase, IRuntimeField + { + public RuntimeFieldDescriptor(FieldType fieldType) => Self.Type = fieldType; + + string IRuntimeField.Format { get; set; } + IStoredScript IRuntimeField.Script { get; set; } + FieldType IRuntimeField.Type { get; set; } + + public RuntimeFieldDescriptor Format(string format) => Assign(format, (a, v) => a.Format = v); + + public RuntimeFieldDescriptor Script(IStoredScript script) => Assign(script, (a, v) => a.Script = v); + + public RuntimeFieldDescriptor Script(string source) => Assign(source, (a, v) => a.Script = new PainlessScript(source)); + } +} diff --git a/src/Nest/Mapping/RuntimeFields/RuntimeFields.cs b/src/Nest/Mapping/RuntimeFields/RuntimeFields.cs new file mode 100644 index 00000000000..dac72883f71 --- /dev/null +++ b/src/Nest/Mapping/RuntimeFields/RuntimeFields.cs @@ -0,0 +1,36 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.Collections.Generic; +using Elasticsearch.Net.Utf8Json; + +namespace Nest +{ + [JsonFormatter(typeof(VerbatimDictionaryKeysFormatter))] + public interface IRuntimeFields : IIsADictionary { } + + public class RuntimeFields : IsADictionaryBase, IRuntimeFields + { + public RuntimeFields() { } + + public RuntimeFields(IDictionary container) : base(container) { } + + public RuntimeFields(Dictionary container) : base(container) { } + + public void Add(string name, IRuntimeField runtimeField) => BackingDictionary.Add(name, runtimeField); + } + + public class RuntimeFieldsDescriptor + : IsADictionaryDescriptorBase + { + public RuntimeFieldsDescriptor() : base(new RuntimeFields()) { } + + public RuntimeFieldsDescriptor RuntimeField(string name, FieldType type, Func selector) => + Assign(name, selector?.Invoke(new RuntimeFieldDescriptor(type))); + + public RuntimeFieldsDescriptor RuntimeField(string name, FieldType type) => + Assign(name, new RuntimeFieldDescriptor(type)); + } +} diff --git a/src/Nest/Mapping/TypeMapping.cs b/src/Nest/Mapping/TypeMapping.cs index 0ca74b4ff92..0058e2d06f1 100644 --- a/src/Nest/Mapping/TypeMapping.cs +++ b/src/Nest/Mapping/TypeMapping.cs @@ -96,6 +96,12 @@ public interface ITypeMapping [DataMember(Name = "_routing")] IRoutingField RoutingField { get; set; } + /// + /// Specifies runtime fields for the mapping. + /// + [DataMember(Name = "runtime")] + IRuntimeFields RuntimeFields { get; set; } + /// /// If enabled, indexes the size in bytes of the original _source field. /// Requires mapper-size plugin be installed @@ -147,6 +153,9 @@ public class TypeMapping : ITypeMapping /// public IRoutingField RoutingField { get; set; } + /// + public IRuntimeFields RuntimeFields { get; set; } + /// public ISizeField SizeField { get; set; } @@ -171,6 +180,7 @@ public class TypeMappingDescriptor : DescriptorBase, bool? ITypeMapping.NumericDetection { get; set; } IProperties ITypeMapping.Properties { get; set; } IRoutingField ITypeMapping.RoutingField { get; set; } + IRuntimeFields ITypeMapping.RuntimeFields { get; set; } ISizeField ITypeMapping.SizeField { get; set; } ISourceField ITypeMapping.SourceField { get; set; } @@ -259,6 +269,10 @@ public TypeMappingDescriptor DisableIndexField(bool? disabled = true) => public TypeMappingDescriptor RoutingField(Func, IRoutingField> routingFieldSelector) => Assign(routingFieldSelector, (a, v) => a.RoutingField = v?.Invoke(new RoutingFieldDescriptor())); + /// + public TypeMappingDescriptor RuntimeFields(Func> runtimeFieldsSelector) => + Assign(runtimeFieldsSelector, (a, v) => a.RuntimeFields = v?.Invoke(new RuntimeFieldsDescriptor())?.Value); + /// public TypeMappingDescriptor FieldNamesField(Func, IFieldNamesField> fieldNamesFieldSelector) => Assign(fieldNamesFieldSelector.Invoke(new FieldNamesFieldDescriptor()), (a, v) => a.FieldNamesField = v); diff --git a/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs b/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs index f1bb96790ef..42d7a020b0c 100644 --- a/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs +++ b/tests/Tests/Indices/MappingManagement/PutMapping/PutMappingApiTest.cs @@ -338,4 +338,61 @@ protected override LazyResponses ClientUsage() => Calls( (client, r) => client.MapAsync(r) ); } + + [SkipVersion("<7.11.0", "Runtime fields introduced in 7.11.0")] + public class PutMappingWithRuntimeFieldsTests : ApiTestBase, PutMappingRequest> + { + // These test serialisation only. Integration tests take place in RuntimeFieldsTests.cs + + private const string ScriptValue = "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"; + + public PutMappingWithRuntimeFieldsTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + + protected override HttpMethod HttpMethod => HttpMethod.PUT; + + protected override string UrlPath => $"/{CallIsolatedValue}/_mapping"; + + protected override PutMappingRequest Initializer => new(CallIsolatedValue) + { + RuntimeFields = new RuntimeFields + { + { "runtime_date", new RuntimeField { Type = FieldType.Date, Format = "yyyy-MM-dd" } }, + { "runtime_scripted", new RuntimeField { Type = FieldType.Keyword, Script = new PainlessScript(ScriptValue) } } + } + }; + + protected override Func, IPutMappingRequest> Fluent => d => d + .Index(CallIsolatedValue) + .RuntimeFields(rtf => rtf + .RuntimeField("runtime_date", FieldType.Date, rf => rf.Format("yyyy-MM-dd")) + .RuntimeField("runtime_scripted", FieldType.Keyword, rf=> rf.Script(new PainlessScript(ScriptValue)))); + + protected override LazyResponses ClientUsage() => Calls( + (client, f) => client.Indices.PutMapping(f), + (client, f) => client.Indices.PutMappingAsync(f), + (client, r) => client.Indices.PutMapping(r), + (client, r) => client.Indices.PutMappingAsync(r) + ); + + protected override object ExpectJson => new + { + runtime = new + { + runtime_date = new + { + type = "date", + format = "yyyy-MM-dd" + }, + runtime_scripted = new + { + type = "keyword", + script = new + { + lang = "painless", + source = ScriptValue + } + } + } + }; + } } diff --git a/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs b/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs new file mode 100644 index 00000000000..7f0a060803a --- /dev/null +++ b/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs @@ -0,0 +1,178 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Linq; +using System.Threading.Tasks; +using Elastic.Elasticsearch.Xunit.XunitPlumbing; +using FluentAssertions; +using Nest; +using Tests.Core.Extensions; +using Tests.Core.ManagedElasticsearch.Clusters; +using Tests.Domain; +using Tests.Framework.EndpointTests; +using Tests.Framework.EndpointTests.TestState; + +namespace Tests.Mapping.RuntimeFields +{ + [SkipVersion("<7.11.0", "Runtime fields introduced in 7.11.0")] + public class RuntimeFieldsTests : CoordinatedIntegrationTestBase + { + private const string ScriptValue = "emit(doc['lastActivity'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"; + private const string DateFormat = "yyyy-MM-dd"; + private const string RuntimeFieldNameOne = "runtimeFieldOne"; + private const string RuntimeFieldNameTwo = "runtimeFieldTwo"; + + private const string CreateIndexWithMappingStep = nameof(CreateIndexWithMappingStep); + private const string GetCreatedIndexMappingStep = nameof(GetCreatedIndexMappingStep); + private const string DeleteIndexStep = nameof(DeleteIndexStep); + private const string CreateIndexWithoutMappingStep = nameof(CreateIndexWithoutMappingStep); + private const string CreateMappingStep = nameof(CreateMappingStep); + private const string GetMappingStep = nameof(GetMappingStep); + + public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(new CoordinatedUsage(cluster, usage) + { + { + CreateIndexWithMappingStep, u => + u.Calls( + v => new CreateIndexRequest(v) + { + Mappings = new TypeMapping + { + RuntimeFields = new Nest.RuntimeFields + { + {RuntimeFieldNameOne, new RuntimeField + { + Type = FieldType.Keyword, + Script = new PainlessScript(ScriptValue) + }}, + {RuntimeFieldNameTwo, new RuntimeField + { + Type = FieldType.Date, + Format = DateFormat + }} + } + } + }, + (v, d) => d.Index(v).Map(mapping => mapping + .RuntimeFields(rtf => rtf + .RuntimeField(RuntimeFieldNameOne, FieldType.Keyword, f1 => f1 + .Script(ScriptValue)) + .RuntimeField(RuntimeFieldNameTwo, FieldType.Date, f2 => f2.Format(DateFormat)))), + (v, c, f) => c.Indices.Create(v, f), + (v, c, f) => c.Indices.CreateAsync(v, f), + (v, c, r) => c.Indices.Create(r), + (v, c, r) => c.Indices.CreateAsync(r) + ) + }, + { + GetCreatedIndexMappingStep, u => + u.Calls, GetMappingRequest, IGetMappingRequest, GetMappingResponse>( + v => new GetMappingRequest(v), + (v, d) => d.Index(v), + (v, c, f) => c.Indices.GetMapping(f), + (v, c, f) => c.Indices.GetMappingAsync(f), + (v, c, r) => c.Indices.GetMapping(r), + (v, c, r) => c.Indices.GetMappingAsync(r) + ) + }, + { + DeleteIndexStep, u => + u.Calls( + v => new DeleteIndexRequest(v), + (v, d) => d, + (v, c, f) => c.Indices.Delete(v, f), + (v, c, f) => c.Indices.DeleteAsync(v, f), + (v, c, r) => c.Indices.Delete(r), + (v, c, r) => c.Indices.DeleteAsync(r) + ) + }, + { + CreateIndexWithoutMappingStep, u => + u.Calls( + v => new CreateIndexRequest(v), + (v, d) => d.Index(v), + (v, c, f) => c.Indices.Create(v, f), + (v, c, f) => c.Indices.CreateAsync(v, f), + (v, c, r) => c.Indices.Create(r), + (v, c, r) => c.Indices.CreateAsync(r) + ) + }, + { + CreateMappingStep, u => + u.Calls, PutMappingRequest, IPutMappingRequest, PutMappingResponse>( + v => new PutMappingRequest(v) + { + RuntimeFields = new Nest.RuntimeFields + { + {RuntimeFieldNameOne, new RuntimeField + { + Type = FieldType.Keyword, + Script = new PainlessScript(ScriptValue) + }}, + {RuntimeFieldNameTwo, new RuntimeField + { + Type = FieldType.Date, + Format = DateFormat + }} + } + }, + (v, d) => d.Index(v) + .RuntimeFields(rtf => rtf + .RuntimeField(RuntimeFieldNameOne, FieldType.Keyword, f1 => f1 + .Script(ScriptValue)) + .RuntimeField(RuntimeFieldNameTwo, FieldType.Date, f2 => f2.Format(DateFormat))), + (v, c, f) => c.Indices.PutMapping(f), + (v, c, f) => c.Indices.PutMappingAsync(f), + (v, c, r) => c.Indices.PutMapping(r), + (v, c, r) => c.Indices.PutMappingAsync(r) + ) + }, + { + GetMappingStep, u => + u.Calls, GetMappingRequest, IGetMappingRequest, GetMappingResponse>( + v => new GetMappingRequest(v), + (v, d) => d.Index(v), + (v, c, f) => c.Indices.GetMapping(f), + (v, c, f) => c.Indices.GetMappingAsync(f), + (v, c, r) => c.Indices.GetMapping(r), + (v, c, r) => c.Indices.GetMappingAsync(r) + ) + } + }) + { } + + [I] public async Task CreateIndexWithRuntimeFieldsMapping() => await Assert(CreateIndexWithMappingStep, (v, r) => + { + r.ShouldBeValid(); + r.Acknowledged.Should().BeTrue(); + }); + + [I] public async Task GetIndexMappingWithRuntimeFields() => await Assert(GetCreatedIndexMappingStep, (v, r) => AssertRuntimeFields(r)); + + [I] public async Task PutMappingWithRuntimeFields() => await Assert(CreateMappingStep, (v, r) => + { + r.ShouldBeValid(); + r.Acknowledged.Should().BeTrue(); + }); + + [I] public async Task GetMappingWithRuntimeFields() => await Assert(GetMappingStep, (v, r) => AssertRuntimeFields(r)); + + private static void AssertRuntimeFields(GetMappingResponse response) + { + response.ShouldBeValid(); + var runtimeFields = response.Indices.First().Value.Mappings.RuntimeFields; + + runtimeFields.Count.Should().Be(2); + runtimeFields.TryGetValue(RuntimeFieldNameOne, out var fieldOne).Should().BeTrue(); + runtimeFields.TryGetValue(RuntimeFieldNameTwo, out var fieldTwo).Should().BeTrue(); + + fieldOne!.Type.Should().Be(FieldType.Keyword); + fieldOne.Script.Lang.Should().Be("painless"); + fieldOne.Script.Source.Should().Be(ScriptValue); + + fieldTwo!.Type.Should().Be(FieldType.Date); + fieldTwo.Format.Should().Be(DateFormat); + } + } +} From 75bbbb5a8702f3d0da4d4174ddb16a73af64ca96 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 5 Jan 2021 09:46:36 +0000 Subject: [PATCH 2/3] Add missing XML comment for PIT --- src/Nest/Search/Search/SearchRequest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Nest/Search/Search/SearchRequest.cs b/src/Nest/Search/Search/SearchRequest.cs index fb63c469458..0a999065451 100644 --- a/src/Nest/Search/Search/SearchRequest.cs +++ b/src/Nest/Search/Search/SearchRequest.cs @@ -167,6 +167,9 @@ public partial interface ISearchRequest : ITypedSearchRequest [DataMember(Name = "version")] bool? Version { get; set; } + /// + /// The to search over. + /// [DataMember(Name = "pit")] IPointInTime PointInTime { get; set; } } From c788a24f66a7a8489510d9969320303d80f3622d Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 5 Jan 2021 11:11:05 +0000 Subject: [PATCH 3/3] Adjust tests to avoid index name clash --- .../RuntimeFields/RuntimeFieldsTests.cs | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs b/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs index 7f0a060803a..81e611f264f 100644 --- a/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs +++ b/tests/Tests/Mapping/RuntimeFields/RuntimeFieldsTests.cs @@ -35,7 +35,7 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n { CreateIndexWithMappingStep, u => u.Calls( - v => new CreateIndexRequest(v) + v => new CreateIndexRequest(IndexName(v)) { Mappings = new TypeMapping { @@ -54,13 +54,13 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n } } }, - (v, d) => d.Index(v).Map(mapping => mapping + (v, d) => d.Index(IndexName(v)).Map(mapping => mapping .RuntimeFields(rtf => rtf .RuntimeField(RuntimeFieldNameOne, FieldType.Keyword, f1 => f1 .Script(ScriptValue)) .RuntimeField(RuntimeFieldNameTwo, FieldType.Date, f2 => f2.Format(DateFormat)))), - (v, c, f) => c.Indices.Create(v, f), - (v, c, f) => c.Indices.CreateAsync(v, f), + (v, c, f) => c.Indices.Create(IndexName(v), f), + (v, c, f) => c.Indices.CreateAsync(IndexName(v), f), (v, c, r) => c.Indices.Create(r), (v, c, r) => c.Indices.CreateAsync(r) ) @@ -68,8 +68,8 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n { GetCreatedIndexMappingStep, u => u.Calls, GetMappingRequest, IGetMappingRequest, GetMappingResponse>( - v => new GetMappingRequest(v), - (v, d) => d.Index(v), + v => new GetMappingRequest(IndexName(v)), + (v, d) => d.Index(IndexName(v)), (v, c, f) => c.Indices.GetMapping(f), (v, c, f) => c.Indices.GetMappingAsync(f), (v, c, r) => c.Indices.GetMapping(r), @@ -79,10 +79,10 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n { DeleteIndexStep, u => u.Calls( - v => new DeleteIndexRequest(v), + v => new DeleteIndexRequest(IndexName(v)), (v, d) => d, - (v, c, f) => c.Indices.Delete(v, f), - (v, c, f) => c.Indices.DeleteAsync(v, f), + (v, c, f) => c.Indices.Delete(IndexName(v), f), + (v, c, f) => c.Indices.DeleteAsync(IndexName(v), f), (v, c, r) => c.Indices.Delete(r), (v, c, r) => c.Indices.DeleteAsync(r) ) @@ -90,10 +90,10 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n { CreateIndexWithoutMappingStep, u => u.Calls( - v => new CreateIndexRequest(v), - (v, d) => d.Index(v), - (v, c, f) => c.Indices.Create(v, f), - (v, c, f) => c.Indices.CreateAsync(v, f), + v => new CreateIndexRequest(IndexName(v)), + (v, d) => d, + (v, c, f) => c.Indices.Create(IndexName(v), f), + (v, c, f) => c.Indices.CreateAsync(IndexName(v), f), (v, c, r) => c.Indices.Create(r), (v, c, r) => c.Indices.CreateAsync(r) ) @@ -101,7 +101,7 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n { CreateMappingStep, u => u.Calls, PutMappingRequest, IPutMappingRequest, PutMappingResponse>( - v => new PutMappingRequest(v) + v => new PutMappingRequest(IndexName(v)) { RuntimeFields = new Nest.RuntimeFields { @@ -117,7 +117,7 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n }} } }, - (v, d) => d.Index(v) + (v, d) => d.Index(IndexName(v)) .RuntimeFields(rtf => rtf .RuntimeField(RuntimeFieldNameOne, FieldType.Keyword, f1 => f1 .Script(ScriptValue)) @@ -131,8 +131,8 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n { GetMappingStep, u => u.Calls, GetMappingRequest, IGetMappingRequest, GetMappingResponse>( - v => new GetMappingRequest(v), - (v, d) => d.Index(v), + v => new GetMappingRequest(IndexName(v)), + (v, d) => d.Index(IndexName(v)), (v, c, f) => c.Indices.GetMapping(f), (v, c, f) => c.Indices.GetMappingAsync(f), (v, c, r) => c.Indices.GetMapping(r), @@ -142,6 +142,8 @@ public RuntimeFieldsTests(WritableCluster cluster, EndpointUsage usage) : base(n }) { } + private static string IndexName(string uniqueId) => $"runtime-{uniqueId}"; + [I] public async Task CreateIndexWithRuntimeFieldsMapping() => await Assert(CreateIndexWithMappingStep, (v, r) => { r.ShouldBeValid();