Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
/**
* A geo metric aggregator that computes a geo-centroid from a {@code geo_point} type field
*/
public final class GeoCentroidAggregator extends MetricsAggregator {
final class GeoCentroidAggregator extends MetricsAggregator {
private final ValuesSource.GeoPoint valuesSource;
LongArray centroids;
LongArray counts;
private LongArray centroids;
private LongArray counts;

protected GeoCentroidAggregator(String name, SearchContext context, Aggregator parent,
GeoCentroidAggregator(String name, SearchContext context, Aggregator parent,
ValuesSource.GeoPoint valuesSource, List<PipelineAggregator> pipelineAggregators,
Map<String, Object> metaData) throws IOException {
super(name, context, parent, pipelineAggregators, metaData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
import java.util.List;
import java.util.Map;

public class GeoCentroidAggregatorFactory extends ValuesSourceAggregatorFactory<ValuesSource.GeoPoint, GeoCentroidAggregatorFactory> {
class GeoCentroidAggregatorFactory extends ValuesSourceAggregatorFactory<ValuesSource.GeoPoint, GeoCentroidAggregatorFactory> {

public GeoCentroidAggregatorFactory(String name, ValuesSourceConfig<ValuesSource.GeoPoint> config,
GeoCentroidAggregatorFactory(String name, ValuesSourceConfig<ValuesSource.GeoPoint> config,
SearchContext context, AggregatorFactory<?> parent, AggregatorFactories.Builder subFactoriesBuilder,
Map<String, Object> metaData) throws IOException {
super(name, config, context, parent, subFactoriesBuilder, metaData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class InternalGeoCentroid extends InternalAggregation implements GeoCentr
protected final GeoPoint centroid;
protected final long count;

public InternalGeoCentroid(String name, GeoPoint centroid, long count, List<PipelineAggregator>
InternalGeoCentroid(String name, GeoPoint centroid, long count, List<PipelineAggregator>
pipelineAggregators, Map<String, Object> metaData) {
super(name, pipelineAggregators, metaData);
assert (centroid == null) == (count == 0);
Expand Down Expand Up @@ -132,7 +132,7 @@ public Object getProperty(List<String> path) {
}

static class Fields {
public static final String CENTROID = "location";
static final String CENTROID = "location";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.search.aggregations.metrics.geocentroid;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.LatLonDocValuesField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.store.Directory;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.mapper.GeoPointFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.search.aggregations.AggregatorTestCase;
import org.elasticsearch.test.geo.RandomGeoGenerator;

import java.io.IOException;

public class GeoCentroidAggregatorTests extends AggregatorTestCase {

private static final double GEOHASH_TOLERANCE = 1E-4D;

public void testEmpty() throws Exception {
try (Directory dir = newDirectory();
RandomIndexWriter w = new RandomIndexWriter(random(), dir)) {
GeoCentroidAggregationBuilder aggBuilder = new GeoCentroidAggregationBuilder("my_agg")
.field("field");

MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
fieldType.setHasDocValues(true);
fieldType.setName("field");
try (IndexReader reader = w.getReader()) {
IndexSearcher searcher = new IndexSearcher(reader);
InternalGeoCentroid result = search(searcher, new MatchAllDocsQuery(), aggBuilder, fieldType);
assertNull(result.centroid());
}
}
}

public void testUnmapped() throws Exception {
try (Directory dir = newDirectory();
RandomIndexWriter w = new RandomIndexWriter(random(), dir)) {
GeoCentroidAggregationBuilder aggBuilder = new GeoCentroidAggregationBuilder("my_agg")
.field("another_field");

Document document = new Document();
document.add(new LatLonDocValuesField("field", 10, 10));
w.addDocument(document);
try (IndexReader reader = w.getReader()) {
IndexSearcher searcher = new IndexSearcher(reader);

MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
fieldType.setHasDocValues(true);
fieldType.setName("another_field");
InternalGeoCentroid result = search(searcher, new MatchAllDocsQuery(), aggBuilder, fieldType);
assertNull(result.centroid());

fieldType = new GeoPointFieldMapper.GeoPointFieldType();
fieldType.setHasDocValues(true);
fieldType.setName("field");
result = search(searcher, new MatchAllDocsQuery(), aggBuilder, fieldType);
assertNull(result.centroid());
}
}
}

public void testSingleValuedField() throws Exception {
int numDocs = scaledRandomIntBetween(64, 256);
int numUniqueGeoPoints = randomIntBetween(1, numDocs);
try (Directory dir = newDirectory();
RandomIndexWriter w = new RandomIndexWriter(random(), dir)) {
GeoPoint expectedCentroid = new GeoPoint(0, 0);
GeoPoint[] singleValues = new GeoPoint[numUniqueGeoPoints];
for (int i = 0 ; i < singleValues.length; i++) {
singleValues[i] = RandomGeoGenerator.randomPoint(random());
}
GeoPoint singleVal;
for (int i = 0; i < numDocs; i++) {
singleVal = singleValues[i % numUniqueGeoPoints];
Document document = new Document();
document.add(new LatLonDocValuesField("field", singleVal.getLat(), singleVal.getLon()));
w.addDocument(document);
expectedCentroid = expectedCentroid.reset(expectedCentroid.lat() + (singleVal.lat() - expectedCentroid.lat()) / (i + 1),
expectedCentroid.lon() + (singleVal.lon() - expectedCentroid.lon()) / (i + 1));
}
assertCentroid(w, expectedCentroid);
}
}

public void testMultiValuedField() throws Exception {
int numDocs = scaledRandomIntBetween(64, 256);
int numUniqueGeoPoints = randomIntBetween(1, numDocs);
try (Directory dir = newDirectory();
RandomIndexWriter w = new RandomIndexWriter(random(), dir)) {

GeoPoint expectedCentroid = new GeoPoint(0, 0);
GeoPoint[] multiValues = new GeoPoint[numUniqueGeoPoints];
for (int i = 0 ; i < multiValues.length; i++) {
multiValues[i] = RandomGeoGenerator.randomPoint(random());
}
final GeoPoint[] multiVal = new GeoPoint[2];
for (int i = 0; i < numDocs; i++) {
multiVal[0] = multiValues[i % numUniqueGeoPoints];
multiVal[1] = multiValues[(i+1) % numUniqueGeoPoints];
Document document = new Document();
document.add(new LatLonDocValuesField("field", multiVal[0].getLat(), multiVal[0].getLon()));
document.add(new LatLonDocValuesField("field", multiVal[1].getLat(), multiVal[1].getLon()));
w.addDocument(document);
double newMVLat = (multiVal[0].lat() + multiVal[1].lat())/2d;
double newMVLon = (multiVal[0].lon() + multiVal[1].lon())/2d;
expectedCentroid = expectedCentroid.reset(expectedCentroid.lat() + (newMVLat - expectedCentroid.lat()) / (i + 1),
expectedCentroid.lon() + (newMVLon - expectedCentroid.lon()) / (i + 1));
}
assertCentroid(w, expectedCentroid);
}
}

private void assertCentroid(RandomIndexWriter w, GeoPoint expectedCentroid) throws IOException {
MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
fieldType.setHasDocValues(true);
fieldType.setName("field");
GeoCentroidAggregationBuilder aggBuilder = new GeoCentroidAggregationBuilder("my_agg")
.field("field");
try (IndexReader reader = w.getReader()) {
IndexSearcher searcher = new IndexSearcher(reader);
InternalGeoCentroid result = search(searcher, new MatchAllDocsQuery(), aggBuilder, fieldType);

assertEquals("my_agg", result.getName());
GeoPoint centroid = result.centroid();
assertNotNull(centroid);
assertEquals(expectedCentroid.getLat(), centroid.getLat(), GEOHASH_TOLERANCE);
assertEquals(expectedCentroid.getLon(), centroid.getLon(), GEOHASH_TOLERANCE);
}
}

}