-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Feature/geo hash filter #1033
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
Feature/geo hash filter #1033
Changes from 2 commits
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 |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Nest.DSL.Filter; | ||
|
Contributor
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. Remove |
||
| using Newtonsoft.Json; | ||
| using System.Linq.Expressions; | ||
| using System.Globalization; | ||
|
|
@@ -241,6 +242,33 @@ private FilterContainer _GeoDistance(PropertyPathMarker field, Action<GeoDistanc | |
| return this.New(filter, f => f.GeoDistance = filter); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// By defining a geohash cell, only geopoints within this cell will match this filter | ||
| /// </summary> | ||
| public FilterContainer GeoHashCell(string field, Action<GeoHashCellFilterDescriptor> filterDescriptor) | ||
| { | ||
| return _GeoHashCell(field, filterDescriptor); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// By defining a geohash cell, only geopoints within this cell will match this filter | ||
| /// </summary> | ||
| public FilterContainer GeoHashCell(Expression<Func<T, object>> fieldDescriptor, Action<GeoHashCellFilterDescriptor> filterDescriptor) | ||
| { | ||
| return _GeoHashCell(fieldDescriptor, filterDescriptor); | ||
| } | ||
|
|
||
| private FilterContainer _GeoHashCell(PropertyPathMarker field, Action<GeoHashCellFilterDescriptor> filterDescriptor) | ||
| { | ||
| var filter = new GeoHashCellFilterDescriptor(); | ||
| if (filterDescriptor != null) | ||
| filterDescriptor(filter); | ||
|
|
||
| IGeoHashCellFilter ff = filter; | ||
| ff.Field = field; | ||
| return New(filter, f => f.GeoHashCell = filter); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Filters documents that exists within a range from a specific point: | ||
| /// </summary> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| using System.Globalization; | ||
| using Newtonsoft.Json; | ||
| using Newtonsoft.Json.Converters; | ||
|
|
||
| namespace Nest.DSL.Filter | ||
|
Contributor
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. @robertlyson Typically, we do not fully namespace our public API classes. This should be changed to just |
||
| { | ||
| [JsonObject(MemberSerialization = MemberSerialization.OptIn)] | ||
| public interface IGeoHashCellFilter : IFilter | ||
| { | ||
| PropertyPathMarker Field { get; set; } | ||
| string Location { get; set; } | ||
|
|
||
| [JsonProperty("distance")] | ||
| object Precision { get; set; } | ||
|
|
||
| [JsonProperty("unit")] | ||
| [JsonConverter(typeof(StringEnumConverter))] | ||
| GeoUnit? Unit { get; set; } | ||
|
|
||
| [JsonProperty("neighbors")] | ||
| bool Neighbors { get; set; } | ||
| } | ||
|
|
||
| public class GeoHashCellFilter : PlainFilter, IGeoHashCellFilter | ||
| { | ||
| protected internal override void WrapInContainer(IFilterContainer container) | ||
| { | ||
| container.GeoHashCell = this; | ||
| } | ||
|
|
||
| public PropertyPathMarker Field { get; set; } | ||
| public string Location { get; set; } | ||
| public object Precision { get; set; } | ||
| public GeoUnit? Unit { get; set; } | ||
| public bool Neighbors { get; set; } | ||
| } | ||
|
|
||
| public class GeoHashCellFilterDescriptor : FilterBase, IGeoHashCellFilter | ||
| { | ||
| PropertyPathMarker IGeoHashCellFilter.Field { get; set; } | ||
| string IGeoHashCellFilter.Location { get; set; } | ||
| object IGeoHashCellFilter.Precision { get; set; } | ||
| GeoUnit? IGeoHashCellFilter.Unit { get; set; } | ||
| bool IGeoHashCellFilter.Neighbors { get; set; } | ||
|
|
||
| bool IFilter.IsConditionless | ||
| { | ||
| get | ||
| { | ||
| var isConditionless = ((IGeoHashCellFilter) this).Location.IsNullOrEmpty(); | ||
|
|
||
| return isConditionless; | ||
| } | ||
| } | ||
|
|
||
| public GeoHashCellFilterDescriptor Location(double lat, double lon) | ||
| { | ||
| var c = CultureInfo.InvariantCulture; | ||
| ((IGeoHashCellFilter)this).Location = "{{ lat: {0}, lon: {1} }}".F(lat.ToString(c), lon.ToString(c)); | ||
| return this; | ||
| } | ||
|
|
||
| public GeoHashCellFilterDescriptor Location(string geoHash) | ||
| { | ||
| ((IGeoHashCellFilter)this).Location = geoHash; | ||
| return this; | ||
| } | ||
|
|
||
| public GeoHashCellFilterDescriptor Precision(int precision) | ||
| { | ||
| ((IGeoHashCellFilter)this).Precision = precision; | ||
| return this; | ||
| } | ||
|
|
||
| public GeoHashCellFilterDescriptor Distance(double distance, GeoUnit unit) | ||
| { | ||
| ((IGeoHashCellFilter)this).Precision = distance; | ||
| ((IGeoHashCellFilter)this).Unit = unit; | ||
| return this; | ||
| } | ||
|
|
||
| public GeoHashCellFilterDescriptor Neighbors(bool neighbors) | ||
| { | ||
| ((IGeoHashCellFilter)this).Neighbors = neighbors; | ||
| return this; | ||
| } | ||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using Nest.DSL.Filter; | ||
|
Contributor
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. This using can be removed once the namespace for |
||
| using Nest.DSL.Visitor; | ||
| using Nest.Resolvers.Converters; | ||
| using Nest.Resolvers.Converters.Filters; | ||
|
|
@@ -50,6 +51,10 @@ public interface IFilterContainer | |
| [JsonConverter(typeof(GeoDistanceFilterConverter))] | ||
| IGeoDistanceFilter GeoDistance { get; set; } | ||
|
|
||
| [JsonProperty(PropertyName = "geohash_cell")] | ||
| [JsonConverter(typeof(GeoHashCellFilterConverter))] | ||
| IGeoHashCellFilter GeoHashCell { get; set; } | ||
|
|
||
| [JsonProperty(PropertyName = "geo_distance_range")] | ||
| [JsonConverter(typeof(GeoDistanceRangeFilterConverter))] | ||
| IGeoDistanceRangeFilter GeoDistanceRange { get; set; } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using Nest.DSL.Filter; | ||
|
Contributor
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. Remove |
||
|
|
||
| namespace Nest.DSL.Visitor | ||
| { | ||
|
|
@@ -358,6 +359,11 @@ public virtual void Visit(IGeoDistanceFilter filter) | |
| Write("geo_distance"); | ||
| } | ||
|
|
||
| public virtual void Visit(IGeoHashCellFilter filter) | ||
| { | ||
| Write("geohash_cell"); | ||
| } | ||
|
|
||
| public virtual void Visit(IGeoBoundingBoxFilter filter) | ||
| { | ||
| Write("geo_bounding_box"); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Linq.Expressions; | ||
| using Nest.DSL.Filter; | ||
|
Contributor
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. Remove |
||
|
|
||
| namespace Nest | ||
| { | ||
|
|
@@ -52,6 +53,10 @@ public static FilterContainer GeoDistance(string field, Action<GeoDistanceFilter | |
| { | ||
| return new FilterDescriptor<T>().GeoDistance(field, filterDescriptor); | ||
| } | ||
| public static FilterContainer GeoHashCell(string field, Action<GeoHashCellFilterDescriptor> filterDescriptor) | ||
| { | ||
| return new FilterDescriptor<T>().GeoHashCell(field, filterDescriptor); | ||
| } | ||
| public static FilterContainer GeoDistanceRange(Expression<Func<T, object>> fieldDescriptor, Action<GeoDistanceRangeFilterDescriptor> filterDescriptor) | ||
| { | ||
| return new FilterDescriptor<T>().GeoDistanceRange(fieldDescriptor, filterDescriptor); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using Nest.DSL.Filter; | ||
|
Contributor
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. Remove |
||
| using Newtonsoft.Json; | ||
| using Newtonsoft.Json.Linq; | ||
|
|
||
| namespace Nest.Resolvers.Converters | ||
| { | ||
| public class GeoHashCellFilterConverter : JsonConverter | ||
| { | ||
| public override bool CanRead { get { return true; } } | ||
| public override bool CanWrite { get { return true; } } | ||
|
|
||
| public override bool CanConvert(Type objectType) | ||
| { | ||
| return true; //only to be used with attribute or contract registration. | ||
| } | ||
|
|
||
| public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | ||
| { | ||
| var f = value as IGeoHashCellFilter; | ||
| if (f == null || (f.IsConditionless && !f.IsVerbatim)) return; | ||
|
|
||
| var contract = serializer.ContractResolver as SettingsContractResolver; | ||
| if (contract == null) | ||
| return; | ||
|
|
||
| var field = contract.Infer.PropertyPath(f.Field); | ||
| if (field.IsNullOrEmpty()) | ||
| return; | ||
|
|
||
| writer.WriteStartObject(); | ||
| { | ||
| WriteProperty(writer, f, field, f.Location); | ||
| WriteProperty(writer, f, "precision", f.Precision); | ||
| SerializeProperty(writer, serializer, f, "unit", f.Unit); | ||
| SerializeProperty(writer, serializer, f, "neighbors", f.Neighbors); | ||
|
|
||
| WriteProperty(writer, f, "_cache", f.Cache); | ||
| WriteProperty(writer, f, "_cache_key", f.CacheKey); | ||
| WriteProperty(writer, f, "_name", f.FilterName); | ||
| } | ||
|
|
||
| writer.WriteEndObject(); | ||
| } | ||
|
|
||
| public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | ||
| { | ||
| var j = JObject.Load(reader); | ||
| if (j == null || !j.HasValues) | ||
| return null; | ||
|
|
||
| IGeoHashCellFilter filter = new GeoHashCellFilterDescriptor(); | ||
|
|
||
| foreach (var jv in j) | ||
| { | ||
| switch (jv.Key) | ||
| { | ||
| case "precision": | ||
| filter.Precision = jv.Value.Value<string>(); | ||
| break; | ||
| case "neighbors": | ||
| filter.Neighbors = jv.Value.Value<bool>(); | ||
| break; | ||
| case "unit": | ||
| filter.Unit = jv.Value.Value<string>().ToEnum<GeoUnit>(); | ||
| break; | ||
| case "_cache": | ||
| filter.Cache = jv.Value.Value<bool>(); | ||
| break; | ||
| case "_cache_key": | ||
| filter.CacheKey = jv.Value.Value<string>(); | ||
| break; | ||
| case "_name": | ||
| filter.FilterName = jv.Value.Value<string>(); | ||
| break; | ||
| default: | ||
| filter.Field = jv.Key; | ||
| filter.Location = jv.Value.Value<string>(); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| return filter; | ||
| } | ||
|
|
||
| private static void SerializeProperty(JsonWriter writer, JsonSerializer serializer, IFilter filter, string field, object value) | ||
| { | ||
| if ((field.IsNullOrEmpty() || value == null)) | ||
| return; | ||
| writer.WritePropertyName(field); | ||
| serializer.Serialize(writer, value); | ||
| } | ||
| private static void WriteProperty(JsonWriter writer, IFilter filter, string field, object value) | ||
| { | ||
| if ((field.IsNullOrEmpty() || value == null)) | ||
| return; | ||
| writer.WritePropertyName(field); | ||
| writer.WriteValue(value); | ||
| } | ||
| } | ||
|
|
||
| } | ||
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.
This using can be removed once the namespace for GeoHashCellFilterDescriptor is changed to Nest.