Skip to content

Add support for wildcard property #4890

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 2 commits into from
Jul 31, 2020
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 @@ -141,6 +141,10 @@ public IProperty SearchAsYouType(Func<SearchAsYouTypePropertyDescriptor<T>, ISea
public IProperty ConstantKeyword(Func<ConstantKeywordPropertyDescriptor<T>, IConstantKeywordProperty> selector) =>
selector?.Invoke(new ConstantKeywordPropertyDescriptor<T>());

/// <inheritdoc />
public IProperty Wildcard(Func<WildcardPropertyDescriptor<T>, IWildcardProperty> selector) =>
selector?.Invoke(new WildcardPropertyDescriptor<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) =>
selector.InvokeOrDefault(new NumberPropertyDescriptor<T>().Name(field).Type(NumberType.Integer));
Expand Down
5 changes: 4 additions & 1 deletion src/Nest/Mapping/Types/FieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ public enum FieldType
Histogram,

[EnumMember(Value = "constant_keyword")]
ConstantKeyword
ConstantKeyword,

[EnumMember(Value = "wildcard")]
Wildcard,
}
}
7 changes: 7 additions & 0 deletions src/Nest/Mapping/Types/Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ TReturnType Nested<TChild>(Func<NestedPropertyDescriptor<T, TChild>, INestedProp

/// <inheritdoc cref="IConstantKeywordProperty"/>
TReturnType ConstantKeyword(Func<ConstantKeywordPropertyDescriptor<T>, IConstantKeywordProperty> selector);

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

public partial class PropertiesDescriptor<T> where T : class
Expand Down Expand Up @@ -229,6 +232,10 @@ public PropertiesDescriptor<T> Object<TChild>(Func<ObjectTypeDescriptor<T, TChil
public PropertiesDescriptor<T> ConstantKeyword(Func<ConstantKeywordPropertyDescriptor<T>, IConstantKeywordProperty> selector) =>
SetProperty(selector);

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

public PropertiesDescriptor<T> Custom(IProperty customType) => SetProperty(customType);

private PropertiesDescriptor<T> SetProperty<TDescriptor, TInterface>(Func<TDescriptor, TInterface> selector)
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 @@ -98,6 +98,7 @@ public IProperty Deserialize(ref JsonReader reader, IJsonFormatterResolver forma
case FieldType.Flattened: return Deserialize<FlattenedProperty>(ref segmentReader, formatterResolver);
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.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 @@ -209,6 +210,9 @@ public void Serialize(ref JsonWriter writer, IProperty value, IJsonFormatterReso
case IConstantKeywordProperty constantKeywordProperty:
Serialize(ref writer, constantKeywordProperty, formatterResolver);
break;
case IWildcardProperty wildcardProperty:
Serialize(ref writer, wildcardProperty, formatterResolver);
break;
case IGenericProperty genericProperty:
Serialize(ref writer, genericProperty, formatterResolver);
break;
Expand Down
26 changes: 26 additions & 0 deletions src/Nest/Mapping/Types/Specialized/Wildcard/WildcardAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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
{
/// <inheritdoc cref="IWildcardProperty"/>
public class WildcardAttribute : ElasticsearchPropertyAttributeBase, IWildcardProperty
{
public WildcardAttribute() : base(FieldType.Wildcard) { }

int? IWildcardProperty.IgnoreAbove { get; set; }

private IWildcardProperty Self => this;

/// <inheritdoc cref="IWildcardProperty.IgnoreAbove" />
public int IgnoreAbove
{
get => Self.IgnoreAbove.GetValueOrDefault(2147483647);
set => Self.IgnoreAbove = value;
}

/// <inheritdoc cref="IWildcardProperty.NullValue" />
public string NullValue { get; set; }
}
}
62 changes: 62 additions & 0 deletions src/Nest/Mapping/Types/Specialized/Wildcard/WildcardProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// 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 System.Runtime.Serialization;
using Elasticsearch.Net.Utf8Json;

namespace Nest
{
/// <summary>
/// A wildcard field stores values optimised for wildcard grep-like queries.
/// <para />
/// Available in Elasticsearch 7.9.0+ with at least a basic license level
/// </summary>
[InterfaceDataContract]
public interface IWildcardProperty : IProperty
{
/// <summary>
/// Do not index any string longer than this value. Defaults to 2147483647 so that all values would be accepted.
/// </summary>
[DataMember(Name = "ignore_above")]
int? IgnoreAbove { get; set; }

/// <summary>
/// Accepts a string value which is substituted for any explicit null values. Defaults to null, which means the field is treated as missing.
/// </summary>
[DataMember(Name ="null_value")]
string NullValue { get; set; }
}

/// <inheritdoc cref="IWildcardProperty" />
[DebuggerDisplay("{DebugDisplay}")]
public class WildcardProperty : PropertyBase, IWildcardProperty
{
public WildcardProperty() : base(FieldType.Wildcard) { }

/// <inheritdoc cref="IWildcardProperty.IgnoreAbove" />
public int? IgnoreAbove { get; set; }

/// <inheritdoc cref="IWildcardProperty.NullValue" />
public string NullValue { get; set; }
}

/// <inheritdoc cref="IWildcardProperty" />
[DebuggerDisplay("{DebugDisplay}")]
public class WildcardPropertyDescriptor<T>
: PropertyDescriptorBase<WildcardPropertyDescriptor<T>, IWildcardProperty, T>, IWildcardProperty
where T : class
{
public WildcardPropertyDescriptor() : base(FieldType.Wildcard) { }

int? IWildcardProperty.IgnoreAbove { get; set; }
string IWildcardProperty.NullValue { get; set; }

/// <inheritdoc cref="IWildcardProperty.IgnoreAbove" />
public WildcardPropertyDescriptor<T> IgnoreAbove(int? ignoreAbove) => Assign(ignoreAbove, (a, v) => a.IgnoreAbove = v);

/// <inheritdoc cref="IWildcardProperty.NullValue" />
public WildcardPropertyDescriptor<T> NullValue(string nullValue) => Assign(nullValue, (a, v) => a.NullValue = v);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 Elastic.Elasticsearch.Xunit.XunitPlumbing;
using Nest;

namespace Tests.Mapping.Types.Specialized.Wildcard
{
public class WildcardTest
{
[Wildcard(IgnoreAbove = 512, NullValue = "foo")]
public string Full { get; set; }

[Wildcard]
public string Simple { get; set; }
}

[SkipVersion("<7.9.0", "introduced in 7.9.0")]
public class WildcardAttributeTests : AttributeTestsBase<WildcardTest>
{
protected override object ExpectJson => new
{
properties = new
{
full = new
{
type = "wildcard",
ignore_above = 512,
null_value = "foo"
},
simple = new
{
type = "wildcard"
}
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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.Wildcard
{
[SkipVersion("<7.9.0", "introduced in 7.9.0")]
public class WildcardPropertyTests : PropertyTestsBase
{
public WildcardPropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }

protected override object ExpectJson => new
{
properties = new
{
description = new
{
type = "wildcard"
}
}
};

protected override Func<PropertiesDescriptor<Project>, IPromise<IProperties>> FluentProperties => f => f
.Wildcard(s => s
.Name(n => n.Description)
);

protected override IProperties InitializerProperties => new Properties
{
{
"description", new WildcardProperty()
}
};
}
}