-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Long range query support #3299
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
Long range query support #3299
Changes from 8 commits
6dca245
51d7589
2166072
1020933
a3e493b
6686482
24b1793
78d918b
958118c
b4fbbb3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using Newtonsoft.Json; | ||
|
||
namespace Nest | ||
{ | ||
public interface ILongRangeQuery : IRangeQuery | ||
{ | ||
[JsonProperty("gte")] | ||
long? GreaterThanOrEqualTo { get; set; } | ||
|
||
[JsonProperty("lte")] | ||
long? LessThanOrEqualTo { get; set; } | ||
|
||
[JsonProperty("gt")] | ||
long? GreaterThan { get; set; } | ||
|
||
[JsonProperty("lt")] | ||
long? LessThan { get; set; } | ||
|
||
[JsonProperty("relation")] | ||
RangeRelation? Relation { get; set; } | ||
} | ||
|
||
public class LongRangeQuery : FieldNameQueryBase, ILongRangeQuery | ||
{ | ||
protected override bool Conditionless => IsConditionless(this); | ||
public long? GreaterThanOrEqualTo { get; set; } | ||
public long? LessThanOrEqualTo { get; set; } | ||
public long? GreaterThan { get; set; } | ||
public long? LessThan { get; set; } | ||
|
||
public RangeRelation? Relation { get; set; } | ||
|
||
internal override void InternalWrapInContainer(IQueryContainer c) => c.Range = this; | ||
|
||
internal static bool IsConditionless(ILongRangeQuery q) | ||
{ | ||
return q.Field.IsConditionless() | ||
|| (q.GreaterThanOrEqualTo == null | ||
&& q.LessThanOrEqualTo == null | ||
&& q.GreaterThan == null | ||
&& q.LessThan == null); | ||
} | ||
} | ||
|
||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | ||
public class LongRangeQueryDescriptor<T> | ||
: FieldNameQueryDescriptorBase<LongRangeQueryDescriptor<T>, ILongRangeQuery, T> | ||
, ILongRangeQuery where T : class | ||
{ | ||
protected override bool Conditionless => LongRangeQuery.IsConditionless(this); | ||
long? ILongRangeQuery.GreaterThanOrEqualTo { get; set; } | ||
long? ILongRangeQuery.LessThanOrEqualTo { get; set; } | ||
long? ILongRangeQuery.GreaterThan { get; set; } | ||
long? ILongRangeQuery.LessThan { get; set; } | ||
RangeRelation? ILongRangeQuery.Relation { get; set; } | ||
|
||
public LongRangeQueryDescriptor<T> Relation(RangeRelation? relation) => Assign(a => a.Relation = relation); | ||
|
||
public LongRangeQueryDescriptor<T> GreaterThan(long? from) => Assign(a => a.GreaterThan = from); | ||
|
||
public LongRangeQueryDescriptor<T> GreaterThanOrEquals(long? from) => Assign(a => a.GreaterThanOrEqualTo = from); | ||
|
||
public LongRangeQueryDescriptor<T> LessThan(long? to) => Assign(a => a.LessThan = to); | ||
|
||
public LongRangeQueryDescriptor<T> LessThanOrEquals(long? to) => Assign(a => a.LessThanOrEqualTo = to); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,24 +26,37 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist | |
var jo = firstProp.Value.Value<JObject>(); | ||
if (jo == null) return null; | ||
|
||
var fq = GetRangeQuery(serializer, jo); | ||
|
||
var isNumeric = !jo.Properties().Any(p=>p.Name == "format" || p.Name == "time_zone") | ||
&& jo.Properties().Any(p=> _rangeKeys.Contains(p.Name) && (p.Value.Type == JTokenType.Integer || p.Value.Type == JTokenType.Float)); | ||
fq.Name = GetPropValue<string>(jo, "_name"); | ||
fq.Boost = GetPropValue<double?>(jo, "boost"); | ||
fq.Field = field; | ||
|
||
return fq; | ||
} | ||
|
||
IRangeQuery fq; | ||
if (isNumeric) | ||
{ | ||
fq = FromJson.ReadAs<NumericRangeQuery>(jo.CreateReader(), serializer); | ||
} | ||
else | ||
private static IRangeQuery GetRangeQuery(JsonSerializer serializer, JObject jo) | ||
{ | ||
IRangeQuery fq = FromJson.ReadAs<DateRangeQuery>(jo.CreateReader(), serializer); | ||
var isNumeric = false; | ||
var isLong = false; | ||
|
||
foreach (var property in jo.Properties()) | ||
{ | ||
fq = FromJson.ReadAs<DateRangeQuery>(jo.CreateReader(), serializer); | ||
if (property.Name == "format" || property.Name == "time_zone") | ||
return fq; | ||
if (_rangeKeys.Contains(property.Name)) | ||
{ | ||
if (property.Value.Type == JTokenType.Float) | ||
isNumeric = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If any one of the range properties is a The assumption that can't be made, if I've understood correctly, is that we can't rule out There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Earlier was check !jo.Properties().Any(p => p.Name == "format" || p.Name == "time_zone") It is the same as jo.Properties().All(p => p.Name != "format" && p.Name != "time_zone"). So, we have to done this for all properties and I dont want return here NumericRangeQuery |
||
else if (property.Value.Type == JTokenType.Integer) | ||
isLong = true; | ||
} | ||
} | ||
|
||
fq.Name = GetPropValue<string>(jo, "_name"); | ||
fq.Boost = GetPropValue<double?>(jo, "boost"); | ||
fq.Field = field; | ||
if (isNumeric) | ||
return FromJson.ReadAs<NumericRangeQuery>(jo.CreateReader(), serializer); | ||
if (isLong) | ||
return FromJson.ReadAs<LongRangeQuery>(jo.CreateReader(), serializer); | ||
|
||
return fq; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using Nest; | ||
using Tests.Framework.Integration; | ||
using Tests.Framework.ManagedElasticsearch.Clusters; | ||
using Tests.Framework.MockData; | ||
|
||
namespace Tests.QueryDsl.TermLevel.Range | ||
{ | ||
public class LongRangeQueryUsageTests : QueryDslUsageTestsBase | ||
{ | ||
public LongRangeQueryUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) {} | ||
|
||
protected override object QueryJson => new | ||
{ | ||
range = new | ||
{ | ||
description = new | ||
{ | ||
_name = "named_query", | ||
boost = 1.1, | ||
gt = 636634079999999999, | ||
gte = 636634080000000000, | ||
lt = 636634080000000000, | ||
lte = 636634079999999999, | ||
relation = "within" | ||
} | ||
} | ||
}; | ||
|
||
protected override QueryContainer QueryInitializer => new LongRangeQuery | ||
{ | ||
Name = "named_query", | ||
Boost = 1.1, | ||
Field = "description", | ||
GreaterThan = 636634079999999999, | ||
GreaterThanOrEqualTo = 636634080000000000, | ||
LessThan = 636634080000000000, | ||
LessThanOrEqualTo = 636634079999999999, | ||
Relation = RangeRelation.Within | ||
}; | ||
|
||
protected override QueryContainer QueryFluent(QueryContainerDescriptor<Project> q) => q | ||
.LongRange(c => c | ||
.Name("named_query") | ||
.Boost(1.1) | ||
.Field(p => p.Description) | ||
.GreaterThan(636634079999999999) | ||
.GreaterThanOrEquals(636634080000000000) | ||
.LessThan(636634080000000000) | ||
.LessThanOrEquals(636634079999999999) | ||
.Relation(RangeRelation.Within) | ||
); | ||
|
||
protected override ConditionlessWhen ConditionlessWhen => new ConditionlessWhen<ILongRangeQuery>(q => q.Range as ILongRangeQuery) | ||
{ | ||
q=> q.Field = null, | ||
q=> | ||
{ | ||
q.GreaterThan = null; | ||
q.GreaterThanOrEqualTo = null; | ||
q.LessThan = null; | ||
q.LessThanOrEqualTo = null; | ||
} | ||
}; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point, we don't know if the range query is one on date fields. I think assigning
null
is more appropriateand deserializing to
DateRangeQuery
only when it is known that the query is one on date fields.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Earlier we deserialize to DateRangeQuery always when check for numeric Type was false. I think that we can just not declare fq.