Skip to content

Commit b29f03d

Browse files
authored
Support for calculated numeric fields (#5622)
1 parent 7319550 commit b29f03d

File tree

4 files changed

+121
-3
lines changed

4 files changed

+121
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Runtime.Serialization;
6+
using Elasticsearch.Net;
7+
8+
namespace Nest
9+
{
10+
[StringEnum]
11+
public enum OnScriptError
12+
{
13+
[EnumMember(Value = "fail")]
14+
Fail,
15+
[EnumMember(Value = "continue")]
16+
Continue
17+
}
18+
}

src/Nest/Mapping/Types/Core/Number/NumberAttribute.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,28 @@ public double ScalingFactor
5252
set => Self.ScalingFactor = value;
5353
}
5454

55+
public IInlineScript Script
56+
{
57+
get => Self.Script;
58+
set => Self.Script = value;
59+
}
60+
61+
public OnScriptError OnScriptError
62+
{
63+
get => Self.OnScriptError.GetValueOrDefault();
64+
set => Self.OnScriptError = value;
65+
}
66+
5567
double? INumberProperty.Boost { get; set; }
5668
bool? INumberProperty.Coerce { get; set; }
5769
INumericFielddata INumberProperty.Fielddata { get; set; }
5870
bool? INumberProperty.IgnoreMalformed { get; set; }
59-
6071
bool? INumberProperty.Index { get; set; }
6172
double? INumberProperty.NullValue { get; set; }
6273
double? INumberProperty.ScalingFactor { get; set; }
74+
IInlineScript INumberProperty.Script { get; set; }
75+
OnScriptError? INumberProperty.OnScriptError { get; set; }
76+
6377
private INumberProperty Self => this;
6478
}
6579
}

src/Nest/Mapping/Types/Core/Number/NumberProperty.cs

+36-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ public interface INumberProperty : IDocValuesProperty
3737

3838
[DataMember(Name = "scaling_factor")]
3939
double? ScalingFactor { get; set; }
40+
41+
/// <summary>
42+
/// If this parameter is set, then the field will index values generated by this script, rather than reading the values directly from the source.
43+
/// If a value is set for this field on the input document, then the document will be rejected with an error.
44+
/// Scripts are in the same format as their runtime equivalent. Scripts can only be configured on long and double field types.
45+
/// </summary>
46+
[DataMember(Name = "script")]
47+
IInlineScript Script { get; set; }
48+
49+
/// <summary>
50+
/// Defines what to do if the script defined by the `script` parameter throws an error at indexing time.Accepts `reject` (default), which
51+
/// will cause the entire document to be rejected, and `ignore`, which will register the field in the document's ignored metadata field and
52+
/// continue indexing.This parameter can only be set if the `script` field is also set.
53+
/// </summary>
54+
[DataMember(Name = "on_script_error")]
55+
OnScriptError? OnScriptError { get; set; }
4056
}
4157

4258
[DebuggerDisplay("{DebugDisplay}")]
@@ -50,10 +66,15 @@ public NumberProperty(NumberType type) : base(type.ToFieldType()) { }
5066
public bool? Coerce { get; set; }
5167
public INumericFielddata Fielddata { get; set; }
5268
public bool? IgnoreMalformed { get; set; }
53-
5469
public bool? Index { get; set; }
5570
public double? NullValue { get; set; }
5671
public double? ScalingFactor { get; set; }
72+
73+
/// <inheritdoc />
74+
public IInlineScript Script { get; set; }
75+
76+
/// <inheritdoc />
77+
public OnScriptError? OnScriptError { get; set; }
5778
}
5879

5980
[DebuggerDisplay("{DebugDisplay}")]
@@ -71,10 +92,11 @@ protected NumberPropertyDescriptorBase(FieldType type) : base(type) { }
7192
bool? INumberProperty.Coerce { get; set; }
7293
INumericFielddata INumberProperty.Fielddata { get; set; }
7394
bool? INumberProperty.IgnoreMalformed { get; set; }
74-
7595
bool? INumberProperty.Index { get; set; }
7696
double? INumberProperty.NullValue { get; set; }
7797
double? INumberProperty.ScalingFactor { get; set; }
98+
IInlineScript INumberProperty.Script { get; set; }
99+
OnScriptError? INumberProperty.OnScriptError { get; set; }
78100

79101
public TDescriptor Type(NumberType? type) => Assign(type?.GetStringValue(), (a, v) => a.Type = v);
80102

@@ -93,6 +115,18 @@ public TDescriptor Fielddata(Func<NumericFielddataDescriptor, INumericFielddata>
93115
Assign(selector(new NumericFielddataDescriptor()), (a, v) => a.Fielddata = v);
94116

95117
public TDescriptor ScalingFactor(double? scalingFactor) => Assign(scalingFactor, (a, v) => a.ScalingFactor = v);
118+
119+
/// <inheritdoc cref="INumberProperty.Script" />
120+
public TDescriptor Script(IInlineScript inlineScript) => Assign(inlineScript, (a, v) => a.Script = v);
121+
122+
/// <inheritdoc cref="INumberProperty.Script" />
123+
public TDescriptor Script(string source) => Assign(source, (a, v) => a.Script = new InlineScript(source));
124+
125+
/// <inheritdoc cref="INumberProperty.Script" />
126+
public TDescriptor Script(Func<InlineScriptDescriptor, IInlineScript> selector) => Assign(selector, (a, v) => a.Script = v?.Invoke(new InlineScriptDescriptor()));
127+
128+
/// <inheritdoc cref="INumberProperty.OnScriptError" />
129+
public TDescriptor OnScriptError(OnScriptError? onScriptError) => Assign(onScriptError, (a, v) => a.OnScriptError = v);
96130
}
97131

98132
public class NumberPropertyDescriptor<T> : NumberPropertyDescriptorBase<NumberPropertyDescriptor<T>, INumberProperty, T>

tests/Tests/Mapping/Types/Core/Number/NumberPropertyTests.cs

+52
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information
44

55
using System;
6+
using System.Collections.Generic;
67
using Elastic.Elasticsearch.Xunit.XunitPlumbing;
78
using Nest;
89
using Tests.Core.ManagedElasticsearch.Clusters;
@@ -166,4 +167,55 @@ public UnsignedLongNumberPropertyTests(WritableCluster cluster, EndpointUsage us
166167
}
167168
};
168169
}
170+
171+
[SkipVersion("<7.13.0", "Script support added in 7.13.0")]
172+
public class ScriptedNumberPropertyTests : PropertyTestsBase
173+
{
174+
public ScriptedNumberPropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
175+
176+
protected override object ExpectJson => new
177+
{
178+
properties = new
179+
{
180+
doublesCommits = new
181+
{
182+
type = "long",
183+
script = new
184+
{
185+
source = "emit((long)(doc['numberOfCommits'].value * params.multiplier))",
186+
@params = new Dictionary<string, int>
187+
{
188+
{"multiplier", 2 }
189+
}
190+
},
191+
on_script_error = "continue"
192+
}
193+
}
194+
};
195+
196+
protected override Func<PropertiesDescriptor<Project>, IPromise<IProperties>> FluentProperties => f => f
197+
.Number(n => n
198+
.Name("doublesCommits")
199+
.Type(NumberType.Long)
200+
.Script(s => s.Source("emit((long)(doc['numberOfCommits'].value * params.multiplier))").Params(p => p.Add("multiplier", 2)))
201+
.OnScriptError(OnScriptError.Continue)
202+
);
203+
204+
protected override IProperties InitializerProperties => new Properties
205+
{
206+
{
207+
"doublesCommits", new NumberProperty(NumberType.Long)
208+
{
209+
Script = new InlineScript("emit((long)(doc['numberOfCommits'].value * params.multiplier))")
210+
{
211+
Params = new Dictionary<string, object>
212+
{
213+
{ "multiplier", 2 }
214+
}
215+
},
216+
OnScriptError = OnScriptError.Continue
217+
}
218+
}
219+
};
220+
}
169221
}

0 commit comments

Comments
 (0)