Skip to content

Commit

Permalink
Add Point property for mapping point datatype
Browse files Browse the repository at this point in the history
Relates: #4718, elastic/elasticsearch#53804

This commit adds a Point property to map the new point data type.
A CartesianPoint type is introduced to model points.
  • Loading branch information
russcam committed Sep 15, 2020
1 parent aeeba1d commit b8e06f7
Show file tree
Hide file tree
Showing 17 changed files with 543 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/Nest/Mapping/DynamicTemplate/SingleMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public IProperty GeoShape(Func<GeoShapePropertyDescriptor<T>, IGeoShapeProperty>
public IProperty Shape(Func<ShapePropertyDescriptor<T>, IShapeProperty> selector) =>
selector?.Invoke(new ShapePropertyDescriptor<T>());

/// <inheritdoc />
public IProperty Point(Func<PointPropertyDescriptor<T>, IPointProperty> selector) =>
selector?.Invoke(new PointPropertyDescriptor<T>());

/// <inheritdoc />
public IProperty IntegerRange(Func<IntegerRangePropertyDescriptor<T>, IIntegerRangeProperty> selector) =>
selector?.Invoke(new IntegerRangePropertyDescriptor<T>());
Expand Down
3 changes: 3 additions & 0 deletions src/Nest/Mapping/Types/FieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,8 @@ public enum FieldType

[EnumMember(Value = "wildcard")]
Wildcard,

[EnumMember(Value = "point")]
Point,
}
}
33 changes: 33 additions & 0 deletions src/Nest/Mapping/Types/Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ TReturnType Nested<TChild>(Func<NestedPropertyDescriptor<T, TChild>, INestedProp
/// <inheritdoc cref="IShapeProperty"/>
TReturnType Shape(Func<ShapePropertyDescriptor<T>, IShapeProperty> selector);

/// <inheritdoc cref="IPointProperty"/>
TReturnType Point(Func<PointPropertyDescriptor<T>, IPointProperty> selector);

/// <inheritdoc cref="ICompletionProperty"/>
TReturnType Completion(Func<CompletionPropertyDescriptor<T>, ICompletionProperty> selector);

Expand Down Expand Up @@ -156,42 +159,64 @@ public PropertiesDescriptor() : base(new Properties<T>()) { }

public PropertiesDescriptor(IProperties properties) : base(properties ?? new Properties<T>()) { }

/// <inheritdoc cref="IBinaryProperty"/>
public PropertiesDescriptor<T> Binary(Func<BinaryPropertyDescriptor<T>, IBinaryProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IBooleanProperty"/>
public PropertiesDescriptor<T> Boolean(Func<BooleanPropertyDescriptor<T>, IBooleanProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="ICompletionProperty"/>
public PropertiesDescriptor<T> Completion(Func<CompletionPropertyDescriptor<T>, ICompletionProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IDateProperty"/>
public PropertiesDescriptor<T> Date(Func<DatePropertyDescriptor<T>, IDateProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IDateNanosProperty"/>
public PropertiesDescriptor<T> DateNanos(Func<DateNanosPropertyDescriptor<T>, IDateNanosProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IDateRangeProperty"/>
public PropertiesDescriptor<T> DateRange(Func<DateRangePropertyDescriptor<T>, IDateRangeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IDoubleRangeProperty"/>
public PropertiesDescriptor<T> DoubleRange(Func<DoubleRangePropertyDescriptor<T>, IDoubleRangeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IFloatRangeProperty"/>
public PropertiesDescriptor<T> FloatRange(Func<FloatRangePropertyDescriptor<T>, IFloatRangeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IGeoPointProperty"/>
public PropertiesDescriptor<T> GeoPoint(Func<GeoPointPropertyDescriptor<T>, IGeoPointProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IGeoShapeProperty"/>
public PropertiesDescriptor<T> GeoShape(Func<GeoShapePropertyDescriptor<T>, IGeoShapeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IShapeProperty"/>
public PropertiesDescriptor<T> Shape(Func<ShapePropertyDescriptor<T>, IShapeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IPointProperty"/>
public PropertiesDescriptor<T> Point(Func<PointPropertyDescriptor<T>, IPointProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IIntegerRangeProperty"/>
public PropertiesDescriptor<T> IntegerRange(Func<IntegerRangePropertyDescriptor<T>, IIntegerRangeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IIpProperty"/>
public PropertiesDescriptor<T> Ip(Func<IpPropertyDescriptor<T>, IIpProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IIpRangeProperty"/>
public PropertiesDescriptor<T> IpRange(Func<IpRangePropertyDescriptor<T>, IIpRangeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IJoinProperty"/>
public PropertiesDescriptor<T> Join(Func<JoinPropertyDescriptor<T>, IJoinProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IKeywordProperty"/>
public PropertiesDescriptor<T> Keyword(Func<KeywordPropertyDescriptor<T>, IKeywordProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="ILongRangeProperty"/>
public PropertiesDescriptor<T> LongRange(Func<LongRangePropertyDescriptor<T>, ILongRangeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IMurmur3HashProperty"/>
public PropertiesDescriptor<T> Murmur3Hash(Func<Murmur3HashPropertyDescriptor<T>, IMurmur3HashProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="INestedProperty"/>
public PropertiesDescriptor<T> Nested<TChild>(Func<NestedPropertyDescriptor<T, TChild>, INestedProperty> selector)
where TChild : class => SetProperty(selector);

Expand All @@ -202,18 +227,23 @@ public PropertiesDescriptor<T> Nested<TChild>(Func<NestedPropertyDescriptor<T, T
/// </summary>
public PropertiesDescriptor<T> Number(Func<NumberPropertyDescriptor<T>, INumberProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IObjectProperty"/>
public PropertiesDescriptor<T> Object<TChild>(Func<ObjectTypeDescriptor<T, TChild>, IObjectProperty> selector)
where TChild : class => SetProperty(selector);

/// <inheritdoc cref="IPercolatorProperty"/>
public PropertiesDescriptor<T> Percolator(Func<PercolatorPropertyDescriptor<T>, IPercolatorProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="ITextProperty"/>
public PropertiesDescriptor<T> Text(Func<TextPropertyDescriptor<T>, ITextProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="ISearchAsYouTypeProperty"/>
public PropertiesDescriptor<T> SearchAsYouType(Func<SearchAsYouTypePropertyDescriptor<T>, ISearchAsYouTypeProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="ITokenCountProperty"/>
public PropertiesDescriptor<T> TokenCount(Func<TokenCountPropertyDescriptor<T>, ITokenCountProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IFieldAliasProperty"/>
public PropertiesDescriptor<T> FieldAlias(Func<FieldAliasPropertyDescriptor<T>, IFieldAliasProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IRankFeatureProperty"/>
Expand All @@ -236,6 +266,9 @@ public PropertiesDescriptor<T> ConstantKeyword(Func<ConstantKeywordPropertyDescr
public PropertiesDescriptor<T> Wildcard(Func<WildcardPropertyDescriptor<T>, IWildcardProperty> selector) =>
SetProperty(selector);

/// <summary>
/// Map a custom property.
/// </summary>
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 @@ -81,6 +81,7 @@ public IProperty Deserialize(ref JsonReader reader, IJsonFormatterResolver forma
case FieldType.GeoPoint: return Deserialize<GeoPointProperty>(ref segmentReader, formatterResolver);
case FieldType.GeoShape: return Deserialize<GeoShapeProperty>(ref segmentReader, formatterResolver);
case FieldType.Shape: return Deserialize<ShapeProperty>(ref segmentReader, formatterResolver);
case FieldType.Point: return Deserialize<PointProperty>(ref segmentReader, formatterResolver);
case FieldType.Completion: return Deserialize<CompletionProperty>(ref segmentReader, formatterResolver);
case FieldType.TokenCount: return Deserialize<TokenCountProperty>(ref segmentReader, formatterResolver);
case FieldType.Murmur3Hash: return Deserialize<Murmur3HashProperty>(ref segmentReader, formatterResolver);
Expand Down Expand Up @@ -159,6 +160,9 @@ public void Serialize(ref JsonWriter writer, IProperty value, IJsonFormatterReso
case IShapeProperty shapeProperty:
Serialize(ref writer, shapeProperty, formatterResolver);
break;
case IPointProperty pointProperty:
Serialize(ref writer, pointProperty, formatterResolver);
break;
case ICompletionProperty completionProperty:
Serialize(ref writer, completionProperty, formatterResolver);
break;
Expand Down
39 changes: 39 additions & 0 deletions src/Nest/Mapping/Types/Specialized/Point/PointAttribute.cs
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

namespace Nest
{
/// <inheritdoc cref="IPointProperty" />
public class PointAttribute : ElasticsearchPropertyAttributeBase, IPointProperty
{
public PointAttribute() : base(FieldType.Point) { }

bool? IPointProperty.IgnoreMalformed { get; set; }
bool? IPointProperty.IgnoreZValue { get; set; }
CartesianPoint IPointProperty.NullValue { get; set; }

private IPointProperty Self => this;

/// <inheritdoc cref="IPointProperty.IgnoreMalformed" />
public bool IgnoreMalformed
{
get => Self.IgnoreMalformed.GetValueOrDefault(false);
set => Self.IgnoreMalformed = value;
}

/// <inheritdoc cref="IPointProperty.IgnoreZValue" />
public bool IgnoreZValue
{
get => Self.IgnoreZValue.GetValueOrDefault(true);
set => Self.IgnoreZValue = value;
}

/// <inheritdoc cref="IPointProperty.NullValue" />
public CartesianPoint NullValue
{
get => Self.NullValue;
set => Self.NullValue = value;
}
}
}
87 changes: 87 additions & 0 deletions src/Nest/Mapping/Types/Specialized/Point/PointProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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>
/// The point datatype facilitates the indexing of and searching
/// arbitrary `x, y` pairs that fall in a 2-dimensional planar
/// coordinate system.
/// <para />
/// You can query documents using this type using <see cref="IShapeQuery"/>.
/// <para />
/// Available in Elasticsearch 7.8.0+ with at least basic license level
/// </summary>
[InterfaceDataContract]
public interface IPointProperty : IProperty
{
/// <summary>
/// If <c>true</c>, malformed geojson shapes are ignored. If false (default),
/// malformed geojson shapes throw an exception and reject the whole document.
/// </summary>
[DataMember(Name ="ignore_malformed")]
bool? IgnoreMalformed { get; set; }

/// <summary>
/// If true (default) three dimension points will be accepted (stored in source) but
/// only x and y values will be indexed; the third dimension is ignored. If false,
/// geo-points containing any more than x and y (two dimensions) values throw
/// an exception and reject the whole document.
/// </summary>
[DataMember(Name ="ignore_z_value")]
bool? IgnoreZValue { get; set; }

/// <summary>
/// Accepts an point 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")]
CartesianPoint NullValue { get; set; }
}

/// <inheritdoc cref="IPointProperty" />
[DebuggerDisplay("{DebugDisplay}")]
public class PointProperty : PropertyBase, IPointProperty
{
public PointProperty() : base(FieldType.Point) { }

/// <inheritdoc />
public bool? IgnoreMalformed { get; set; }

/// <inheritdoc />
public bool? IgnoreZValue { get; set; }

/// <inheritdoc />
public CartesianPoint NullValue { get; set; }
}

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

bool? IPointProperty.IgnoreMalformed { get; set; }
bool? IPointProperty.IgnoreZValue { get; set; }
CartesianPoint IPointProperty.NullValue { get; set; }

/// <inheritdoc cref="IPointProperty.IgnoreMalformed" />
public PointPropertyDescriptor<T> IgnoreMalformed(bool? ignoreMalformed = true) =>
Assign(ignoreMalformed, (a, v) => a.IgnoreMalformed = v);

/// <inheritdoc cref="IPointProperty.IgnoreZValue" />
public PointPropertyDescriptor<T> IgnoreZValue(bool? ignoreZValue = true) =>
Assign(ignoreZValue, (a, v) => a.IgnoreZValue = v);

/// <inheritdoc cref="IPointProperty.NullValue" />
public PointPropertyDescriptor<T> NullValue(CartesianPoint nullValue) =>
Assign(nullValue, (a, v) => a.NullValue = v);
}
}
4 changes: 4 additions & 0 deletions src/Nest/Mapping/Visitor/IMappingVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public interface IMappingVisitor

void Visit(IShapeProperty property);

void Visit(IPointProperty property);

void Visit(INumberProperty property);

void Visit(ICompletionProperty property);
Expand Down Expand Up @@ -89,6 +91,8 @@ public virtual void Visit(IBooleanProperty property) { }

public virtual void Visit(IBinaryProperty property) { }

public virtual void Visit(IPointProperty property) { }

public virtual void Visit(INumberProperty property) { }

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

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

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

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

void Visit(IIpProperty type, 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 @@ -165,6 +165,12 @@ public void Accept(IProperties properties)
Accept(t.Fields);
});
break;
case FieldType.Point:
Visit<IPointProperty>(field, t =>
{
_visitor.Visit(t);
});
break;
case FieldType.Completion:
Visit<ICompletionProperty>(field, t =>
{
Expand Down
2 changes: 2 additions & 0 deletions src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public virtual void Visit(IGeoShapeProperty type, PropertyInfo propertyInfo, Ela

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

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

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

public virtual void Visit(IMurmur3HashProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }
Expand Down
4 changes: 3 additions & 1 deletion src/Nest/QueryDsl/Geo/Shape/GeoShapeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ public interface IGeoShape
internal enum GeoFormat
{
GeoJson,
WellKnownText
WellKnownText,
String,
}

// TODO: Rename to ShapeType in 8.x
internal static class GeoShapeType
{
// WKT uses BBOX for envelope geo shape
Expand Down
3 changes: 2 additions & 1 deletion src/Nest/QueryDsl/Geo/WKT/GeoWKTException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

namespace Nest
{
// TODO: Change to WKTException in 8.x
/// <summary>
/// An exception when handling <see cref="IGeoShape" /> in Well-Known Text format
/// An exception when handling shapes in Well-Known Text (WKT) format
/// </summary>
public class GeoWKTException : Exception
{
Expand Down
2 changes: 1 addition & 1 deletion src/Nest/QueryDsl/Geo/WKT/GeoWKTReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ internal static double NextNumber(WellKnownTextTokenizer tokenizer)
$"Expected number but found: {tokenizer.TokenString()}", tokenizer.LineNumber, tokenizer.Position);
}

private static bool IsNumberNext(WellKnownTextTokenizer tokenizer)
internal static bool IsNumberNext(WellKnownTextTokenizer tokenizer)
{
var token = tokenizer.PeekToken();
return token == TokenType.Word;
Expand Down
Loading

0 comments on commit b8e06f7

Please sign in to comment.