Skip to content
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

[Backport 7.6] Add support for bounds in geohash_grid aggregation #4422

Merged
merged 1 commit into from
Feb 21, 2020
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
54 changes: 51 additions & 3 deletions src/Nest/Aggregations/Bucket/GeoHashGrid/GeoHashGridAggregation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,74 @@

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

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

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

/// <summary>
/// The maximum number of geohash buckets to return. Defaults to <c>10,000</c>. When results are trimmed,
/// buckets are prioritised based on the volumes of documents they contain.
/// </summary>
[DataMember(Name ="size")]
int? Size { get; set; }

/// <summary>
/// Restricts the points considered to those that fall within the bounds provided.
/// <para />
/// Available in Elasticsearch 7.6.0+.
/// </summary>
[DataMember(Name = "bounds")]
IBoundingBox Bounds { get; set; }
}

/// <inheritdoc cref="IGeoHashGridAggregation"/>
public class GeoHashGridAggregation : BucketAggregationBase, IGeoHashGridAggregation
{
internal GeoHashGridAggregation() { }

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

/// <inheritdoc cref="IGeoHashGridAggregation.Field"/>
public Field Field { get; set; }

/// <inheritdoc cref="IGeoHashGridAggregation.Precision"/>
public GeoHashPrecision? Precision { get; set; }

/// <inheritdoc cref="IGeoHashGridAggregation.ShardSize"/>
public int? ShardSize { get; set; }

/// <inheritdoc cref="IGeoHashGridAggregation.Size"/>
public int? Size { get; set; }

/// <inheritdoc cref="IGeoHashGridAggregation.Bounds"/>
public IBoundingBox Bounds { get; set; }

internal override void WrapInContainer(AggregationContainer c) => c.GeoHash = this;
}

Expand All @@ -42,22 +82,30 @@ public class GeoHashGridAggregationDescriptor<T>
where T : class
{
Field IGeoHashGridAggregation.Field { get; set; }

GeoHashPrecision? IGeoHashGridAggregation.Precision { get; set; }

int? IGeoHashGridAggregation.ShardSize { get; set; }

int? IGeoHashGridAggregation.Size { get; set; }
IBoundingBox IGeoHashGridAggregation.Bounds { get; set; }

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

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

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

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

/// <inheritdoc cref="IGeoHashGridAggregation.Precision"/>
// TODO: Rename to precision in next major.
public GeoHashGridAggregationDescriptor<T> GeoHashPrecision(GeoHashPrecision? precision) =>
Assign(precision, (a, v) => a.Precision = v);

/// <inheritdoc cref="IGeoHashGridAggregation.Bounds"/>
public GeoHashGridAggregationDescriptor<T> Bounds(Func<BoundingBoxDescriptor, IBoundingBox> selector) =>
Assign(selector, (a, v) => a.Bounds = v?.Invoke(new BoundingBoxDescriptor()));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Elastic.Xunit.XunitPlumbing;
using FluentAssertions;
using Nest;
using Tests.Core.Extensions;
Expand Down Expand Up @@ -51,4 +52,62 @@ protected override void ExpectResponse(ISearchResponse<Project> response)
myGeoHashGrid.Should().NotBeNull();
}
}

[SkipVersion("<7.6.0", "bounds introduced in 7.6.0")]
// hide
public class GeoHashGridAggregationWithBoundsUsageTests : AggregationUsageTestBase
{
public GeoHashGridAggregationWithBoundsUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { }

protected override object AggregationJson => new
{
my_geohash_grid = new
{
geohash_grid = new
{
field = "locationPoint",
bounds = new
{
top_left = new
{
lat = 90.0,
lon = -180.0
},
bottom_right = new
{
lat = -90.0,
lon = 180.0
}
}
}
}
};

protected override Func<AggregationContainerDescriptor<Project>, IAggregationContainer> FluentAggs => a => a
.GeoHash("my_geohash_grid", g => g
.Field(p => p.LocationPoint)
.Bounds(b => b
.TopLeft(90,-180)
.BottomRight(-90, 180)
)
);

protected override AggregationDictionary InitializerAggs =>
new GeoHashGridAggregation("my_geohash_grid")
{
Field = Field<Project>(p => p.LocationPoint),
Bounds = new BoundingBox
{
TopLeft = new GeoLocation(90, -180),
BottomRight = new GeoLocation(-90, 180)
}
};

protected override void ExpectResponse(ISearchResponse<Project> response)
{
response.ShouldBeValid();
var myGeoHashGrid = response.Aggregations.GeoHash("my_geohash_grid");
myGeoHashGrid.Should().NotBeNull();
}
}
}