Skip to content

Implement version field type #5200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Nest/Mapping/DynamicTemplate/SingleMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ public IProperty ConstantKeyword(Func<ConstantKeywordPropertyDescriptor<T>, ICon
/// <inheritdoc />
public IProperty Wildcard(Func<WildcardPropertyDescriptor<T>, IWildcardProperty> selector) =>
selector?.Invoke(new WildcardPropertyDescriptor<T>());

/// <inheritdoc />
public IProperty Version(Func<VersionPropertyDescriptor<T>, IVersionProperty> selector) =>
selector?.Invoke(new VersionPropertyDescriptor<T>());

#pragma warning disable CS3001 // Argument type is not CLS-compliant
public IProperty Scalar(Expression<Func<T, int>> field, Func<NumberPropertyDescriptor<T>, INumberProperty> selector = null) =>
Expand Down
6 changes: 6 additions & 0 deletions src/Nest/Mapping/Types/FieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,11 @@ public enum FieldType

[EnumMember(Value = "point")]
Point,

/// <summary>
/// Version field type for storing semver compatible version numbers.
/// </summary>
[EnumMember(Value = "version")]
Version
}
}
9 changes: 7 additions & 2 deletions src/Nest/Mapping/Types/Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ TReturnType Nested<TChild>(Func<NestedPropertyDescriptor<T, TChild>, INestedProp

/// <inheritdoc cref="IWildcardProperty"/>
TReturnType Wildcard(Func<WildcardPropertyDescriptor<T>, IWildcardProperty> selector);

/// <inheritdoc cref="IVersionProperty"/>
TReturnType Version(Func<VersionPropertyDescriptor<T>, IVersionProperty> selector);
}

public partial class PropertiesDescriptor<T> where T : class
Expand Down Expand Up @@ -263,8 +266,10 @@ public PropertiesDescriptor<T> ConstantKeyword(Func<ConstantKeywordPropertyDescr
SetProperty(selector);

/// <inheritdoc cref="IWildcardProperty"/>
public PropertiesDescriptor<T> Wildcard(Func<WildcardPropertyDescriptor<T>, IWildcardProperty> selector) =>
SetProperty(selector);
public PropertiesDescriptor<T> Wildcard(Func<WildcardPropertyDescriptor<T>, IWildcardProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IVersionProperty"/>
public PropertiesDescriptor<T> Version(Func<VersionPropertyDescriptor<T>, IVersionProperty> selector) => SetProperty(selector);

/// <summary>
/// Map a custom property.
Expand Down
4 changes: 4 additions & 0 deletions src/Nest/Mapping/Types/PropertyFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public IProperty Deserialize(ref JsonReader reader, IJsonFormatterResolver forma
case FieldType.Histogram: return Deserialize<HistogramProperty>(ref segmentReader, formatterResolver);
case FieldType.ConstantKeyword: return Deserialize<ConstantKeywordProperty>(ref segmentReader, formatterResolver);
case FieldType.Wildcard: return Deserialize<WildcardProperty>(ref segmentReader, formatterResolver);
case FieldType.Version: return Deserialize<VersionProperty>(ref segmentReader, formatterResolver);
case FieldType.None:
// no "type" field in the property mapping, or FieldType enum could not be parsed from typeString
return Deserialize<ObjectProperty>(ref segmentReader, formatterResolver);
Expand Down Expand Up @@ -220,6 +221,9 @@ public void Serialize(ref JsonWriter writer, IProperty value, IJsonFormatterReso
case IGenericProperty genericProperty:
Serialize(ref writer, genericProperty, formatterResolver);
break;
case IVersionProperty versionProperty:
Serialize(ref writer, versionProperty, formatterResolver);
break;
default:
var formatter = formatterResolver.GetFormatter<object>();
formatter.Serialize(ref writer, value, formatterResolver);
Expand Down
13 changes: 13 additions & 0 deletions src/Nest/Mapping/Types/Specialized/Version/VersionAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// 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

namespace Nest
{
public class VersionAttribute : ElasticsearchPropertyAttributeBase, IVersionProperty
{
public VersionAttribute() : base(FieldType.Version) { }

private IVersionProperty Self => this;
}
}
33 changes: 33 additions & 0 deletions src/Nest/Mapping/Types/Specialized/Version/VersionProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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.Diagnostics;
using Elasticsearch.Net.Utf8Json;

namespace Nest
{
/// <summary>
/// A version field can index/store semver version numbers.
/// </summary>
[InterfaceDataContract]
public interface IVersionProperty : IProperty
{
}

/// <inheritdoc cref="IVersionProperty"/>
[DebuggerDisplay("{DebugDisplay}")]
public class VersionProperty : PropertyBase, IVersionProperty
{
public VersionProperty() : base(FieldType.Version) { }
}

/// <inheritdoc cref="IVersionProperty" />
[DebuggerDisplay("{DebugDisplay}")]
public class VersionPropertyDescriptor<T>
: PropertyDescriptorBase<VersionPropertyDescriptor<T>, IVersionProperty, T>, IVersionProperty
where T : class
{
public VersionPropertyDescriptor() : base(FieldType.Version) { }
}
}
4 changes: 4 additions & 0 deletions src/Nest/Mapping/Visitor/IMappingVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ public interface IMappingVisitor
void Visit(IHistogramProperty property);

void Visit(IConstantKeywordProperty property);

void Visit(IVersionProperty property);
}

public class NoopMappingVisitor : IMappingVisitor
Expand Down Expand Up @@ -140,5 +142,7 @@ public virtual void Visit(IFlattenedProperty property) { }
public virtual void Visit(IHistogramProperty property) { }

public virtual void Visit(IConstantKeywordProperty property) { }

public virtual void Visit(IVersionProperty property) { }
}
}
2 changes: 2 additions & 0 deletions src/Nest/Mapping/Visitor/IPropertyVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public interface IPropertyVisitor

void Visit(IWildcardProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

void Visit(IVersionProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

bool SkipProperty(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);
Expand Down
6 changes: 6 additions & 0 deletions src/Nest/Mapping/Visitor/MappingWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ public void Accept(IProperties properties)
_visitor.Visit(t);
});
break;
case FieldType.Version:
Visit<IVersionProperty>(field, t =>
{
_visitor.Visit(t);
});
break;
case FieldType.None:
continue;
}
Expand Down
7 changes: 6 additions & 1 deletion src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public virtual void Visit(IFieldAliasProperty type, PropertyInfo propertyInfo, E

public virtual void Visit(IWildcardProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }

public virtual void Visit(IVersionProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }

public virtual IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) => null;

public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute)
Expand Down Expand Up @@ -169,7 +171,7 @@ public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchProper
break;
case IPointProperty point:
Visit(point, propertyInfo, attribute);
break;
break;
case ISearchAsYouTypeProperty searchAsYouType:
Visit(searchAsYouType, propertyInfo, attribute);
break;
Expand All @@ -179,6 +181,9 @@ public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchProper
case IFieldAliasProperty fieldAlias:
Visit(fieldAlias, propertyInfo, attribute);
break;
case IVersionProperty version:
Visit(version, propertyInfo, attribute);
break;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public class FieldTypes : IsADictionaryBase<string, FieldCapabilities>
public FieldCapabilities Integer => BackingDictionary.TryGetValue("integer", out var f) ? f : null;
public FieldCapabilities IntegerRange => BackingDictionary.TryGetValue("integer_range", out var f) ? f : null;
public FieldCapabilities Ip => BackingDictionary.TryGetValue("ip", out var f) ? f : null;

public FieldCapabilities Keyword => BackingDictionary.TryGetValue("keyword", out var f) ? f : null;
public FieldCapabilities Long => BackingDictionary.TryGetValue("long", out var f) ? f : null;
public FieldCapabilities LongRange => BackingDictionary.TryGetValue("long_range", out var f) ? f : null;
Expand All @@ -71,6 +70,7 @@ public class FieldTypes : IsADictionaryBase<string, FieldCapabilities>
public FieldCapabilities Uid => BackingDictionary.TryGetValue("_uid", out var f) ? f : null;
public FieldCapabilities ParentJoin => BackingDictionary.TryGetValue("_parent_join", out var f) ? f : null;
public FieldCapabilities Version => BackingDictionary.TryGetValue("_version", out var f) ? f : null;
public FieldCapabilities VersionField => BackingDictionary.TryGetValue("version", out var f) ? f : null;
}

public class FieldCapabilities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ internal class TestVisitor : IMappingVisitor

public void Visit(IConstantKeywordProperty property) => Increment("constant_keyword");

public void Visit(IVersionProperty property) => Increment("version");

private void Increment(string key)
{
if (!Counts.ContainsKey(key)) Counts.Add(key, 0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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 Nest;

namespace Tests.Mapping.Types.Specialized.Version
{
public class VersionTest
{
[Version]
public string VersionNumber { get; set; }
}

public class VersionAttributeTests : AttributeTestsBase<VersionTest>
{
protected override object ExpectJson => new
{
properties = new
{
versionNumber = new
{
type = "version"
}
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// 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 Elastic.Elasticsearch.Xunit.XunitPlumbing;
using Nest;
using Tests.Core.ManagedElasticsearch.Clusters;
using Tests.Domain;
using Tests.Framework.EndpointTests.TestState;

namespace Tests.Mapping.Types.Specialized.Version
{
[SkipVersion("<7.10.0", "Version property introduced in 7.10.0")]
public class VersionPropertyTests : PropertyTestsBase
{
public VersionPropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }

protected override object ExpectJson => new
{
properties = new
{
name = new
{
type = "version"
}
}
};

protected override Func<PropertiesDescriptor<Project>, IPromise<IProperties>> FluentProperties => f => f
.Version(s => s
.Name(p => p.Name)
);

protected override IProperties InitializerProperties => new Properties
{
{
"name", new VersionProperty
{
}
}
};
}
}