Skip to content

Commit d23925a

Browse files
codebrainrusscam
authored andcommitted
Implement GeoTileGrid aggregation (#3932)
Implement GeoTileGrid aggregation
1 parent 25645c0 commit d23925a

File tree

7 files changed

+271
-0
lines changed

7 files changed

+271
-0
lines changed

src/Nest/Aggregations/AggregateDictionary.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ public TermsAggregate<TKey> Terms<TKey>(string key)
174174

175175
public MultiBucketAggregate<KeyedBucket<string>> GeoHash(string key) => GetMultiKeyedBucketAggregate<string>(key);
176176

177+
public MultiBucketAggregate<KeyedBucket<string>> GeoTile(string key) => GetMultiKeyedBucketAggregate<string>(key);
178+
177179
public MultiBucketAggregate<KeyedBucket<string>> AdjacencyMatrix(string key) => GetMultiKeyedBucketAggregate<string>(key);
178180

179181
public MultiBucketAggregate<RangeBucket> Range(string key) => GetMultiBucketAggregate<RangeBucket>(key);

src/Nest/Aggregations/AggregationContainer.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ public interface IAggregationContainer
149149
[DataMember(Name = "geohash_grid")]
150150
IGeoHashGridAggregation GeoHash { get; set; }
151151

152+
[DataMember(Name = "geotile_grid")]
153+
IGeoTileGridAggregation GeoTile { get; set; }
154+
152155
[DataMember(Name = "global")]
153156
IGlobalAggregation Global { get; set; }
154157

@@ -300,6 +303,8 @@ public class AggregationContainer : IAggregationContainer
300303

301304
public IGeoHashGridAggregation GeoHash { get; set; }
302305

306+
public IGeoTileGridAggregation GeoTile { get; set; }
307+
303308
public IGlobalAggregation Global { get; set; }
304309

305310
public IHistogramAggregation Histogram { get; set; }
@@ -439,6 +444,8 @@ public class AggregationContainerDescriptor<T> : DescriptorBase<AggregationConta
439444

440445
IGeoHashGridAggregation IAggregationContainer.GeoHash { get; set; }
441446

447+
IGeoTileGridAggregation IAggregationContainer.GeoTile { get; set; }
448+
442449
IGlobalAggregation IAggregationContainer.Global { get; set; }
443450

444451
IHistogramAggregation IAggregationContainer.Histogram { get; set; }
@@ -565,6 +572,11 @@ Func<GeoHashGridAggregationDescriptor<T>, IGeoHashGridAggregation> selector
565572
) =>
566573
_SetInnerAggregation(name, selector, (a, d) => a.GeoHash = d);
567574

575+
public AggregationContainerDescriptor<T> GeoTile(string name,
576+
Func<GeoTileGridAggregationDescriptor<T>, IGeoTileGridAggregation> selector
577+
) =>
578+
_SetInnerAggregation(name, selector, (a, d) => a.GeoTile = d);
579+
568580
public AggregationContainerDescriptor<T> GeoBounds(string name,
569581
Func<GeoBoundsAggregationDescriptor<T>, IGeoBoundsAggregation> selector
570582
) =>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using System.Linq.Expressions;
3+
using System.Runtime.Serialization;
4+
using Elasticsearch.Net.Utf8Json;
5+
6+
namespace Nest
7+
{
8+
[InterfaceDataContract]
9+
[ReadAs(typeof(GeoTileGridAggregation))]
10+
public interface IGeoTileGridAggregation : IBucketAggregation
11+
{
12+
/// <summary>
13+
/// The name of the field indexed with GeoPoints.
14+
/// </summary>
15+
[DataMember(Name ="field")]
16+
Field Field { get; set; }
17+
18+
/// <summary>
19+
/// The zoom of the key used to define cells/buckets in the results.
20+
/// </summary>
21+
[DataMember(Name ="precision")]
22+
GeoTilePrecision? Precision { get; set; }
23+
24+
/// <summary>
25+
/// To allow for more accurate counting of the top cells returned in the final result the aggregation.
26+
/// </summary>
27+
[DataMember(Name ="shard_size")]
28+
int? ShardSize { get; set; }
29+
30+
/// <summary>
31+
/// The maximum number of geohash buckets to return.
32+
/// </summary>
33+
[DataMember(Name ="size")]
34+
int? Size { get; set; }
35+
}
36+
37+
public class GeoTileGridAggregation : BucketAggregationBase, IGeoTileGridAggregation
38+
{
39+
internal GeoTileGridAggregation() { }
40+
41+
public GeoTileGridAggregation(string name) : base(name) { }
42+
43+
/// <inheritdoc />
44+
public Field Field { get; set; }
45+
46+
/// <inheritdoc />
47+
public GeoTilePrecision? Precision { get; set; }
48+
49+
/// <inheritdoc />
50+
public int? ShardSize { get; set; }
51+
52+
/// <inheritdoc />
53+
public int? Size { get; set; }
54+
55+
internal override void WrapInContainer(AggregationContainer c) => c.GeoTile = this;
56+
}
57+
58+
public class GeoTileGridAggregationDescriptor<T>
59+
: BucketAggregationDescriptorBase<GeoTileGridAggregationDescriptor<T>, IGeoTileGridAggregation, T>
60+
, IGeoTileGridAggregation
61+
where T : class
62+
{
63+
Field IGeoTileGridAggregation.Field { get; set; }
64+
65+
GeoTilePrecision? IGeoTileGridAggregation.Precision { get; set; }
66+
67+
int? IGeoTileGridAggregation.ShardSize { get; set; }
68+
69+
int? IGeoTileGridAggregation.Size { get; set; }
70+
71+
/// <inheritdoc cref="IGeoTileGridAggregation.Field" />
72+
public GeoTileGridAggregationDescriptor<T> Field(Field field) => Assign(field, (a, v) => a.Field = v);
73+
74+
/// <inheritdoc cref="IGeoTileGridAggregation.Field" />
75+
public GeoTileGridAggregationDescriptor<T> Field<TValue>(Expression<Func<T, TValue>> field) => Assign(field, (a, v) => a.Field = v);
76+
77+
/// <inheritdoc cref="IGeoTileGridAggregation.Size" />
78+
public GeoTileGridAggregationDescriptor<T> Size(int? size) => Assign(size, (a, v) => a.Size = v);
79+
80+
/// <inheritdoc cref="IGeoTileGridAggregation.ShardSize" />
81+
public GeoTileGridAggregationDescriptor<T> ShardSize(int? shardSize) => Assign(shardSize, (a, v) => a.ShardSize = v);
82+
83+
/// <inheritdoc cref="IGeoTileGridAggregation.Precision" />
84+
public GeoTileGridAggregationDescriptor<T> Precision(GeoTilePrecision? precision) =>
85+
Assign(precision, (a, v) => a.Precision = v);
86+
}
87+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
namespace Nest
2+
{
3+
public enum GeoTilePrecision
4+
{
5+
/// <summary>
6+
/// Whole world
7+
/// </summary>
8+
Precision0 = 0,
9+
Precision1 = 1,
10+
11+
/// <summary>
12+
/// Subcontinental area
13+
/// </summary>
14+
Precision2 = 2,
15+
16+
/// <summary>
17+
/// Largest Country
18+
/// </summary>
19+
Precision3 = 3,
20+
Precision4 = 4,
21+
22+
/// <summary>
23+
/// Large African Country
24+
/// </summary>
25+
Precision5 = 5,
26+
27+
/// <summary>
28+
/// Large European Country
29+
/// </summary>
30+
Precision6 = 6,
31+
32+
/// <summary>
33+
/// Small Country / US State
34+
/// </summary>
35+
Precision7 = 7,
36+
Precision8 = 8,
37+
38+
/// <summary>
39+
/// Wide Area / Large Metropolitan Area
40+
/// </summary>
41+
Precision9 = 9,
42+
43+
/// <summary>
44+
/// Metropolitan Area
45+
/// </summary>
46+
Precision10 = 10,
47+
48+
/// <summary>
49+
/// City
50+
/// </summary>
51+
Precision11 = 11,
52+
53+
/// <summary>
54+
/// City / Town / District
55+
/// </summary>
56+
Precision12 = 12,
57+
58+
/// <summary>
59+
/// Village / Suburb
60+
/// </summary>
61+
Precision13 = 13,
62+
Precision14 = 14,
63+
64+
/// <summary>
65+
/// Small Road
66+
/// </summary>
67+
Precision15 = 15,
68+
69+
/// <summary>
70+
/// Street
71+
/// </summary>
72+
Precision16 = 16,
73+
74+
/// <summary>
75+
/// Block / Park / Addresses
76+
/// </summary>
77+
Precision17 = 17,
78+
79+
/// <summary>
80+
/// Some Buildings / Trees
81+
/// </summary>
82+
Precision18 = 18,
83+
84+
/// <summary>
85+
/// Local highway / Crossing
86+
/// </summary>
87+
Precision19 = 19,
88+
Precision20 = 20,
89+
Precision21 = 21,
90+
Precision22 = 22,
91+
Precision23 = 23,
92+
Precision24 = 24,
93+
Precision25 = 25,
94+
Precision26 = 26,
95+
Precision27 = 27,
96+
Precision28 = 28,
97+
98+
/// <summary>
99+
/// Produces cells that cover less than a 10cm by 10cm of land and so high-precision
100+
/// requests can be very costly in terms of RAM and result sizes.
101+
/// </summary>
102+
Precision29 = 29
103+
}
104+
}

src/Nest/Aggregations/Visitor/AggregationVisitor.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public interface IAggregationVisitor
5252

5353
void Visit(IGeoHashGridAggregation aggregation);
5454

55+
void Visit(IGeoTileGridAggregation aggregation);
56+
5557
void Visit(IGeoBoundsAggregation aggregation);
5658

5759
void Visit(IHistogramAggregation aggregation);
@@ -143,6 +145,8 @@ public virtual void Visit(IFiltersAggregation aggregation) { }
143145

144146
public virtual void Visit(IGeoHashGridAggregation aggregation) { }
145147

148+
public virtual void Visit(IGeoTileGridAggregation aggregation) { }
149+
146150
public virtual void Visit(IHistogramAggregation aggregation) { }
147151

148152
public virtual void Visit(IIpRangeAggregation aggregation) { }

src/Nest/Aggregations/Visitor/AggregationWalker.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public void Walk(IAggregationContainer aggregation, IAggregationVisitor visitor)
8181
v.Visit(d);
8282
Accept(v, d.Aggregations);
8383
});
84+
AcceptAggregation(aggregation.GeoTile, visitor, (v, d) =>
85+
{
86+
v.Visit(d);
87+
Accept(v, d.Aggregations);
88+
});
8489
AcceptAggregation(aggregation.Global, visitor, (v, d) =>
8590
{
8691
v.Visit(d);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Linq;
3+
using FluentAssertions;
4+
using Nest;
5+
using Tests.Core.Extensions;
6+
using Tests.Core.ManagedElasticsearch.Clusters;
7+
using Tests.Domain;
8+
using Tests.Framework.EndpointTests.TestState;
9+
using static Nest.Infer;
10+
11+
namespace Tests.Aggregations.Bucket.GeoTileGrid
12+
{
13+
public class GeoTileTileAggregationUsageTests : AggregationUsageTestBase
14+
{
15+
public GeoTileTileAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { }
16+
17+
protected override object AggregationJson => new
18+
{
19+
my_geotile = new
20+
{
21+
geotile_grid = new
22+
{
23+
field = "locationPoint",
24+
precision = 3,
25+
size = 1000,
26+
shard_size = 100
27+
}
28+
}
29+
};
30+
31+
protected override Func<AggregationContainerDescriptor<Project>, IAggregationContainer> FluentAggs => a => a
32+
.GeoTile("my_geotile", g => g
33+
.Field(p => p.LocationPoint)
34+
.Precision(GeoTilePrecision.Precision3)
35+
.Size(1000)
36+
.ShardSize(100)
37+
);
38+
39+
protected override AggregationDictionary InitializerAggs =>
40+
new GeoTileGridAggregation("my_geotile")
41+
{
42+
Field = Field<Project>(p => p.LocationPoint),
43+
Precision = GeoTilePrecision.Precision3,
44+
Size = 1000,
45+
ShardSize = 100
46+
};
47+
48+
protected override void ExpectResponse(ISearchResponse<Project> response)
49+
{
50+
response.ShouldBeValid();
51+
var myGeoTileTile = response.Aggregations.GeoTile("my_geotile");
52+
myGeoTileTile.Should().NotBeNull();
53+
myGeoTileTile.Buckets.FirstOrDefault(r => r.Key == "3/0/4").Should().NotBeNull();
54+
myGeoTileTile.Buckets.FirstOrDefault(r => r.Key == "3/5/5").Should().NotBeNull();
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)