Search in sources :

Example 1 with GeoPoint

use of org.elasticsearch.common.geo.GeoPoint in project elasticsearch by elastic.

the class GeoDistanceSortBuilder method toXContent.

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
    builder.startObject();
    builder.startObject(NAME);
    builder.startArray(fieldName);
    for (GeoPoint point : points) {
        builder.value(point);
    }
    builder.endArray();
    builder.field(UNIT_FIELD.getPreferredName(), unit);
    builder.field(DISTANCE_TYPE_FIELD.getPreferredName(), geoDistance.name().toLowerCase(Locale.ROOT));
    builder.field(ORDER_FIELD.getPreferredName(), order);
    if (sortMode != null) {
        builder.field(SORTMODE_FIELD.getPreferredName(), sortMode);
    }
    if (nestedPath != null) {
        builder.field(NESTED_PATH_FIELD.getPreferredName(), nestedPath);
    }
    if (nestedFilter != null) {
        builder.field(NESTED_FILTER_FIELD.getPreferredName(), nestedFilter, params);
    }
    builder.field(VALIDATION_METHOD_FIELD.getPreferredName(), validation);
    builder.endObject();
    builder.endObject();
    return builder;
}
Also used : GeoPoint(org.elasticsearch.common.geo.GeoPoint)

Example 2 with GeoPoint

use of org.elasticsearch.common.geo.GeoPoint in project elasticsearch by elastic.

the class GeoDistanceSortBuilder method fromXContent.

/**
     * Creates a new {@link GeoDistanceSortBuilder} from the query held by the {@link QueryParseContext} in
     * {@link org.elasticsearch.common.xcontent.XContent} format.
     *
     * @param context the input parse context. The state on the parser contained in this context will be changed as a
     *                side effect of this method call
     * @param elementName in some sort syntax variations the field name precedes the xContent object that specifies
     *                    further parameters, e.g. in '{ "foo": { "order" : "asc"} }'. When parsing the inner object,
     *                    the field name can be passed in via this argument
     */
public static GeoDistanceSortBuilder fromXContent(QueryParseContext context, String elementName) throws IOException {
    XContentParser parser = context.parser();
    String fieldName = null;
    List<GeoPoint> geoPoints = new ArrayList<>();
    DistanceUnit unit = DistanceUnit.DEFAULT;
    GeoDistance geoDistance = GeoDistance.ARC;
    SortOrder order = SortOrder.ASC;
    SortMode sortMode = null;
    QueryBuilder nestedFilter = null;
    String nestedPath = null;
    GeoValidationMethod validation = null;
    XContentParser.Token token;
    String currentName = parser.currentName();
    while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
        if (token == XContentParser.Token.FIELD_NAME) {
            currentName = parser.currentName();
        } else if (token == XContentParser.Token.START_ARRAY) {
            parseGeoPoints(parser, geoPoints);
            fieldName = currentName;
        } else if (token == XContentParser.Token.START_OBJECT) {
            if (NESTED_FILTER_FIELD.match(currentName)) {
                nestedFilter = context.parseInnerQueryBuilder();
            } else {
                // the json in the format of -> field : { lat : 30, lon : 12 }
                if (fieldName != null && fieldName.equals(currentName) == false) {
                    throw new ParsingException(parser.getTokenLocation(), "Trying to reset fieldName to [{}], already set to [{}].", currentName, fieldName);
                }
                fieldName = currentName;
                GeoPoint point = new GeoPoint();
                GeoUtils.parseGeoPoint(parser, point);
                geoPoints.add(point);
            }
        } else if (token.isValue()) {
            if (ORDER_FIELD.match(currentName)) {
                order = SortOrder.fromString(parser.text());
            } else if (UNIT_FIELD.match(currentName)) {
                unit = DistanceUnit.fromString(parser.text());
            } else if (DISTANCE_TYPE_FIELD.match(currentName)) {
                geoDistance = GeoDistance.fromString(parser.text());
            } else if (VALIDATION_METHOD_FIELD.match(currentName)) {
                validation = GeoValidationMethod.fromString(parser.text());
            } else if (SORTMODE_FIELD.match(currentName)) {
                sortMode = SortMode.fromString(parser.text());
            } else if (NESTED_PATH_FIELD.match(currentName)) {
                nestedPath = parser.text();
            } else if (token == Token.VALUE_STRING) {
                if (fieldName != null && fieldName.equals(currentName) == false) {
                    throw new ParsingException(parser.getTokenLocation(), "Trying to reset fieldName to [{}], already set to [{}].", currentName, fieldName);
                }
                GeoPoint point = new GeoPoint();
                point.resetFromString(parser.text());
                geoPoints.add(point);
                fieldName = currentName;
            } else if (fieldName.equals(currentName)) {
                throw new ParsingException(parser.getTokenLocation(), "Only geohashes of type string supported for field [{}]", currentName);
            } else {
                throw new ParsingException(parser.getTokenLocation(), "[{}] does not support [{}]", NAME, currentName);
            }
        }
    }
    GeoDistanceSortBuilder result = new GeoDistanceSortBuilder(fieldName, geoPoints.toArray(new GeoPoint[geoPoints.size()]));
    result.geoDistance(geoDistance);
    result.unit(unit);
    result.order(order);
    if (sortMode != null) {
        result.sortMode(sortMode);
    }
    if (nestedFilter != null) {
        result.setNestedFilter(nestedFilter);
    }
    result.setNestedPath(nestedPath);
    if (validation != null) {
        result.validation(validation);
    }
    return result;
}
Also used : GeoValidationMethod(org.elasticsearch.index.query.GeoValidationMethod) ArrayList(java.util.ArrayList) QueryBuilder(org.elasticsearch.index.query.QueryBuilder) GeoPoint(org.elasticsearch.common.geo.GeoPoint) Token(org.elasticsearch.common.xcontent.XContentParser.Token) ParsingException(org.elasticsearch.common.ParsingException) GeoDistance(org.elasticsearch.common.geo.GeoDistance) DistanceUnit(org.elasticsearch.common.unit.DistanceUnit) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Example 3 with GeoPoint

use of org.elasticsearch.common.geo.GeoPoint in project elasticsearch by elastic.

the class GeoDistanceSortBuilder method parseGeoPoints.

static void parseGeoPoints(XContentParser parser, List<GeoPoint> geoPoints) throws IOException {
    while (!parser.nextToken().equals(XContentParser.Token.END_ARRAY)) {
        if (parser.currentToken() == XContentParser.Token.VALUE_NUMBER) {
            // we might get here if the geo point is " number, number] " and the parser already moved over the
            // opening bracket in this case we cannot use GeoUtils.parseGeoPoint(..) because this expects an opening
            // bracket
            double lon = parser.doubleValue();
            parser.nextToken();
            if (!parser.currentToken().equals(XContentParser.Token.VALUE_NUMBER)) {
                throw new ElasticsearchParseException("geo point parsing: expected second number but got [{}] instead", parser.currentToken());
            }
            double lat = parser.doubleValue();
            GeoPoint point = new GeoPoint();
            point.reset(lat, lon);
            geoPoints.add(point);
        } else {
            GeoPoint point = new GeoPoint();
            GeoUtils.parseGeoPoint(parser, point);
            geoPoints.add(point);
        }
    }
}
Also used : GeoPoint(org.elasticsearch.common.geo.GeoPoint) ElasticsearchParseException(org.elasticsearch.ElasticsearchParseException)

Example 4 with GeoPoint

use of org.elasticsearch.common.geo.GeoPoint in project elasticsearch by elastic.

the class GeoDistanceSortBuilder method build.

@Override
public SortFieldAndFormat build(QueryShardContext context) throws IOException {
    final boolean indexCreatedBeforeV2_0 = context.indexVersionCreated().before(Version.V_2_0_0);
    // validation was not available prior to 2.x, so to support bwc percolation queries we only ignore_malformed
    // on 2.x created indexes
    GeoPoint[] localPoints = points.toArray(new GeoPoint[points.size()]);
    if (!indexCreatedBeforeV2_0 && !GeoValidationMethod.isIgnoreMalformed(validation)) {
        for (GeoPoint point : localPoints) {
            if (GeoUtils.isValidLatitude(point.lat()) == false) {
                throw new ElasticsearchParseException("illegal latitude value [{}] for [GeoDistanceSort] for field [{}].", point.lat(), fieldName);
            }
            if (GeoUtils.isValidLongitude(point.lon()) == false) {
                throw new ElasticsearchParseException("illegal longitude value [{}] for [GeoDistanceSort] for field [{}].", point.lon(), fieldName);
            }
        }
    }
    if (GeoValidationMethod.isCoerce(validation)) {
        for (GeoPoint point : localPoints) {
            GeoUtils.normalizePoint(point, true, true);
        }
    }
    boolean reverse = (order == SortOrder.DESC);
    final MultiValueMode finalSortMode;
    if (sortMode == null) {
        finalSortMode = reverse ? MultiValueMode.MAX : MultiValueMode.MIN;
    } else {
        finalSortMode = MultiValueMode.fromString(sortMode.toString());
    }
    MappedFieldType fieldType = context.fieldMapper(fieldName);
    if (fieldType == null) {
        throw new IllegalArgumentException("failed to find mapper for [" + fieldName + "] for geo distance based sort");
    }
    final IndexGeoPointFieldData geoIndexFieldData = context.getForField(fieldType);
    final Nested nested = resolveNested(context, nestedPath, nestedFilter);
    if (// only works with 5.x geo_point
    geoIndexFieldData.getClass() == LatLonPointDVIndexFieldData.class && nested == null && // LatLonDocValuesField internally picks the closest point
    finalSortMode == MultiValueMode.MIN && unit == DistanceUnit.METERS && reverse == false && localPoints.length == 1) {
        return new SortFieldAndFormat(LatLonDocValuesField.newDistanceSort(fieldName, localPoints[0].lat(), localPoints[0].lon()), DocValueFormat.RAW);
    }
    IndexFieldData.XFieldComparatorSource geoDistanceComparatorSource = new IndexFieldData.XFieldComparatorSource() {

        @Override
        public SortField.Type reducedType() {
            return SortField.Type.DOUBLE;
        }

        @Override
        public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) {
            return new FieldComparator.DoubleComparator(numHits, null, null) {

                @Override
                protected NumericDocValues getNumericDocValues(LeafReaderContext context, String field) throws IOException {
                    final MultiGeoPointValues geoPointValues = geoIndexFieldData.load(context).getGeoPointValues();
                    final SortedNumericDoubleValues distanceValues = GeoUtils.distanceValues(geoDistance, unit, geoPointValues, localPoints);
                    final NumericDoubleValues selectedValues;
                    if (nested == null) {
                        selectedValues = finalSortMode.select(distanceValues, Double.POSITIVE_INFINITY);
                    } else {
                        final BitSet rootDocs = nested.rootDocs(context);
                        final DocIdSetIterator innerDocs = nested.innerDocs(context);
                        selectedValues = finalSortMode.select(distanceValues, Double.POSITIVE_INFINITY, rootDocs, innerDocs, context.reader().maxDoc());
                    }
                    return selectedValues.getRawDoubleValues();
                }
            };
        }
    };
    return new SortFieldAndFormat(new SortField(fieldName, geoDistanceComparatorSource, reverse), DocValueFormat.RAW);
}
Also used : IndexGeoPointFieldData(org.elasticsearch.index.fielddata.IndexGeoPointFieldData) Nested(org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested) BitSet(org.apache.lucene.util.BitSet) SortField(org.apache.lucene.search.SortField) NumericDoubleValues(org.elasticsearch.index.fielddata.NumericDoubleValues) SortedNumericDoubleValues(org.elasticsearch.index.fielddata.SortedNumericDoubleValues) MultiValueMode(org.elasticsearch.search.MultiValueMode) GeoPoint(org.elasticsearch.common.geo.GeoPoint) LatLonPointDVIndexFieldData(org.elasticsearch.index.fielddata.plain.AbstractLatLonPointDVIndexFieldData.LatLonPointDVIndexFieldData) ElasticsearchParseException(org.elasticsearch.ElasticsearchParseException) MappedFieldType(org.elasticsearch.index.mapper.MappedFieldType) LeafReaderContext(org.apache.lucene.index.LeafReaderContext) LatLonPointDVIndexFieldData(org.elasticsearch.index.fielddata.plain.AbstractLatLonPointDVIndexFieldData.LatLonPointDVIndexFieldData) IndexFieldData(org.elasticsearch.index.fielddata.IndexFieldData) SortedNumericDoubleValues(org.elasticsearch.index.fielddata.SortedNumericDoubleValues) MultiGeoPointValues(org.elasticsearch.index.fielddata.MultiGeoPointValues) DocIdSetIterator(org.apache.lucene.search.DocIdSetIterator)

Example 5 with GeoPoint

use of org.elasticsearch.common.geo.GeoPoint in project elasticsearch by elastic.

the class DecayFunctionBuilder method parseGeoVariable.

private AbstractDistanceScoreFunction parseGeoVariable(XContentParser parser, QueryShardContext context, MappedFieldType fieldType, MultiValueMode mode) throws IOException {
    XContentParser.Token token;
    String parameterName = null;
    GeoPoint origin = new GeoPoint();
    String scaleString = null;
    String offsetString = "0km";
    double decay = 0.5;
    while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
        if (token == XContentParser.Token.FIELD_NAME) {
            parameterName = parser.currentName();
        } else if (DecayFunctionBuilder.SCALE.equals(parameterName)) {
            scaleString = parser.text();
        } else if (DecayFunctionBuilder.ORIGIN.equals(parameterName)) {
            origin = GeoUtils.parseGeoPoint(parser);
        } else if (DecayFunctionBuilder.DECAY.equals(parameterName)) {
            decay = parser.doubleValue();
        } else if (DecayFunctionBuilder.OFFSET.equals(parameterName)) {
            offsetString = parser.text();
        } else {
            throw new ElasticsearchParseException("parameter [{}] not supported!", parameterName);
        }
    }
    if (origin == null || scaleString == null) {
        throw new ElasticsearchParseException("[{}] and [{}] must be set for geo fields.", DecayFunctionBuilder.ORIGIN, DecayFunctionBuilder.SCALE);
    }
    double scale = DistanceUnit.DEFAULT.parse(scaleString, DistanceUnit.DEFAULT);
    double offset = DistanceUnit.DEFAULT.parse(offsetString, DistanceUnit.DEFAULT);
    IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
    return new GeoFieldDataScoreFunction(origin, scale, decay, offset, getDecayFunction(), indexFieldData, mode);
}
Also used : GeoPoint(org.elasticsearch.common.geo.GeoPoint) IndexGeoPointFieldData(org.elasticsearch.index.fielddata.IndexGeoPointFieldData) ElasticsearchParseException(org.elasticsearch.ElasticsearchParseException) XContentParser(org.elasticsearch.common.xcontent.XContentParser)

Aggregations

GeoPoint (org.elasticsearch.common.geo.GeoPoint)124 SearchResponse (org.elasticsearch.action.search.SearchResponse)40 ElasticsearchAssertions.assertSearchResponse (org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse)27 ArrayList (java.util.ArrayList)20 XContentBuilder (org.elasticsearch.common.xcontent.XContentBuilder)15 XContentParser (org.elasticsearch.common.xcontent.XContentParser)10 GeoBounds (org.elasticsearch.search.aggregations.metrics.geobounds.GeoBounds)9 ElasticsearchParseException (org.elasticsearch.ElasticsearchParseException)8 Range (org.elasticsearch.search.aggregations.bucket.range.Range)8 GeoCentroid (org.elasticsearch.search.aggregations.metrics.geocentroid.GeoCentroid)8 Version (org.elasticsearch.Version)7 Bucket (org.elasticsearch.search.aggregations.bucket.range.Range.Bucket)7 Settings (org.elasticsearch.common.settings.Settings)6 MultiGeoPointValues (org.elasticsearch.index.fielddata.MultiGeoPointValues)6 IndexRequestBuilder (org.elasticsearch.action.index.IndexRequestBuilder)5 ParsingException (org.elasticsearch.common.ParsingException)5 SearchHit (org.elasticsearch.search.SearchHit)5 Test (org.testng.annotations.Test)5 HashSet (java.util.HashSet)4 DistanceUnit (org.elasticsearch.common.unit.DistanceUnit)4