Skip to content

Commit 72f590a

Browse files
russcamgithub-actions[bot]
authored andcommitted
Add support for bounds in geohash_grid aggregation (#4403)
Relates: #4341, elastic/elasticsearch#50002 This commit adds support for supplying bounds on a geohash_grid aggregation, similar to how bounds are supplied on geo_bounding_box query.
1 parent 54bfe83 commit 72f590a

File tree

2 files changed

+110
-3
lines changed

2 files changed

+110
-3
lines changed

src/Nest/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregation.cs

+51-3
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,74 @@
55

66
namespace Nest
77
{
8+
/// <summary>
9+
/// A multi-bucket aggregation that works on geo_point fields and groups points into buckets that represent cells in a grid.
10+
/// The resulting grid can be sparse and only contains cells that have matching data.
11+
/// Each cell is labeled using a geohash which is of user-definable precision.
12+
/// </summary>
813
[InterfaceDataContract]
914
[ReadAs(typeof(GeoHashGridAggregation))]
1015
public interface IGeoHashGridAggregation : IBucketAggregation
1116
{
17+
/// <summary>
18+
/// The name of the field indexed with geopoints.
19+
/// </summary>
1220
[DataMember(Name ="field")]
1321
Field Field { get; set; }
1422

23+
/// <summary>
24+
/// The string length of the geohashes used to define cells/buckets in the results.
25+
/// Defaults to <see cref="GeoHashPrecision.Precision5"/>.
26+
/// </summary>
1527
[DataMember(Name ="precision")]
1628
GeoHashPrecision? Precision { get; set; }
1729

30+
/// <summary>
31+
/// To allow for more accurate counting of the top cells returned in the final result the aggregation defaults to returning
32+
/// <c>max(10,(size x number-of-shards))</c> buckets from each shard. If this heuristic is undesirable,
33+
/// the number considered from each shard can be over-ridden using this parameter.
34+
/// </summary>
1835
[DataMember(Name ="shard_size")]
1936
int? ShardSize { get; set; }
2037

38+
/// <summary>
39+
/// The maximum number of geohash buckets to return. Defaults to <c>10,000</c>. When results are trimmed,
40+
/// buckets are prioritised based on the volumes of documents they contain.
41+
/// </summary>
2142
[DataMember(Name ="size")]
2243
int? Size { get; set; }
44+
45+
/// <summary>
46+
/// Restricts the points considered to those that fall within the bounds provided.
47+
/// <para />
48+
/// Available in Elasticsearch 7.6.0+.
49+
/// </summary>
50+
[DataMember(Name = "bounds")]
51+
IBoundingBox Bounds { get; set; }
2352
}
2453

54+
/// <inheritdoc cref="IGeoHashGridAggregation"/>
2555
public class GeoHashGridAggregation : BucketAggregationBase, IGeoHashGridAggregation
2656
{
2757
internal GeoHashGridAggregation() { }
2858

2959
public GeoHashGridAggregation(string name) : base(name) { }
3060

61+
/// <inheritdoc cref="IGeoHashGridAggregation.Field"/>
3162
public Field Field { get; set; }
63+
64+
/// <inheritdoc cref="IGeoHashGridAggregation.Precision"/>
3265
public GeoHashPrecision? Precision { get; set; }
66+
67+
/// <inheritdoc cref="IGeoHashGridAggregation.ShardSize"/>
3368
public int? ShardSize { get; set; }
69+
70+
/// <inheritdoc cref="IGeoHashGridAggregation.Size"/>
3471
public int? Size { get; set; }
3572

73+
/// <inheritdoc cref="IGeoHashGridAggregation.Bounds"/>
74+
public IBoundingBox Bounds { get; set; }
75+
3676
internal override void WrapInContainer(AggregationContainer c) => c.GeoHash = this;
3777
}
3878

@@ -42,22 +82,30 @@ public class GeoHashGridAggregationDescriptor<T>
4282
where T : class
4383
{
4484
Field IGeoHashGridAggregation.Field { get; set; }
45-
4685
GeoHashPrecision? IGeoHashGridAggregation.Precision { get; set; }
47-
4886
int? IGeoHashGridAggregation.ShardSize { get; set; }
49-
5087
int? IGeoHashGridAggregation.Size { get; set; }
88+
IBoundingBox IGeoHashGridAggregation.Bounds { get; set; }
5189

90+
/// <inheritdoc cref="IGeoHashGridAggregation.Field"/>
5291
public GeoHashGridAggregationDescriptor<T> Field(Field field) => Assign(field, (a, v) => a.Field = v);
5392

93+
/// <inheritdoc cref="IGeoHashGridAggregation.Field"/>
5494
public GeoHashGridAggregationDescriptor<T> Field<TValue>(Expression<Func<T, TValue>> field) => Assign(field, (a, v) => a.Field = v);
5595

96+
/// <inheritdoc cref="IGeoHashGridAggregation.Size"/>
5697
public GeoHashGridAggregationDescriptor<T> Size(int? size) => Assign(size, (a, v) => a.Size = v);
5798

99+
/// <inheritdoc cref="IGeoHashGridAggregation.ShardSize"/>
58100
public GeoHashGridAggregationDescriptor<T> ShardSize(int? shardSize) => Assign(shardSize, (a, v) => a.ShardSize = v);
59101

102+
/// <inheritdoc cref="IGeoHashGridAggregation.Precision"/>
103+
// TODO: Rename to precision in next major.
60104
public GeoHashGridAggregationDescriptor<T> GeoHashPrecision(GeoHashPrecision? precision) =>
61105
Assign(precision, (a, v) => a.Precision = v);
106+
107+
/// <inheritdoc cref="IGeoHashGridAggregation.Bounds"/>
108+
public GeoHashGridAggregationDescriptor<T> Bounds(Func<BoundingBoxDescriptor, IBoundingBox> selector) =>
109+
Assign(selector, (a, v) => a.Bounds = v?.Invoke(new BoundingBoxDescriptor()));
62110
}
63111
}

tests/Tests/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregationUsageTests.cs

+59
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Elastic.Xunit.XunitPlumbing;
23
using FluentAssertions;
34
using Nest;
45
using Tests.Core.Extensions;
@@ -51,4 +52,62 @@ protected override void ExpectResponse(ISearchResponse<Project> response)
5152
myGeoHashGrid.Should().NotBeNull();
5253
}
5354
}
55+
56+
[SkipVersion("<7.6.0", "bounds introduced in 7.6.0")]
57+
// hide
58+
public class GeoHashGridAggregationWithBoundsUsageTests : AggregationUsageTestBase
59+
{
60+
public GeoHashGridAggregationWithBoundsUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { }
61+
62+
protected override object AggregationJson => new
63+
{
64+
my_geohash_grid = new
65+
{
66+
geohash_grid = new
67+
{
68+
field = "locationPoint",
69+
bounds = new
70+
{
71+
top_left = new
72+
{
73+
lat = 90.0,
74+
lon = -180.0
75+
},
76+
bottom_right = new
77+
{
78+
lat = -90.0,
79+
lon = 180.0
80+
}
81+
}
82+
}
83+
}
84+
};
85+
86+
protected override Func<AggregationContainerDescriptor<Project>, IAggregationContainer> FluentAggs => a => a
87+
.GeoHash("my_geohash_grid", g => g
88+
.Field(p => p.LocationPoint)
89+
.Bounds(b => b
90+
.TopLeft(90,-180)
91+
.BottomRight(-90, 180)
92+
)
93+
);
94+
95+
protected override AggregationDictionary InitializerAggs =>
96+
new GeoHashGridAggregation("my_geohash_grid")
97+
{
98+
Field = Field<Project>(p => p.LocationPoint),
99+
Bounds = new BoundingBox
100+
{
101+
TopLeft = new GeoLocation(90, -180),
102+
BottomRight = new GeoLocation(-90, 180)
103+
}
104+
};
105+
106+
protected override void ExpectResponse(ISearchResponse<Project> response)
107+
{
108+
response.ShouldBeValid();
109+
var myGeoHashGrid = response.Aggregations.GeoHash("my_geohash_grid");
110+
myGeoHashGrid.Should().NotBeNull();
111+
}
112+
}
54113
}

0 commit comments

Comments
 (0)