Skip to content
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
14 changes: 14 additions & 0 deletions src/Nest/CommonOptions/Range/Ranges.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,18 @@ public class LongRange
[JsonProperty("lt")]
public long? LessThan { get; set; }
}
public class IpAddressRange
{
[JsonProperty("gte")]
public string GreaterThanOrEqualTo { get; set; }

[JsonProperty("lte")]
public string LessThanOrEqualTo { get; set; }

[JsonProperty("gt")]
public string GreaterThan { get; set; }

[JsonProperty("lt")]
public string LessThan { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/Nest/Mapping/DynamicTemplate/SingleMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public IProperty IntegerRange(Func<IntegerRangePropertyDescriptor<T>, IIntegerRa
public IProperty LongRange(Func<LongRangePropertyDescriptor<T>, ILongRangeProperty> selector) =>
selector?.Invoke(new LongRangePropertyDescriptor<T>());

public IProperty IpRange(Func<IpRangePropertyDescriptor<T>, IIpRangeProperty> selector) =>
selector?.Invoke(new IpRangePropertyDescriptor<T>());

public IProperty Join(Func<JoinPropertyDescriptor<T>, IJoinProperty> selector) =>
selector?.Invoke(new JoinPropertyDescriptor<T>());

Expand Down Expand Up @@ -239,6 +242,8 @@ public IProperty Scalar(Expression<Func<T, IntegerRange>> field, Func<IntegerRan
selector.InvokeOrDefault(new IntegerRangePropertyDescriptor<T>().Name(field));
public IProperty Scalar(Expression<Func<T, FloatRange>> field, Func<FloatRangePropertyDescriptor<T>, IFloatRangeProperty> selector = null) =>
selector.InvokeOrDefault(new FloatRangePropertyDescriptor<T>().Name(field));
public IProperty Scalar(Expression<Func<T, IpAddressRange>> field, Func<IpRangePropertyDescriptor<T>, IIpRangeProperty> selector = null) =>
selector.InvokeOrDefault(new IpRangePropertyDescriptor<T>().Name(field));
#pragma warning restore CS3001 // Argument type is not CLS-compliant
}
}
21 changes: 21 additions & 0 deletions src/Nest/Mapping/Types/Core/Range/Ip/IpAddressRangeProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using Elasticsearch.Net;
using Newtonsoft.Json;

namespace Nest
{
[JsonObject(MemberSerialization.OptIn)]
public interface IIpRangeProperty : IRangeProperty { }

public class IpRangeProperty : RangePropertyBase, IIpRangeProperty
{
public IpRangeProperty() : base(RangeType.IpRange) { }
}

public class IpRangePropertyDescriptor<T>
: RangePropertyDescriptorBase<IpRangePropertyDescriptor<T>, IIpRangeProperty, T>, IIpRangeProperty
where T : class
{
public IpRangePropertyDescriptor() : base(RangeType.IpRange) { }
}
}
10 changes: 10 additions & 0 deletions src/Nest/Mapping/Types/Core/Range/Ip/IpRangeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using Elasticsearch.Net;

namespace Nest
{
public class IpRangeAttribute : RangePropertyAttributeBase, IIpRangeProperty
{
public IpRangeAttribute() : base(RangeType.IpRange) { }
}
}
6 changes: 3 additions & 3 deletions src/Nest/Mapping/Types/Core/Range/RangePropertyBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ public abstract class RangePropertyDescriptorBase<TDescriptor, TInterface, T>

protected RangePropertyDescriptorBase(RangeType type) : base(type.ToFieldType()) { }

/// <inheritdoc/>
/// <inheritdoc cref="IRangeProperty.Coerce"/>
public TDescriptor Coerce(bool? coerce = true) => Assign(a => a.Coerce = coerce);
/// <inheritdoc/>
/// <inheritdoc cref="IRangeProperty.Boost"/>
public TDescriptor Boost(double? boost) => Assign(a => a.Boost = boost);
/// <inheritdoc/>
/// <inheritdoc cref="IRangeProperty.Index"/>
public TDescriptor Index(bool? index = true) => Assign(a => a.Index = index);
}
}
8 changes: 7 additions & 1 deletion src/Nest/Mapping/Types/Core/Range/RangeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ public enum RangeType
/// A range of date values represented as unsigned 64-bit integer milliseconds elapsed since system epoch.
/// </summary>
[EnumMember(Value = "date_range")]
DateRange
DateRange,
/// <summary>
/// A range of ip values supporting either IPv4 or IPv6 (or mixed) addresses.
/// </summary>
[EnumMember(Value = "ip_range")]
IpRange
}
internal static class RangeTypeExtensions
{
Expand All @@ -45,6 +50,7 @@ public static FieldType ToFieldType(this RangeType rangeType)
case RangeType.LongRange: return FieldType.LongRange;
case RangeType.DoubleRange: return FieldType.DoubleRange;
case RangeType.DateRange: return FieldType.DateRange;
case RangeType.IpRange: return FieldType.IpRange;
default:
throw new ArgumentOutOfRangeException(nameof(rangeType), rangeType, null);
}
Expand Down
2 changes: 2 additions & 0 deletions src/Nest/Mapping/Types/FieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public enum FieldType
DoubleRange,
[EnumMember(Value = "date_range")]
DateRange,
[EnumMember(Value = "ip_range")]
IpRange,
[EnumMember(Value = "join")]
Join,
}
Expand Down
3 changes: 3 additions & 0 deletions src/Nest/Mapping/Types/Properties-Scalar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public partial interface IPropertiesDescriptor<T, out TReturnType>
TReturnType Scalar(Expression<Func<T, LongRange>> field, Func<LongRangePropertyDescriptor<T>, ILongRangeProperty> selector = null);
TReturnType Scalar(Expression<Func<T, IntegerRange>> field, Func<IntegerRangePropertyDescriptor<T>, IIntegerRangeProperty> selector = null);
TReturnType Scalar(Expression<Func<T, FloatRange>> field, Func<FloatRangePropertyDescriptor<T>, IFloatRangeProperty> selector = null);
TReturnType Scalar(Expression<Func<T, IpAddressRange>> field, Func<IpRangePropertyDescriptor<T>, IIpRangeProperty> selector = null);
#pragma warning restore CS3001 // Argument type is not CLS-compliant
}

Expand Down Expand Up @@ -269,6 +270,8 @@ public PropertiesDescriptor<T> Scalar(Expression<Func<T, IntegerRange>> field, F
SetProperty(selector.InvokeOrDefault(new IntegerRangePropertyDescriptor<T>().Name(field)));
public PropertiesDescriptor<T> Scalar(Expression<Func<T, FloatRange>> field, Func<FloatRangePropertyDescriptor<T>, IFloatRangeProperty> selector = null) =>
SetProperty(selector.InvokeOrDefault(new FloatRangePropertyDescriptor<T>().Name(field)));
public PropertiesDescriptor<T> Scalar(Expression<Func<T, IpAddressRange>> field, Func<IpRangePropertyDescriptor<T>, IIpRangeProperty> selector = null) =>
SetProperty(selector.InvokeOrDefault(new IpRangePropertyDescriptor<T>().Name(field)));

#pragma warning restore CS3001 // Argument type is not CLS-compliant
}
Expand Down
3 changes: 3 additions & 0 deletions src/Nest/Mapping/Types/Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ TReturnType Nested<TChild>(Func<NestedPropertyDescriptor<T, TChild>, INestedProp
TReturnType FloatRange(Func<FloatRangePropertyDescriptor<T>, IFloatRangeProperty> selector);
TReturnType IntegerRange(Func<IntegerRangePropertyDescriptor<T>, IIntegerRangeProperty> selector);
TReturnType LongRange(Func<LongRangePropertyDescriptor<T>, ILongRangeProperty> selector);
TReturnType IpRange(Func<IpRangePropertyDescriptor<T>, IIpRangeProperty> selector);
TReturnType Join(Func<JoinPropertyDescriptor<T>, IJoinProperty> selector);
}

Expand Down Expand Up @@ -127,6 +128,8 @@ public PropertiesDescriptor<T> Nested<TChild>(Func<NestedPropertyDescriptor<T, T

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

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

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

public PropertiesDescriptor<T> Custom(IProperty customType) => SetProperty(customType);
Expand Down
8 changes: 2 additions & 6 deletions src/Nest/Mapping/Types/PropertiesJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
foreach (var p in o.Properties())
{
var name = p.Name;
var po = p.First as JObject;
if (po == null) continue;

var mapping = _elasticTypeConverter.ReadJson(po.CreateReader(), objectType, existingValue, serializer) as IProperty;
if (mapping == null) continue;
if (!(p.First is JObject po)) continue;
if (!(_elasticTypeConverter.ReadJson(po.CreateReader(), objectType, existingValue, serializer) is IProperty mapping)) continue;

mapping.Name = name;

r.Add(name, mapping);
}
return r;
Expand Down
12 changes: 4 additions & 8 deletions src/Nest/Mapping/Types/PropertyJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@ internal class PropertyJsonConverter : JsonConverter

public override bool CanConvert(Type objectType) => objectType == typeof(IProperty);

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
throw new NotSupportedException();
}

private TProperty ReadProperty<TProperty>(JObject j, JsonSerializer s)
where TProperty : IProperty
{
return FromJson.ReadAs<TProperty>(j.CreateReader(), s);
}
private TProperty ReadProperty<TProperty>(JObject j, JsonSerializer s) where TProperty : IProperty =>
FromJson.ReadAs<TProperty>(j.CreateReader(), s);

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Expand Down Expand Up @@ -64,6 +59,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
case FieldType.FloatRange: return ReadProperty<FloatRangeProperty>(jObject, serializer);
case FieldType.IntegerRange: return ReadProperty<IntegerRangeProperty>(jObject, serializer);
case FieldType.LongRange: return ReadProperty<LongRangeProperty>(jObject, serializer);
case FieldType.IpRange: return ReadProperty<IpRangeProperty>(jObject, serializer);
case FieldType.Join: return ReadProperty<JoinProperty>(jObject, serializer);
case FieldType.None:
break;
Expand Down
3 changes: 3 additions & 0 deletions src/Nest/Mapping/Visitor/PropertyWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ private static IProperty InferProperty(PropertyInfo propertyInfo)
if (type == typeof(LongRange))
return new LongRangeProperty();

if (type == typeof(IpAddressRange))
return new IpRangeProperty();

return new ObjectProperty();
}

Expand Down
24 changes: 24 additions & 0 deletions src/Tests/Framework/MockData/Ranges.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Net;
using Bogus;
using Nest;

Expand All @@ -11,6 +12,7 @@ public class Ranges
public FloatRange Floats { get; set; }
public IntegerRange Integers { get; set; }
public LongRange Longs { get; set; }
public IpAddressRange Ips { get; set; }

//for deserialization
public Ranges() { }
Expand All @@ -23,6 +25,7 @@ private Ranges(Faker faker)
SetFloats(faker, r);
SetIntegers(faker, r);
SetLongs(faker, r);
SetIps(faker, r);
}

private void SetDates(Faker faker, Func<bool> r)
Expand Down Expand Up @@ -70,6 +73,27 @@ private void SetLongs(Faker faker, Func<bool> r)
SwapAssign(r(), high, v => d.LessThan = v, v => d.LessThanOrEqualTo = v);
this.Longs = d;
}
private void SetIps(Faker faker, Func<bool> r)
{
var low = faker.Internet.Ip();
var high = faker.Internet.Ip();
var lowBytes = IPAddress.Parse(low).GetAddressBytes();
var highBytes = IPAddress.Parse(high).GetAddressBytes();
for (int i = 0; i < lowBytes.Length; i++)
{
if (lowBytes[i] > highBytes[i])
{
var s = low;
low = high;
high = s;
break;
}
}
var d = new IpAddressRange();
SwapAssign(r(), low, v => d.GreaterThan = v, v => d.GreaterThanOrEqualTo = v);
SwapAssign(r(), high, v => d.LessThan = v, v => d.LessThanOrEqualTo = v);
this.Ips = d;
}

private static void SwapAssign<T>(bool b, T value, Action<T> first, Action<T> second)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ protected override LazyResponses ClientUsage() => Calls(
doubles = new { type = "double_range" },
floats = new { type = "float_range" },
integers = new { type = "integer_range" },
longs = new { type = "long_range" }
longs = new { type = "long_range" },
ips = new { type = "ip_range" }
},
type = "object"
},
Expand Down Expand Up @@ -274,6 +275,7 @@ protected override LazyResponses ClientUsage() => Calls(
{p => p.Floats, new FloatRangeProperty()},
{p => p.Integers, new IntegerRangeProperty()},
{p => p.Longs, new LongRangeProperty()},
{p => p.Ips, new IpRangeProperty()},
}
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Nest;
using Tests.Framework;

namespace Tests.Mapping.Types.Core.Range.IpRange
{
public class IpRangeTest
{
[IpRange]
public Nest.IpAddressRange Range { get; set; }
}

[SkipVersion("<5.5.0", "ip range type is a new 5.5.0 feature")]
public class IpRangeAttributeTests : AttributeTestsBase<IpRangeTest>
{
protected override object ExpectJson => new
{
properties = new
{
range = new
{
type = "ip_range"
}
}
};
}
}
73 changes: 73 additions & 0 deletions src/Tests/Mapping/Types/Core/Range/IpRange/IpRangePropertyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using Nest;
using Tests.Framework;
using Tests.Framework.Integration;
using Tests.Framework.ManagedElasticsearch.Clusters;
using Tests.Framework.MockData;

namespace Tests.Mapping.Types.Core.Range.IpRange
{
[SkipVersion("<5.5.0", "ip range type is a new 5.5.0 feature")]
public class IpRangePropertyTests : PropertyTestsBase
{
public IpRangePropertyTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }

protected override object ExpectJson => new
{
properties = new
{
ranges = new
{
type = "object",
properties = new
{
ips = new
{
type = "ip_range",
store = true,
index = false,
boost = 1.5,
coerce = true
}
}
}
}
};

protected override Func<PropertiesDescriptor<Project>, IPromise<IProperties>> FluentProperties => f => f
.Object<Ranges>(m => m
.Name(p => p.Ranges)
.Properties(props => props
.IpRange(n => n
.Name(p => p.Ips)
.Store()
.Index(false)
.Boost(1.5)
.Coerce()
)
)
);


protected override IProperties InitializerProperties => new Properties
{
{
"ranges", new ObjectProperty
{
Properties = new Properties
{
{
"ips", new IpRangeProperty
{
Store = true,
Index = false,
Boost = 1.5,
Coerce = true
}
}
}
}
}
};
}
}