|
@@ -28,6 +28,9 @@ import org.apache.lucene.search.MatchAllDocsQuery;
|
|
|
import org.apache.lucene.search.Query;
|
|
|
import org.apache.lucene.store.Directory;
|
|
|
import org.elasticsearch.common.CheckedConsumer;
|
|
|
+import org.elasticsearch.common.geo.GeoBoundingBox;
|
|
|
+import org.elasticsearch.common.geo.GeoBoundingBoxTests;
|
|
|
+import org.elasticsearch.common.geo.GeoUtils;
|
|
|
import org.elasticsearch.index.mapper.GeoPointFieldMapper;
|
|
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
|
|
import org.elasticsearch.search.aggregations.Aggregator;
|
|
@@ -44,6 +47,8 @@ import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
|
+import static org.hamcrest.Matchers.equalTo;
|
|
|
+
|
|
|
public abstract class GeoGridAggregatorTestCase<T extends InternalGeoGridBucket> extends AggregatorTestCase {
|
|
|
|
|
|
private static final String FIELD_NAME = "location";
|
|
@@ -64,18 +69,18 @@ public abstract class GeoGridAggregatorTestCase<T extends InternalGeoGridBucket>
|
|
|
protected abstract GeoGridAggregationBuilder createBuilder(String name);
|
|
|
|
|
|
public void testNoDocs() throws IOException {
|
|
|
- testCase(new MatchAllDocsQuery(), FIELD_NAME, randomPrecision(), iw -> {
|
|
|
- // Intentionally not writing any docs
|
|
|
- }, geoGrid -> {
|
|
|
+ testCase(new MatchAllDocsQuery(), FIELD_NAME, randomPrecision(), null, geoGrid -> {
|
|
|
assertEquals(0, geoGrid.getBuckets().size());
|
|
|
+ }, iw -> {
|
|
|
+ // Intentionally not writing any docs
|
|
|
});
|
|
|
}
|
|
|
|
|
|
public void testFieldMissing() throws IOException {
|
|
|
- testCase(new MatchAllDocsQuery(), "wrong_field", randomPrecision(), iw -> {
|
|
|
- iw.addDocument(Collections.singleton(new LatLonDocValuesField(FIELD_NAME, 10D, 10D)));
|
|
|
- }, geoGrid -> {
|
|
|
+ testCase(new MatchAllDocsQuery(), "wrong_field", randomPrecision(), null, geoGrid -> {
|
|
|
assertEquals(0, geoGrid.getBuckets().size());
|
|
|
+ }, iw -> {
|
|
|
+ iw.addDocument(Collections.singleton(new LatLonDocValuesField(FIELD_NAME, 10D, 10D)));
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -83,7 +88,13 @@ public abstract class GeoGridAggregatorTestCase<T extends InternalGeoGridBucket>
|
|
|
int precision = randomPrecision();
|
|
|
int numPoints = randomIntBetween(8, 128);
|
|
|
Map<String, Integer> expectedCountPerGeoHash = new HashMap<>();
|
|
|
- testCase(new MatchAllDocsQuery(), FIELD_NAME, precision, iw -> {
|
|
|
+ testCase(new MatchAllDocsQuery(), FIELD_NAME, precision, null, geoHashGrid -> {
|
|
|
+ assertEquals(expectedCountPerGeoHash.size(), geoHashGrid.getBuckets().size());
|
|
|
+ for (GeoGrid.Bucket bucket : geoHashGrid.getBuckets()) {
|
|
|
+ assertEquals((long) expectedCountPerGeoHash.get(bucket.getKeyAsString()), bucket.getDocCount());
|
|
|
+ }
|
|
|
+ assertTrue(AggregationInspectionHelper.hasValue(geoHashGrid));
|
|
|
+ }, iw -> {
|
|
|
List<LatLonDocValuesField> points = new ArrayList<>();
|
|
|
Set<String> distinctHashesPerDoc = new HashSet<>();
|
|
|
for (int pointId = 0; pointId < numPoints; pointId++) {
|
|
@@ -112,17 +123,71 @@ public abstract class GeoGridAggregatorTestCase<T extends InternalGeoGridBucket>
|
|
|
if (points.size() != 0) {
|
|
|
iw.addDocument(points);
|
|
|
}
|
|
|
- }, geoHashGrid -> {
|
|
|
- assertEquals(expectedCountPerGeoHash.size(), geoHashGrid.getBuckets().size());
|
|
|
- for (GeoGrid.Bucket bucket : geoHashGrid.getBuckets()) {
|
|
|
- assertEquals((long) expectedCountPerGeoHash.get(bucket.getKeyAsString()), bucket.getDocCount());
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testBounds() throws IOException {
|
|
|
+ final int numDocs = randomIntBetween(64, 256);
|
|
|
+ final GeoGridAggregationBuilder builder = createBuilder("_name");
|
|
|
+
|
|
|
+ expectThrows(IllegalArgumentException.class, () -> builder.precision(-1));
|
|
|
+ expectThrows(IllegalArgumentException.class, () -> builder.precision(30));
|
|
|
+
|
|
|
+ GeoBoundingBox bbox = GeoBoundingBoxTests.randomBBox();
|
|
|
+
|
|
|
+ int in = 0, out = 0;
|
|
|
+ List<LatLonDocValuesField> docs = new ArrayList<>();
|
|
|
+ while (in + out < numDocs) {
|
|
|
+ if (bbox.left() > bbox.right()) {
|
|
|
+ if (randomBoolean()) {
|
|
|
+ double lonWithin = randomBoolean() ?
|
|
|
+ randomDoubleBetween(bbox.left(), 180.0, true)
|
|
|
+ : randomDoubleBetween(-180.0, bbox.right(), true);
|
|
|
+ double latWithin = randomDoubleBetween(bbox.bottom(), bbox.top(), true);
|
|
|
+ in++;
|
|
|
+ docs.add(new LatLonDocValuesField(FIELD_NAME, latWithin, lonWithin));
|
|
|
+ } else {
|
|
|
+ double lonOutside = randomDoubleBetween(bbox.left(), bbox.right(), true);
|
|
|
+ double latOutside = randomDoubleBetween(bbox.top(), -90, false);
|
|
|
+ out++;
|
|
|
+ docs.add(new LatLonDocValuesField(FIELD_NAME, latOutside, lonOutside));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (randomBoolean()) {
|
|
|
+ double lonWithin = randomDoubleBetween(bbox.left(), bbox.right(), true);
|
|
|
+ double latWithin = randomDoubleBetween(bbox.bottom(), bbox.top(), true);
|
|
|
+ in++;
|
|
|
+ docs.add(new LatLonDocValuesField(FIELD_NAME, latWithin, lonWithin));
|
|
|
+ } else {
|
|
|
+ double lonOutside = GeoUtils.normalizeLon(randomDoubleBetween(bbox.right(), 180.001, false));
|
|
|
+ double latOutside = GeoUtils.normalizeLat(randomDoubleBetween(bbox.top(), 90.001, false));
|
|
|
+ out++;
|
|
|
+ docs.add(new LatLonDocValuesField(FIELD_NAME, latOutside, lonOutside));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ final long numDocsInBucket = in;
|
|
|
+ final int precision = randomPrecision();
|
|
|
+
|
|
|
+ testCase(new MatchAllDocsQuery(), FIELD_NAME, precision, bbox, geoGrid -> {
|
|
|
+ assertTrue(AggregationInspectionHelper.hasValue(geoGrid));
|
|
|
+ long docCount = 0;
|
|
|
+ for (int i = 0; i < geoGrid.getBuckets().size(); i++) {
|
|
|
+ docCount += geoGrid.getBuckets().get(i).getDocCount();
|
|
|
+ }
|
|
|
+ assertThat(docCount, equalTo(numDocsInBucket));
|
|
|
+ }, iw -> {
|
|
|
+ for (LatLonDocValuesField docField : docs) {
|
|
|
+ iw.addDocument(Collections.singletonList(docField));
|
|
|
}
|
|
|
- assertTrue(AggregationInspectionHelper.hasValue(geoHashGrid));
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- private void testCase(Query query, String field, int precision, CheckedConsumer<RandomIndexWriter, IOException> buildIndex,
|
|
|
- Consumer<InternalGeoGrid<T>> verify) throws IOException {
|
|
|
+ private void testCase(Query query, String field, int precision, GeoBoundingBox geoBoundingBox,
|
|
|
+ Consumer<InternalGeoGrid<T>> verify,
|
|
|
+ CheckedConsumer<RandomIndexWriter, IOException> buildIndex) throws IOException {
|
|
|
Directory directory = newDirectory();
|
|
|
RandomIndexWriter indexWriter = new RandomIndexWriter(random(), directory);
|
|
|
buildIndex.accept(indexWriter);
|
|
@@ -133,6 +198,11 @@ public abstract class GeoGridAggregatorTestCase<T extends InternalGeoGridBucket>
|
|
|
|
|
|
GeoGridAggregationBuilder aggregationBuilder = createBuilder("_name").field(field);
|
|
|
aggregationBuilder.precision(precision);
|
|
|
+ if (geoBoundingBox != null) {
|
|
|
+ aggregationBuilder.setGeoBoundingBox(geoBoundingBox);
|
|
|
+ assertThat(aggregationBuilder.geoBoundingBox(), equalTo(geoBoundingBox));
|
|
|
+ }
|
|
|
+
|
|
|
MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
|
|
|
fieldType.setHasDocValues(true);
|
|
|
fieldType.setName(FIELD_NAME);
|