Skip to content

Commit 6b3f816

Browse files
authored
Add histogram datatype (#4367)
This commit adds the histogram datatype to the client. The histogram datatype is available in Elasticsearch 7.6.0+ with at least a basic license level Closes #4358
1 parent 9bc7470 commit 6b3f816

File tree

13 files changed

+179
-3
lines changed

13 files changed

+179
-3
lines changed

src/Nest/Mapping/DynamicTemplate/SingleMapping.cs

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ public IProperty Join(Func<JoinPropertyDescriptor<T>, IJoinProperty> selector) =
6767
selector?.Invoke(new JoinPropertyDescriptor<T>());
6868

6969
/// <inheritdoc />
70+
public IProperty Histogram(Func<HistogramPropertyDescriptor<T>, IHistogramProperty> selector) =>
71+
selector?.Invoke(new HistogramPropertyDescriptor<T>());
72+
73+
/// <inheritdoc />
7074
public IProperty FieldAlias(Func<FieldAliasPropertyDescriptor<T>, IFieldAliasProperty> selector) =>
7175
selector?.Invoke(new FieldAliasPropertyDescriptor<T>());
7276

src/Nest/Mapping/Types/FieldType.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ public enum FieldType
138138
Flattened,
139139

140140
[EnumMember(Value = "shape")]
141-
Shape
141+
Shape,
142+
143+
[EnumMember(Value = "histogram")]
144+
Histogram
142145
}
143146
}

src/Nest/Mapping/Types/Properties.cs

+6
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ TReturnType Nested<TChild>(Func<NestedPropertyDescriptor<T, TChild>, INestedProp
121121
/// <inheritdoc cref="IJoinProperty"/>
122122
TReturnType Join(Func<JoinPropertyDescriptor<T>, IJoinProperty> selector);
123123

124+
/// <inheritdoc cref="IHistogramProperty"/>
125+
TReturnType Histogram(Func<HistogramPropertyDescriptor<T>, IHistogramProperty> selector);
126+
124127
/// <inheritdoc cref="IFieldAliasProperty"/>
125128
TReturnType FieldAlias(Func<FieldAliasPropertyDescriptor<T>, IFieldAliasProperty> selector);
126129

@@ -212,6 +215,9 @@ public PropertiesDescriptor<T> Object<TChild>(Func<ObjectTypeDescriptor<T, TChil
212215
/// <inheritdoc cref="IFlattenedProperty"/>
213216
public PropertiesDescriptor<T> Flattened(Func<FlattenedPropertyDescriptor<T>, IFlattenedProperty> selector) => SetProperty(selector);
214217

218+
/// <inheritdoc cref="IHistogramProperty"/>
219+
public PropertiesDescriptor<T> Histogram(Func<HistogramPropertyDescriptor<T>, IHistogramProperty> selector) => SetProperty(selector);
220+
215221
public PropertiesDescriptor<T> Custom(IProperty customType) => SetProperty(customType);
216222

217223
private PropertiesDescriptor<T> SetProperty<TDescriptor, TInterface>(Func<TDescriptor, TInterface> selector)

src/Nest/Mapping/Types/PropertyFormatter.cs

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public IProperty Deserialize(ref JsonReader reader, IJsonFormatterResolver forma
9494
case FieldType.RankFeature: return Deserialize<RankFeatureProperty>(ref segmentReader, formatterResolver);
9595
case FieldType.RankFeatures: return Deserialize<RankFeaturesProperty>(ref segmentReader, formatterResolver);
9696
case FieldType.Flattened: return Deserialize<FlattenedProperty>(ref segmentReader, formatterResolver);
97+
case FieldType.Histogram: return Deserialize<HistogramProperty>(ref segmentReader, formatterResolver);
9798
case FieldType.None:
9899
// no "type" field in the property mapping, or FieldType enum could not be parsed from typeString
99100
return Deserialize<ObjectProperty>(ref segmentReader, formatterResolver);
@@ -199,6 +200,9 @@ public void Serialize(ref JsonWriter writer, IProperty value, IJsonFormatterReso
199200
case IFlattenedProperty flattenedProperty:
200201
Serialize(ref writer, flattenedProperty, formatterResolver);
201202
break;
203+
case IHistogramProperty histogramProperty:
204+
Serialize(ref writer, histogramProperty, formatterResolver);
205+
break;
202206
case IGenericProperty genericProperty:
203207
Serialize(ref writer, genericProperty, formatterResolver);
204208
break;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Nest
2+
{
3+
public class HistogramAttribute : ElasticsearchPropertyAttributeBase, IHistogramProperty
4+
{
5+
public HistogramAttribute() : base(FieldType.Histogram) { }
6+
7+
/// <inheritdoc cref="IHistogramProperty.IgnoreMalformed"/>
8+
public bool IgnoreMalformed
9+
{
10+
get => Self.IgnoreMalformed.GetValueOrDefault();
11+
set => Self.IgnoreMalformed = value;
12+
}
13+
14+
bool? IHistogramProperty.IgnoreMalformed { get; set; }
15+
16+
private IHistogramProperty Self => this;
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Diagnostics;
2+
using System.Runtime.Serialization;
3+
using Elasticsearch.Net.Utf8Json;
4+
5+
namespace Nest
6+
{
7+
/// <summary>
8+
/// A field to store pre-aggregated numerical data representing a histogram.
9+
/// <para />
10+
/// Available in Elasticsearch 7.6.0+ with at least basic license level
11+
/// </summary>
12+
[InterfaceDataContract]
13+
public interface IHistogramProperty : IProperty
14+
{
15+
/// <summary>
16+
/// Whether to ignore malformed input values.
17+
/// </summary>
18+
[DataMember(Name = "ignore_malformed")]
19+
bool? IgnoreMalformed { get; set; }
20+
}
21+
22+
/// <inheritdoc cref="IHistogramProperty"/>
23+
[DebuggerDisplay("{DebugDisplay}")]
24+
public class HistogramProperty : PropertyBase, IHistogramProperty
25+
{
26+
public HistogramProperty() : base(FieldType.Histogram) { }
27+
28+
/// <inheritdoc />
29+
public bool? IgnoreMalformed { get; set; }
30+
}
31+
32+
/// <inheritdoc cref="IHistogramProperty"/>
33+
[DebuggerDisplay("{DebugDisplay}")]
34+
public class HistogramPropertyDescriptor<T>
35+
: PropertyDescriptorBase<HistogramPropertyDescriptor<T>, IHistogramProperty, T>, IHistogramProperty
36+
where T : class
37+
{
38+
bool? IHistogramProperty.IgnoreMalformed { get; set; }
39+
40+
public HistogramPropertyDescriptor() : base(FieldType.Histogram) { }
41+
42+
/// <inheritdoc cref="IHistogramProperty.IgnoreMalformed"/>
43+
public HistogramPropertyDescriptor<T> IgnoreMalformed(bool? ignoreMalformed = true) =>
44+
Assign(ignoreMalformed, (a, v) => a.IgnoreMalformed = v);
45+
}
46+
}

src/Nest/Mapping/Visitor/IMappingVisitor.cs

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public interface IMappingVisitor
6161
void Visit(ISearchAsYouTypeProperty property);
6262

6363
void Visit(IFlattenedProperty property);
64+
65+
void Visit(IHistogramProperty property);
6466
}
6567

6668
public class NoopMappingVisitor : IMappingVisitor
@@ -124,5 +126,7 @@ public virtual void Visit(IRankFeaturesProperty property) { }
124126
public virtual void Visit(ISearchAsYouTypeProperty property) { }
125127

126128
public virtual void Visit(IFlattenedProperty property) { }
129+
130+
public virtual void Visit(IHistogramProperty property) { }
127131
}
128132
}

src/Nest/Mapping/Visitor/IPropertyVisitor.cs

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public interface IPropertyVisitor
6060

6161
void Visit(IFlattenedProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);
6262

63+
void Visit(IHistogramProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);
64+
6365
IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);
6466

6567
bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

src/Nest/Mapping/Visitor/MappingWalker.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,6 @@ public void Accept(IProperties properties)
182182
Accept(t.Fields);
183183
});
184184
break;
185-
case FieldType.None:
186-
continue;
187185
case FieldType.Percolator:
188186
Visit<IPercolatorProperty>(field, t => { _visitor.Visit(t); });
189187
break;
@@ -253,6 +251,14 @@ public void Accept(IProperties properties)
253251
_visitor.Visit(t);
254252
});
255253
break;
254+
case FieldType.Histogram:
255+
Visit<IHistogramProperty>(field, t =>
256+
{
257+
_visitor.Visit(t);
258+
});
259+
break;
260+
case FieldType.None:
261+
continue;
256262
}
257263
}
258264
}

src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public virtual void Visit(IKeywordProperty type, PropertyInfo propertyInfo, Elas
6060

6161
public virtual void Visit(IFlattenedProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }
6262

63+
public virtual void Visit(IHistogramProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }
64+
6365
public virtual IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => null;
6466

6567
public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute)
@@ -144,6 +146,9 @@ public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchProper
144146
case IRankFeaturesProperty rankFeatures:
145147
Visit(rankFeatures, propertyInfo, attribute);
146148
break;
149+
case IHistogramProperty histogram:
150+
Visit(histogram, propertyInfo, attribute);
151+
break;
147152
}
148153
}
149154
}

tests/Tests/Indices/MappingManagement/GetMapping/GetMappingApiTest.cs

+2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ internal class TestVisitor : IMappingVisitor
211211

212212
public void Visit(IFlattenedProperty property) => Increment("flattened");
213213

214+
public void Visit(IHistogramProperty property) => Increment("histogram");
215+
214216
private void Increment(string key)
215217
{
216218
if (!Counts.ContainsKey(key)) Counts.Add(key, 0);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using Nest;
2+
3+
namespace Tests.Mapping.Types.Specialized.Histogram
4+
{
5+
public class HistogramTest
6+
{
7+
[Histogram(IgnoreMalformed = true)]
8+
public string Full { get; set; }
9+
10+
[Histogram]
11+
public string Minimal { get; set; }
12+
}
13+
14+
public class HistogramAttributeTests : AttributeTestsBase<HistogramTest>
15+
{
16+
protected override object ExpectJson => new
17+
{
18+
properties = new
19+
{
20+
full = new
21+
{
22+
type = "histogram",
23+
ignore_malformed = true
24+
},
25+
minimal = new
26+
{
27+
type = "histogram"
28+
}
29+
}
30+
};
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using Elastic.Xunit.XunitPlumbing;
3+
using Nest;
4+
using Tests.Core.ManagedElasticsearch.Clusters;
5+
using Tests.Domain;
6+
using Tests.Framework.EndpointTests.TestState;
7+
8+
namespace Tests.Mapping.Types.Specialized.Histogram
9+
{
10+
[SkipVersion("<7.6.0", "Introduced in 7.6.0")]
11+
public class HistogramPropertyTests : PropertyTestsBase
12+
{
13+
public HistogramPropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
14+
15+
protected override object ExpectJson => new
16+
{
17+
properties = new
18+
{
19+
name = new
20+
{
21+
type = "histogram",
22+
ignore_malformed = true,
23+
}
24+
}
25+
};
26+
27+
protected override Func<PropertiesDescriptor<Project>, IPromise<IProperties>> FluentProperties => f => f
28+
.Histogram(s => s
29+
.Name(p => p.Name)
30+
.IgnoreMalformed()
31+
);
32+
33+
34+
protected override IProperties InitializerProperties => new Properties
35+
{
36+
{
37+
"name", new HistogramProperty
38+
{
39+
IgnoreMalformed = true,
40+
}
41+
}
42+
};
43+
}
44+
}

0 commit comments

Comments
 (0)