org.elasticsearch.index.query.DistanceFeatureQueryBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch - Open Source, Distributed, RESTful Search Engine
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.elasticsearch.TransportVersion;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.xcontent.ConstructingObjectParser;
import org.elasticsearch.xcontent.ObjectParser;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
/**
* A query to boost scores based on their proximity to the given origin
* for date, date_nanos and geo_point field types
*/
public class DistanceFeatureQueryBuilder extends AbstractQueryBuilder {
public static final String NAME = "distance_feature";
private static final ParseField FIELD_FIELD = new ParseField("field");
private static final ParseField ORIGIN_FIELD = new ParseField("origin");
private static final ParseField PIVOT_FIELD = new ParseField("pivot");
private final String field;
private final Origin origin;
private final String pivot;
private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
"distance_feature",
false,
args -> new DistanceFeatureQueryBuilder((String) args[0], (Origin) args[1], (String) args[2])
);
static {
PARSER.declareString(constructorArg(), FIELD_FIELD);
// origin: number or string for date and date_nanos fields; string, array, object for geo fields
PARSER.declareField(
constructorArg(),
DistanceFeatureQueryBuilder.Origin::originFromXContent,
ORIGIN_FIELD,
ObjectParser.ValueType.OBJECT_ARRAY_STRING_OR_NUMBER
);
PARSER.declareString(constructorArg(), PIVOT_FIELD);
declareStandardFields(PARSER);
}
public DistanceFeatureQueryBuilder(String field, Origin origin, String pivot) {
this.field = Objects.requireNonNull(field);
this.origin = Objects.requireNonNull(origin);
this.pivot = Objects.requireNonNull(pivot);
}
public static DistanceFeatureQueryBuilder fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);
builder.field(FIELD_FIELD.getPreferredName(), field);
builder.field(ORIGIN_FIELD.getPreferredName(), origin.origin);
builder.field(PIVOT_FIELD.getPreferredName(), pivot);
printBoostAndQueryName(builder);
builder.endObject();
}
public DistanceFeatureQueryBuilder(StreamInput in) throws IOException {
super(in);
field = in.readString();
origin = new Origin(in);
pivot = in.readString();
}
@Override
protected void doWriteTo(StreamOutput out) throws IOException {
out.writeString(field);
origin.writeTo(out);
out.writeString(pivot);
}
@Override
public String getWriteableName() {
return NAME;
}
@Override
protected Query doToQuery(SearchExecutionContext context) throws IOException {
MappedFieldType fieldType = context.getFieldType(field);
if (fieldType == null) {
return Queries.newMatchNoDocsQuery("Can't run [" + NAME + "] query on unmapped fields!");
}
return fieldType.distanceFeatureQuery(origin.origin(), pivot, context);
}
String fieldName() {
return field;
}
Origin origin() {
return origin;
}
String pivot() {
return pivot;
}
@Override
protected int doHashCode() {
return Objects.hash(field, origin, pivot);
}
@Override
protected boolean doEquals(DistanceFeatureQueryBuilder other) {
return this.field.equals(other.field) && Objects.equals(this.origin, other.origin) && this.pivot.equals(other.pivot);
}
public static class Origin {
private final Object origin;
public Origin(Long origin) {
this.origin = Objects.requireNonNull(origin);
}
public Origin(String origin) {
this.origin = Objects.requireNonNull(origin);
}
public Origin(GeoPoint origin) {
this.origin = Objects.requireNonNull(origin);
}
private static Origin originFromXContent(XContentParser parser) throws IOException {
if (parser.currentToken() == XContentParser.Token.VALUE_NUMBER) {
return new Origin(parser.longValue());
} else if (parser.currentToken() == XContentParser.Token.VALUE_STRING) {
return new Origin(parser.text());
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
return new Origin(GeoUtils.parseGeoPoint(parser));
} else if (parser.currentToken() == XContentParser.Token.START_ARRAY) {
return new Origin(GeoUtils.parseGeoPoint(parser));
} else {
throw new ParsingException(
parser.getTokenLocation(),
"Illegal type while parsing [origin]! Must be [number] or [string] for date and date_nanos fields;"
+ " or [string], [array], [object] for geo_point fields!"
);
}
}
private Origin(StreamInput in) throws IOException {
origin = in.readGenericValue();
}
private void writeTo(final StreamOutput out) throws IOException {
out.writeGenericValue(origin);
}
Object origin() {
return origin;
}
@Override
public final boolean equals(Object other) {
if ((other instanceof Origin) == false) {
return false;
}
Object otherOrigin = ((Origin) other).origin();
return this.origin().equals(otherOrigin);
}
@Override
public int hashCode() {
return Objects.hash(origin);
}
@Override
public String toString() {
return origin.toString();
}
}
@Override
public TransportVersion getMinimalSupportedVersion() {
return TransportVersion.V_7_2_0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy