![JAR search and dependency download from the Maven repository](/logo.png)
org.opensearch.index.query.DistanceFeatureQueryBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opensearch Show documentation
Show all versions of opensearch Show documentation
OpenSearch subproject :server
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* 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.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.index.query;
import org.apache.lucene.search.Query;
import org.opensearch.common.ParseField;
import org.opensearch.common.ParsingException;
import org.opensearch.common.geo.GeoPoint;
import org.opensearch.common.geo.GeoUtils;
import org.opensearch.common.io.stream.StreamInput;
import org.opensearch.common.io.stream.StreamOutput;
import org.opensearch.common.lucene.search.Queries;
import org.opensearch.common.xcontent.ConstructingObjectParser;
import org.opensearch.common.xcontent.ObjectParser;
import org.opensearch.common.xcontent.XContentBuilder;
import org.opensearch.common.xcontent.XContentParser;
import org.opensearch.index.mapper.MappedFieldType;
import java.io.IOException;
import java.util.Objects;
import static org.opensearch.common.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(QueryShardContext context) throws IOException {
MappedFieldType fieldType = context.fieldMapper(field);
if (fieldType == null) {
return Queries.newMatchNoDocsQuery("Can't run [" + NAME + "] query on unmapped fields!");
}
// As we already apply boost in AbstractQueryBuilder::toQuery, we always passing a boost of 1.0 to distanceFeatureQuery
return fieldType.distanceFeatureQuery(origin.origin(), pivot, 1.0f, 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();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy