Query Refactoring: moving validation to setters and constructors

Moving validation from validate() to constructors and setters for the
following query builders:

* GeoDistanceQueryBuilder
* GeoDistanceRangeQueryBuilder
* GeoPolygonQueryBuilder
* GeoShapeQueryBuilder
* GeohashCellQuery
* TermsQueryBuilder

Relates to #10217
This commit is contained in:
Christoph Büscher 2015-09-18 15:22:17 +02:00
parent cc69de5c5f
commit 03035a28a3
29 changed files with 507 additions and 795 deletions

View File

@ -114,13 +114,6 @@ public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder> exte
return context.indexQueryParserService().indicesQueriesRegistry().queryParsers().get(getName()).parse(context);
}
@Override
public QueryValidationException validate() {
// default impl does not validate, subclasses should override.
//norelease to be possibly made abstract once all queries support validation
return null;
}
/**
* Returns the query name for the query.
*/
@ -267,27 +260,6 @@ public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder> exte
return queries;
}
protected QueryValidationException validateInnerQueries(List<QueryBuilder> queryBuilders, QueryValidationException initialValidationException) {
QueryValidationException validationException = initialValidationException;
for (QueryBuilder queryBuilder : queryBuilders) {
validationException = validateInnerQuery(queryBuilder, validationException);
}
return validationException;
}
protected QueryValidationException validateInnerQuery(QueryBuilder queryBuilder, QueryValidationException initialValidationException) {
QueryValidationException validationException = initialValidationException;
if (queryBuilder != null) {
QueryValidationException queryValidationException = queryBuilder.validate();
if (queryValidationException != null) {
validationException = QueryValidationException.addValidationErrors(queryValidationException.validationErrors(), validationException);
}
} else {
validationException = addValidationError("inner query cannot be null", validationException);
}
return validationException;
}
@Override
public String getName() {
//default impl returns the same as writeable name, but we keep the distinction between the two just to make sure

View File

@ -78,13 +78,6 @@ public class EmptyQueryBuilder extends ToXContentToBytes implements QueryBuilder
return null;
}
@Override
public QueryValidationException validate() {
// nothing to validate
return null;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
}

View File

@ -21,7 +21,6 @@ package org.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.elasticsearch.Version;
import org.elasticsearch.common.Numbers;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
@ -76,12 +75,7 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
/** Whether or not to accept geo points with invalid latitude or longitude */
private boolean ignoreMalformed = DEFAULT_IGNORE_MALFORMED;
static final GeoDistanceQueryBuilder PROTOTYPE = new GeoDistanceQueryBuilder();
/** For serialization purposes only. */
private GeoDistanceQueryBuilder() {
this.fieldName = null;
}
static final GeoDistanceQueryBuilder PROTOTYPE = new GeoDistanceQueryBuilder("_na_");
/**
* Construct new GeoDistanceQueryBuilder.
@ -127,10 +121,7 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
/** Sets the distance from the center using the default distance unit.*/
public GeoDistanceQueryBuilder distance(String distance) {
if (Strings.isEmpty(distance)) {
throw new IllegalArgumentException("distance must not be null or empty");
}
return this.distance(distance, DistanceUnit.DEFAULT);
return distance(distance, DistanceUnit.DEFAULT);
}
/** Sets the distance from the center for this query. */
@ -147,11 +138,7 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
/** Sets the distance from the center for this query. */
public GeoDistanceQueryBuilder distance(double distance, DistanceUnit unit) {
if (unit == null) {
throw new IllegalArgumentException("distance unit must not be null");
}
this.distance = DistanceUnit.DEFAULT.convert(distance, unit);
return this;
return distance(Double.toString(distance), unit);
}
/** Returns the distance configured as radius. */
@ -188,8 +175,16 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
* enclosing bounding box.
**/
public GeoDistanceQueryBuilder optimizeBbox(String optimizeBbox) {
if (Strings.isEmpty(optimizeBbox)) {
throw new IllegalArgumentException("optimizeBbox must not be null or empty");
if (optimizeBbox == null) {
throw new IllegalArgumentException("optimizeBox must not be null");
}
switch (optimizeBbox) {
case "none":
case "memory":
case "indexed":
break;
default:
throw new IllegalArgumentException("optimizeBbox must be one of [none, memory, indexed]");
}
this.optimizeBbox = optimizeBbox;
return this;
@ -249,9 +244,7 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
builder.startObject(NAME);
builder.startArray(fieldName).value(center.lon()).value(center.lat()).endArray();
builder.field("distance", distance);
if (geoDistance != null) {
builder.field("distance_type", geoDistance.name().toLowerCase(Locale.ROOT));
}
builder.field("distance_type", geoDistance.name().toLowerCase(Locale.ROOT));
builder.field("optimize_bbox", optimizeBbox);
builder.field("coerce", coerce);
builder.field("ignore_malformed", ignoreMalformed);
@ -299,29 +292,6 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
geoDistance.writeTo(out);
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (!ignoreMalformed) {
if (Numbers.isValidDouble(center.getLat()) == false) {
validationException = addValidationError("center point latitude is invalid number: " + center.getLat(), validationException);
}
if (Numbers.isValidDouble(center.getLon()) == false) {
validationException = addValidationError("center point longitude is invalid number: " + center.getLon(),
validationException);
}
}
if (Strings.isEmpty(fieldName)) {
validationException = addValidationError("field name must be non-null and non-empty", validationException);
}
if (optimizeBbox != null && !(optimizeBbox.equals("none") || optimizeBbox.equals("memory") || optimizeBbox.equals("indexed"))) {
validationException = QueryValidationException.addValidationError(NAME, "optimizeBbox must be one of [none, memory, indexed]",
validationException);
}
return validationException;
}
/**
* @param indexCreatedBeforeV2_0
* @return

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.elasticsearch.Version;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
@ -55,7 +56,7 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
private boolean includeLower = DEFAULT_INCLUDE_LOWER;
private boolean includeUpper = DEFAULT_INCLUDE_UPPER;
private GeoPoint point;
private final GeoPoint point;
private GeoDistance geoDistance = DEFAULT_GEO_DISTANCE;
@ -67,31 +68,47 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
private boolean ignoreMalformed = DEFAULT_IGNORE_MALFORMED;
static final GeoDistanceRangeQueryBuilder PROTOTYPE = new GeoDistanceRangeQueryBuilder(null);
static final GeoDistanceRangeQueryBuilder PROTOTYPE = new GeoDistanceRangeQueryBuilder("_na_", new GeoPoint());
public GeoDistanceRangeQueryBuilder(String fieldName) {
public GeoDistanceRangeQueryBuilder(String fieldName, GeoPoint point) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("fieldName must not be null");
}
if (point == null) {
throw new IllegalArgumentException("point must not be null");
}
this.fieldName = fieldName;
this.point = point;
}
public GeoDistanceRangeQueryBuilder(String fieldName, double lat, double lon) {
this(fieldName, new GeoPoint(lat, lon));
}
public GeoDistanceRangeQueryBuilder(String fieldName, String geohash) {
this(fieldName, geohash == null ? null : new GeoPoint().resetFromGeoHash(geohash));
}
public String fieldName() {
return fieldName;
}
public GeoDistanceRangeQueryBuilder point(double lat, double lon) {
this.point = new GeoPoint(lat, lon);
return this;
}
public GeoDistanceRangeQueryBuilder point(GeoPoint point) {
this.point = point;
return this;
}
public GeoPoint point() {
return point;
}
public GeoDistanceRangeQueryBuilder from(Object from) {
public GeoDistanceRangeQueryBuilder from(String from) {
if (from == null) {
throw new IllegalArgumentException("[from] must not be null");
}
this.from = from;
return this;
}
public GeoDistanceRangeQueryBuilder from(Number from) {
if (from == null) {
throw new IllegalArgumentException("[from] must not be null");
}
this.from = from;
return this;
}
@ -100,7 +117,18 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
return from;
}
public GeoDistanceRangeQueryBuilder to(Object to) {
public GeoDistanceRangeQueryBuilder to(String to) {
if (to == null) {
throw new IllegalArgumentException("[to] must not be null");
}
this.to = to;
return this;
}
public GeoDistanceRangeQueryBuilder to(Number to) {
if (to == null) {
throw new IllegalArgumentException("[to] must not be null");
}
this.to = to;
return this;
}
@ -109,30 +137,6 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
return to;
}
public GeoDistanceRangeQueryBuilder gt(Object from) {
this.from = from;
this.includeLower = false;
return this;
}
public GeoDistanceRangeQueryBuilder gte(Object from) {
this.from = from;
this.includeLower = true;
return this;
}
public GeoDistanceRangeQueryBuilder lt(Object to) {
this.to = to;
this.includeUpper = false;
return this;
}
public GeoDistanceRangeQueryBuilder lte(Object to) {
this.to = to;
this.includeUpper = true;
return this;
}
public GeoDistanceRangeQueryBuilder includeLower(boolean includeLower) {
this.includeLower = includeLower;
return this;
@ -151,12 +155,10 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
return includeUpper;
}
public GeoDistanceRangeQueryBuilder geohash(String geohash) {
this.point = new GeoPoint().resetFromGeoHash(geohash);
return this;
}
public GeoDistanceRangeQueryBuilder geoDistance(GeoDistance geoDistance) {
if (geoDistance == null) {
throw new IllegalArgumentException("geoDistance calculation mode must not be null");
}
this.geoDistance = geoDistance;
return this;
}
@ -166,6 +168,9 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
}
public GeoDistanceRangeQueryBuilder unit(DistanceUnit unit) {
if (unit == null) {
throw new IllegalArgumentException("distance unit must not be null");
}
this.unit = unit;
return this;
}
@ -175,6 +180,17 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
}
public GeoDistanceRangeQueryBuilder optimizeBbox(String optimizeBbox) {
if (optimizeBbox == null) {
throw new IllegalArgumentException("optimizeBox must not be null");
}
switch (optimizeBbox) {
case "none":
case "memory":
case "indexed":
break;
default:
throw new IllegalArgumentException("optimizeBbox must be one of [none, memory, indexed]");
}
this.optimizeBbox = optimizeBbox;
return this;
}
@ -206,32 +222,6 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
return ignoreMalformed;
}
@Override
public QueryValidationException validate() {
QueryValidationException errors = null;
if (fieldName == null) {
errors = QueryValidationException.addValidationError(NAME, "fieldName must not be null", errors);
}
if (point == null) {
errors = QueryValidationException.addValidationError(NAME, "point must not be null", errors);
}
if (from == null && to == null) {
errors = QueryValidationException.addValidationError(NAME, "Must define at least one parameter from [from, to]", errors);
}
if (from != null && !(from instanceof Number || from instanceof String)) {
errors = QueryValidationException.addValidationError(NAME, "from must either be a number or a string. Found ["
+ from.getClass().getName() + "]", errors);
}
if (to != null && !(to instanceof Number || to instanceof String)) {
errors = QueryValidationException.addValidationError(NAME, "to must either be a number or a string. Found ["
+ to.getClass().getName() + "]", errors);
}
if (optimizeBbox != null && !(optimizeBbox.equals("none") || optimizeBbox.equals("memory") || optimizeBbox.equals("indexed"))) {
errors = QueryValidationException.addValidationError(NAME, "optimizeBbox must be one of [none, memory, indexed]", errors);
}
return errors;
}
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
@ -292,15 +282,9 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
builder.field(GeoDistanceRangeQueryParser.TO_FIELD.getPreferredName(), to);
builder.field(GeoDistanceRangeQueryParser.INCLUDE_LOWER_FIELD.getPreferredName(), includeLower);
builder.field(GeoDistanceRangeQueryParser.INCLUDE_UPPER_FIELD.getPreferredName(), includeUpper);
if (unit != null) {
builder.field(GeoDistanceRangeQueryParser.UNIT_FIELD.getPreferredName(), unit);
}
if (geoDistance != null) {
builder.field(GeoDistanceRangeQueryParser.DISTANCE_TYPE_FIELD.getPreferredName(), geoDistance.name().toLowerCase(Locale.ROOT));
}
if (optimizeBbox != null) {
builder.field(GeoDistanceRangeQueryParser.OPTIMIZE_BBOX_FIELD.getPreferredName(), optimizeBbox);
}
builder.field(GeoDistanceRangeQueryParser.UNIT_FIELD.getPreferredName(), unit);
builder.field(GeoDistanceRangeQueryParser.DISTANCE_TYPE_FIELD.getPreferredName(), geoDistance.name().toLowerCase(Locale.ROOT));
builder.field(GeoDistanceRangeQueryParser.OPTIMIZE_BBOX_FIELD.getPreferredName(), optimizeBbox);
builder.field(GeoDistanceRangeQueryParser.COERCE_FIELD.getPreferredName(), coerce);
builder.field(GeoDistanceRangeQueryParser.IGNORE_MALFORMED_FIELD.getPreferredName(), ignoreMalformed);
printBoostAndQueryName(builder);
@ -309,21 +293,14 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
@Override
protected GeoDistanceRangeQueryBuilder doReadFrom(StreamInput in) throws IOException {
GeoDistanceRangeQueryBuilder queryBuilder = new GeoDistanceRangeQueryBuilder(in.readString());
queryBuilder.point = GeoPoint.readGeoPointFrom(in);
GeoDistanceRangeQueryBuilder queryBuilder = new GeoDistanceRangeQueryBuilder(in.readString(), GeoPoint.readGeoPointFrom(in));
queryBuilder.from = in.readGenericValue();
queryBuilder.to = in.readGenericValue();
queryBuilder.includeLower = in.readBoolean();
queryBuilder.includeUpper = in.readBoolean();
String unit = in.readOptionalString();
if (unit != null) {
queryBuilder.unit = DistanceUnit.valueOf(unit);
}
String geoDistance = in.readOptionalString();
if (geoDistance != null) {
queryBuilder.geoDistance = GeoDistance.fromString(geoDistance);
}
queryBuilder.optimizeBbox = in.readOptionalString();
queryBuilder.unit = DistanceUnit.valueOf(in.readString());
queryBuilder.geoDistance = GeoDistance.readGeoDistanceFrom(in);
queryBuilder.optimizeBbox = in.readString();
queryBuilder.coerce = in.readBoolean();
queryBuilder.ignoreMalformed = in.readBoolean();
return queryBuilder;
@ -337,9 +314,9 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
out.writeGenericValue(to);
out.writeBoolean(includeLower);
out.writeBoolean(includeUpper);
out.writeOptionalString(unit.name());
out.writeOptionalString(geoDistance.name());
out.writeOptionalString(optimizeBbox);
out.writeString(unit.name());
geoDistance.writeTo(out);;
out.writeString(optimizeBbox);
out.writeBoolean(coerce);
out.writeBoolean(ignoreMalformed);
}

View File

@ -23,7 +23,6 @@ import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
@ -76,7 +75,6 @@ public class GeoDistanceRangeQueryParser extends BaseQueryParser<GeoDistanceRang
String queryName = null;
String currentFieldName = null;
GeoPoint point = null;
String geohash = null;
String fieldName = null;
Object vFrom = null;
Object vTo = null;
@ -173,7 +171,7 @@ public class GeoDistanceRangeQueryParser extends BaseQueryParser<GeoDistanceRang
point.resetLon(parser.doubleValue());
fieldName = currentFieldName.substring(0, currentFieldName.length() - GeoPointFieldMapper.Names.LON_SUFFIX.length());
} else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.GEOHASH_SUFFIX)) {
geohash = parser.text();
point = GeoPoint.fromGeohash(parser.text());
fieldName = currentFieldName.substring(0, currentFieldName.length() - GeoPointFieldMapper.Names.GEOHASH_SUFFIX.length());
} else if (parseContext.parseFieldMatcher().match(currentFieldName, NAME_FIELD)) {
queryName = parser.text();
@ -195,8 +193,7 @@ public class GeoDistanceRangeQueryParser extends BaseQueryParser<GeoDistanceRang
}
}
GeoDistanceRangeQueryBuilder queryBuilder = new GeoDistanceRangeQueryBuilder(fieldName);
GeoDistanceRangeQueryBuilder queryBuilder = new GeoDistanceRangeQueryBuilder(fieldName, point);
if (boost != null) {
queryBuilder.boost(boost);
}
@ -205,20 +202,12 @@ public class GeoDistanceRangeQueryParser extends BaseQueryParser<GeoDistanceRang
queryBuilder.queryName(queryName);
}
if (point != null) {
queryBuilder.point(point.lat(), point.lon());
}
if (geohash != null) {
queryBuilder.geohash(geohash);
}
if (vFrom != null) {
queryBuilder.from(vFrom);
queryBuilder.from(vFrom.toString());
}
if (vTo != null) {
queryBuilder.to(vTo);
queryBuilder.to(vTo.toString());
}
if (includeUpper != null) {

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.elasticsearch.Version;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.io.stream.StreamInput;
@ -33,6 +34,7 @@ import org.elasticsearch.index.search.geo.GeoPolygonQuery;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@ -40,7 +42,10 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery
public static final String NAME = "geo_polygon";
static final GeoPolygonQueryBuilder PROTOTYPE = new GeoPolygonQueryBuilder("");
private static final List<GeoPoint> PROTO_SHAPE = Arrays.asList(new GeoPoint[] { new GeoPoint(1.0, 1.0), new GeoPoint(1.0, 2.0),
new GeoPoint(2.0, 1.0) });
static final GeoPolygonQueryBuilder PROTOTYPE = new GeoPolygonQueryBuilder("field", PROTO_SHAPE);
private final String fieldName;
@ -50,16 +55,23 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery
private boolean ignoreMalformed = false;
public GeoPolygonQueryBuilder(String fieldName) {
this(fieldName, new ArrayList<>());
}
public GeoPolygonQueryBuilder(String fieldName, List<GeoPoint> points) {
if (fieldName == null) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("fieldName must not be null");
}
if (points == null) {
throw new IllegalArgumentException("polygon must not be null");
if (points == null || points.isEmpty()) {
throw new IllegalArgumentException("polygon must not be null or empty");
} else {
GeoPoint start = points.get(0);
if (start.equals(points.get(points.size() - 1))) {
if (points.size() < 4) {
throw new IllegalArgumentException("too few points defined for geo_polygon query");
}
} else {
if (points.size() < 3) {
throw new IllegalArgumentException("too few points defined for geo_polygon query");
}
}
}
this.fieldName = fieldName;
this.shell = points;
@ -69,26 +81,6 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery
return fieldName;
}
/**
* Adds a point with lat and lon
*
* @param lat The latitude
* @param lon The longitude
* @return the current builder
*/
public GeoPolygonQueryBuilder addPoint(double lat, double lon) {
return addPoint(new GeoPoint(lat, lon));
}
public GeoPolygonQueryBuilder addPoint(String geohash) {
return addPoint(GeoPoint.fromGeohash(geohash));
}
public GeoPolygonQueryBuilder addPoint(GeoPoint point) {
shell.add(point);
return this;
}
public List<GeoPoint> points() {
return shell;
}
@ -116,29 +108,6 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery
return ignoreMalformed;
}
@Override
public QueryValidationException validate() {
QueryValidationException errors = null;
if (fieldName == null) {
errors = QueryValidationException.addValidationError(NAME, "field must not be null", errors);
}
if (shell.isEmpty()) {
errors = QueryValidationException.addValidationError(NAME, "no points defined for geo_polygon query", errors);
} else {
GeoPoint start = shell.get(0);
if (start.equals(shell.get(shell.size() - 1))) {
if (shell.size() < 4) {
errors = QueryValidationException.addValidationError(NAME, "too few points defined for geo_polygon query", errors);
}
} else {
if (shell.size() < 3) {
errors = QueryValidationException.addValidationError(NAME, "too few points defined for geo_polygon query", errors);
}
}
}
return errors;
}
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {

View File

@ -62,7 +62,7 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
public static final String DEFAULT_SHAPE_FIELD_NAME = "shape";
public static final ShapeRelation DEFAULT_SHAPE_RELATION = ShapeRelation.INTERSECTS;
static final GeoShapeQueryBuilder PROTOTYPE = new GeoShapeQueryBuilder("", new BytesArray(new byte[0]));
static final GeoShapeQueryBuilder PROTOTYPE = new GeoShapeQueryBuilder("field", new BytesArray(new byte[1]));
private final String fieldName;
@ -114,11 +114,17 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
}
private GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape, String indexedShapeId, String indexedShapeType) throws IOException {
this(fieldName, new BytesArray(new byte[0]), indexedShapeId, indexedShapeType);
this(fieldName, new BytesArray(new byte[1]), indexedShapeId, indexedShapeType);
if (shape != null) {
XContentBuilder builder = XContentFactory.jsonBuilder();
shape.toXContent(builder, EMPTY_PARAMS);
this.shapeBytes = builder.bytes();
BytesReference bytes = builder.bytes();
if (bytes.length() == 0) {
throw new IllegalArgumentException("shape must not be empty");
}
this.shapeBytes = bytes;
} else {
throw new IllegalArgumentException("shape must not be null");
}
}
@ -126,7 +132,7 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
if (fieldName == null) {
throw new IllegalArgumentException("fieldName is required");
}
if (shapeBytes == null && indexedShapeId == null) {
if ((shapeBytes == null || shapeBytes.length() == 0) && indexedShapeId == null) {
throw new IllegalArgumentException("either shapeBytes or indexedShapeId and indexedShapeType are required");
}
if (indexedShapeId != null && indexedShapeType == null) {
@ -232,6 +238,9 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
* @return this
*/
public GeoShapeQueryBuilder relation(ShapeRelation relation) {
if (relation == null) {
throw new IllegalArgumentException("No Shape Relation defined");
}
this.relation = relation;
return this;
}
@ -243,21 +252,9 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
return relation;
}
@Override
public QueryValidationException validate() {
QueryValidationException errors = null;
if (fieldName == null) {
errors = QueryValidationException.addValidationError(NAME, "No field defined", errors);
}
if ((shapeBytes == null || shapeBytes.length() == 0) && indexedShapeId == null) {
errors = QueryValidationException.addValidationError(NAME, "No Shape defined", errors);
}
if (relation == null) {
errors = QueryValidationException.addValidationError(NAME, "No Shape Relation defined", errors);
}
if (indexedShapeId != null && indexedShapeType == null) {
errors = QueryValidationException.addValidationError(NAME, "Type for indexed shape not provided", errors);
}
// TODO did we validate this before the refactoring and can we do this in setters at all?
if (strategy != null && strategy == SpatialStrategy.TERM && relation != ShapeRelation.INTERSECTS) {
errors = QueryValidationException.addValidationError(NAME,
"strategy [" + strategy.getStrategyName() + "] only supports relation ["

View File

@ -102,15 +102,11 @@ public class GeohashCellQuery {
private String geohash;
private Integer levels = null;
private boolean neighbors = DEFAULT_NEIGHBORS;
private static final Builder PROTOTYPE = new Builder(null);
private static final Builder PROTOTYPE = new Builder("field", new GeoPoint());
public Builder(String field) {
this(field, null, false);
}
public Builder(String field, GeoPoint point) {
this(field, point.geohash(), false);
this(field, point == null ? null : point.geohash(), false);
}
public Builder(String field, String geohash) {
@ -118,7 +114,12 @@ public class GeohashCellQuery {
}
public Builder(String field, String geohash, boolean neighbors) {
super();
if (Strings.isEmpty(field)) {
throw new IllegalArgumentException("fieldName must not be null");
}
if (Strings.isEmpty(geohash)) {
throw new IllegalArgumentException("geohash or point must be defined");
}
this.fieldName = field;
this.geohash = geohash;
this.neighbors = neighbors;
@ -144,6 +145,9 @@ public class GeohashCellQuery {
}
public Builder precision(int levels) {
if (levels <= 0) {
throw new IllegalArgumentException("precision must be greater than 0. Found [" + levels + "]");
}
this.levels = levels;
return this;
}
@ -175,22 +179,6 @@ public class GeohashCellQuery {
return fieldName;
}
@Override
public QueryValidationException validate() {
QueryValidationException errors = null;
if (fieldName == null) {
errors = QueryValidationException.addValidationError(NAME, "fieldName must not be null", errors);
}
if (geohash == null) {
errors = QueryValidationException.addValidationError(NAME, "geohash or point must be defined", errors);
}
if (levels != null && levels <= 0) {
errors = QueryValidationException.addValidationError(NAME, "precision must be greater than 0. Found [" + levels + "]",
errors);
}
return errors;
}
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
MappedFieldType fieldType = context.fieldMapper(fieldName);
@ -348,8 +336,7 @@ public class GeohashCellQuery {
throw new ElasticsearchParseException("failed to parse [{}] query. unexpected token [{}]", NAME, token);
}
}
Builder builder = new Builder(fieldName);
builder.geohash(geohash);
Builder builder = new Builder(fieldName, geohash);
if (levels != null) {
builder.precision(levels);
}

View File

@ -943,7 +943,6 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
}
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (likeTexts.isEmpty() && likeItems.isEmpty()) {

View File

@ -30,13 +30,6 @@ import java.io.IOException;
public interface QueryBuilder<QB extends QueryBuilder> extends NamedWriteable<QB>, ToXContent {
/**
* Validate the query.
* @return a {@link QueryValidationException} containing error messages, {@code null} if query is valid.
* e.g. if fields that are needed to create the lucene query are missing.
*/
QueryValidationException validate();
/**
* Converts this QueryBuilder to a lucene {@link Query}.
* Returns <tt>null</tt> if this query should be ignored in the context of

View File

@ -27,12 +27,14 @@ import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.search.MatchQuery;
import org.elasticsearch.indices.cache.query.terms.TermsLookup;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.Template;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
@ -579,8 +581,8 @@ public abstract class QueryBuilders {
/**
* A terms query that can extract the terms from another doc in an index.
*/
public static TermsQueryBuilder termsLookupQuery(String name) {
return new TermsQueryBuilder(name);
public static TermsQueryBuilder termsLookupQuery(String name, TermsLookup termsLookup) {
return new TermsQueryBuilder(name, termsLookup);
}
/**
@ -606,9 +608,31 @@ public abstract class QueryBuilders {
* A filter to filter based on a specific range from a specific geo location / point.
*
* @param name The location field name.
* @param point The point
*/
public static GeoDistanceRangeQueryBuilder geoDistanceRangeQuery(String name) {
return new GeoDistanceRangeQueryBuilder(name);
public static GeoDistanceRangeQueryBuilder geoDistanceRangeQuery(String name, GeoPoint point) {
return new GeoDistanceRangeQueryBuilder(name, point);
}
/**
* A filter to filter based on a specific range from a specific geo location / point.
*
* @param name The location field name.
* @param point The point as geohash
*/
public static GeoDistanceRangeQueryBuilder geoDistanceRangeQuery(String name, String geohash) {
return new GeoDistanceRangeQueryBuilder(name, geohash);
}
/**
* A filter to filter based on a specific range from a specific geo location / point.
*
* @param name The location field name.
* @param lat The points latitude
* @param lon The points longitude
*/
public static GeoDistanceRangeQueryBuilder geoDistanceRangeQuery(String name, double lat, double lon) {
return new GeoDistanceRangeQueryBuilder(name, lat, lon);
}
/**
@ -620,17 +644,6 @@ public abstract class QueryBuilders {
return new GeoBoundingBoxQueryBuilder(name);
}
/**
* A filter based on a bounding box defined by geohash. The field this filter is applied to
* must have <code>{&quot;type&quot;:&quot;geo_point&quot;, &quot;geohash&quot;:true}</code>
* to work.
*
* @param name The geo point field name.
*/
public static GeohashCellQuery.Builder geoHashCellQuery(String name) {
return new GeohashCellQuery.Builder(name);
}
/**
* A filter based on a bounding box defined by geohash. The field this filter is applied to
* must have <code>{&quot;type&quot;:&quot;geo_point&quot;, &quot;geohash&quot;:true}</code>
@ -673,8 +686,8 @@ public abstract class QueryBuilders {
*
* @param name The location field name.
*/
public static GeoPolygonQueryBuilder geoPolygonQuery(String name) {
return new GeoPolygonQueryBuilder(name);
public static GeoPolygonQueryBuilder geoPolygonQuery(String name, List<GeoPoint> points) {
return new GeoPolygonQueryBuilder(name, points);
}
/**

View File

@ -29,6 +29,7 @@ import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.BytesRefs;
@ -42,6 +43,7 @@ import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* A filter for a field based on several terms matching on any of them.
@ -50,7 +52,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
public static final String NAME = "terms";
static final TermsQueryBuilder PROTOTYPE = new TermsQueryBuilder("");
static final TermsQueryBuilder PROTOTYPE = new TermsQueryBuilder("field", "value");
public static final boolean DEFAULT_DISABLE_COORD = false;
@ -60,13 +62,26 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
private String minimumShouldMatch;
@Deprecated
private boolean disableCoord = DEFAULT_DISABLE_COORD;
private TermsLookup termsLookup;
private final TermsLookup termsLookup;
public TermsQueryBuilder(String fieldName, TermsLookup termsLookup) {
this(fieldName, null, null, DEFAULT_DISABLE_COORD, termsLookup);
}
/**
* constructor used internally for serialization of both value / termslookup variants
*/
TermsQueryBuilder(String fieldName, List<Object> values, String minimumShouldMatch, boolean disableCoord, TermsLookup termsLookup) {
this.fieldName = fieldName;
if (values == null && termsLookup == null) {
throw new IllegalArgumentException("No value specified for terms query");
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name cannot be null.");
}
if (values == null && termsLookup == null) {
throw new IllegalArgumentException("No value or termsLookup specified for terms query");
}
if (values != null && termsLookup != null) {
throw new IllegalArgumentException("Both values and termsLookup specified for terms query");
}
this.fieldName = fieldName;
this.values = values;
this.disableCoord = disableCoord;
this.minimumShouldMatch = minimumShouldMatch;
@ -80,7 +95,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
* @param values The terms
*/
public TermsQueryBuilder(String fieldName, String... values) {
this(fieldName, values != null ? Arrays.asList(values) : (Iterable<?>) null);
this(fieldName, values != null ? Arrays.asList(values) : null);
}
/**
@ -100,14 +115,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
* @param values The terms
*/
public TermsQueryBuilder(String fieldName, long... values) {
if (values == null) {
throw new IllegalArgumentException("No value specified for terms query");
}
this.fieldName = fieldName;
this.values = new ArrayList<>(values.length);
for (long longValue : values) {
this.values.add(longValue);
}
this(fieldName, values != null ? Arrays.stream(values).mapToObj(s -> s).collect(Collectors.toList()) : (Iterable<?>) null);
}
/**
@ -117,14 +125,8 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
* @param values The terms
*/
public TermsQueryBuilder(String fieldName, float... values) {
if (values == null) {
throw new IllegalArgumentException("No value specified for terms query");
}
this.fieldName = fieldName;
this.values = new ArrayList<>(values.length);
for (float floatValue : values) {
this.values.add(floatValue);
}
this(fieldName, values != null ? IntStream.range(0, values.length)
.mapToObj(i -> values[i]).collect(Collectors.toList()) : (Iterable<?>) null);
}
/**
@ -147,16 +149,6 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
this(fieldName, values != null ? Arrays.asList(values) : (Iterable<?>) null);
}
/**
* Constructor used for terms query lookup.
*
* @param fieldName The field name
*/
public TermsQueryBuilder(String fieldName) {
this.fieldName = fieldName;
this.values = null;
}
/**
* A filter for a field based on several terms matching on any of them.
*
@ -164,11 +156,15 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
* @param values The terms
*/
public TermsQueryBuilder(String fieldName, Iterable<?> values) {
if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name cannot be null.");
}
if (values == null) {
throw new IllegalArgumentException("No value specified for terms query");
}
this.fieldName = fieldName;
this.values = convertToBytesRefListIfStringList(values);
this.termsLookup = null;
}
public String fieldName() {
@ -207,89 +203,10 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
return this.disableCoord;
}
private boolean isTermsLookupQuery() {
return this.termsLookup != null;
}
public TermsQueryBuilder termsLookup(TermsLookup termsLookup) {
this.termsLookup = termsLookup;
return this;
}
public TermsLookup termsLookup() {
return this.termsLookup;
}
/**
* Sets the index name to lookup the terms from.
*/
public TermsQueryBuilder lookupIndex(String lookupIndex) {
if (lookupIndex == null) {
throw new IllegalArgumentException("Lookup index cannot be set to null");
}
if (this.termsLookup == null) {
this.termsLookup = new TermsLookup();
}
this.termsLookup.index(lookupIndex);
return this;
}
/**
* Sets the type name to lookup the terms from.
*/
public TermsQueryBuilder lookupType(String lookupType) {
if (lookupType == null) {
throw new IllegalArgumentException("Lookup type cannot be set to null");
}
if (this.termsLookup == null) {
this.termsLookup = new TermsLookup();
}
this.termsLookup.type(lookupType);
return this;
}
/**
* Sets the document id to lookup the terms from.
*/
public TermsQueryBuilder lookupId(String lookupId) {
if (lookupId == null) {
throw new IllegalArgumentException("Lookup id cannot be set to null");
}
if (this.termsLookup == null) {
this.termsLookup = new TermsLookup();
}
this.termsLookup.id(lookupId);
return this;
}
/**
* Sets the path name to lookup the terms from.
*/
public TermsQueryBuilder lookupPath(String lookupPath) {
if (lookupPath == null) {
throw new IllegalArgumentException("Lookup path cannot be set to null");
}
if (this.termsLookup == null) {
this.termsLookup = new TermsLookup();
}
this.termsLookup.path(lookupPath);
return this;
}
/**
* Sets the routing to lookup the terms from.
*/
public TermsQueryBuilder lookupRouting(String lookupRouting) {
if (lookupRouting == null) {
throw new IllegalArgumentException("Lookup routing cannot be set to null");
}
if (this.termsLookup == null) {
this.termsLookup = new TermsLookup();
}
this.termsLookup.routing(lookupRouting);
return this;
}
/**
* Same as {@link #convertToBytesRefIfString} but on Iterable.
* @param objs the Iterable of input object
@ -325,7 +242,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
@Override
public void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);
if (isTermsLookupQuery()) {
if (this.termsLookup != null) {
builder.startObject(fieldName);
termsLookup.toXContent(builder, params);
builder.endObject();
@ -350,7 +267,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
List<Object> terms;
if (isTermsLookupQuery()) {
if (this.termsLookup != null) {
if (termsLookup.index() == null) {
termsLookup.index(context.index().name());
}
@ -413,24 +330,6 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
return query;
}
@Override
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (this.fieldName == null) {
validationException = addValidationError("field name cannot be null.", validationException);
}
if (isTermsLookupQuery() && this.values != null) {
validationException = addValidationError("can't have both a terms query and a lookup query.", validationException);
}
if (isTermsLookupQuery()) {
QueryValidationException exception = termsLookup.validate();
if (exception != null) {
validationException = QueryValidationException.addValidationErrors(exception.validationErrors(), validationException);
}
}
return validationException;
}
@SuppressWarnings("unchecked")
@Override
protected TermsQueryBuilder doReadFrom(StreamInput in) throws IOException {
@ -448,8 +347,8 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
@Override
protected void doWriteTo(StreamOutput out) throws IOException {
out.writeString(fieldName);
out.writeBoolean(isTermsLookupQuery());
if (isTermsLookupQuery()) {
out.writeBoolean(termsLookup != null);
if (termsLookup != null) {
termsLookup.writeTo(out);
}
out.writeGenericValue(values);

View File

@ -21,7 +21,6 @@ package org.elasticsearch.index.query;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.indices.cache.query.terms.TermsLookup;
@ -77,7 +76,7 @@ public class TermsQueryParser extends BaseQueryParser {
values = parseValues(parseContext, parser);
} else if (token == XContentParser.Token.START_OBJECT) {
fieldName = currentFieldName;
termsLookup = parseTermsLookup(parseContext, parser);
termsLookup = TermsLookup.parseTermsLookup(parseContext, parser);
} else if (token.isValue()) {
if (parseContext.parseFieldMatcher().match(currentFieldName, EXECUTION_FIELD)) {
// ignore
@ -119,42 +118,6 @@ public class TermsQueryParser extends BaseQueryParser {
return values;
}
private static TermsLookup parseTermsLookup(QueryParseContext parseContext, XContentParser parser) throws IOException {
TermsLookup termsLookup = new TermsLookup();
XContentParser.Token token;
String currentFieldName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token.isValue()) {
if ("index".equals(currentFieldName)) {
termsLookup.index(parser.textOrNull());
} else if ("type".equals(currentFieldName)) {
termsLookup.type(parser.text());
} else if ("id".equals(currentFieldName)) {
termsLookup.id(parser.text());
} else if ("routing".equals(currentFieldName)) {
termsLookup.routing(parser.textOrNull());
} else if ("path".equals(currentFieldName)) {
termsLookup.path(parser.text());
} else {
throw new ParsingException(parseContext, "[terms] query does not support [" + currentFieldName
+ "] within lookup element");
}
}
}
if (termsLookup.type() == null) {
throw new ParsingException(parseContext, "[terms] query lookup element requires specifying the type");
}
if (termsLookup.id() == null) {
throw new ParsingException(parseContext, "[terms] query lookup element requires specifying the id");
}
if (termsLookup.path() == null) {
throw new ParsingException(parseContext, "[terms] query lookup element requires specifying the path");
}
return termsLookup;
}
@Override
public TermsQueryBuilder getBuilderPrototype() {
return TermsQueryBuilder.PROTOTYPE;

View File

@ -19,12 +19,14 @@
package org.elasticsearch.indices.cache.query.terms;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.QueryValidationException;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import java.io.IOException;
import java.util.Objects;
@ -33,18 +35,24 @@ import java.util.Objects;
* Encapsulates the parameters needed to fetch terms.
*/
public class TermsLookup implements Writeable<TermsLookup>, ToXContent {
static final TermsLookup PROTOTYPE = new TermsLookup();
static final TermsLookup PROTOTYPE = new TermsLookup("index", "type", "id", "path");
private String index;
private String type;
private String id;
private String path;
private final String type;
private final String id;
private final String path;
private String routing;
public TermsLookup() {
}
public TermsLookup(String index, String type, String id, String path) {
if (id == null) {
throw new IllegalArgumentException("[terms] query lookup element requires specifying the id.");
}
if (type == null) {
throw new IllegalArgumentException("[terms] query lookup element requires specifying the type.");
}
if (path == null) {
throw new IllegalArgumentException("[terms] query lookup element requires specifying the path.");
}
this.index = index;
this.type = type;
this.id = id;
@ -64,29 +72,14 @@ public class TermsLookup implements Writeable<TermsLookup>, ToXContent {
return type;
}
public TermsLookup type(String type) {
this.type = type;
return this;
}
public String id() {
return id;
}
public TermsLookup id(String id) {
this.id = id;
return this;
}
public String path() {
return path;
}
public TermsLookup path(String path) {
this.path = path;
return this;
}
public String routing() {
return routing;
}
@ -96,6 +89,43 @@ public class TermsLookup implements Writeable<TermsLookup>, ToXContent {
return this;
}
public static TermsLookup parseTermsLookup(QueryParseContext parseContext, XContentParser parser) throws IOException {
String index = null;
String type = null;
String id = null;
String path = null;
String routing = null;
XContentParser.Token token;
String currentFieldName = "";
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token.isValue()) {
switch (currentFieldName) {
case "index":
index = parser.textOrNull();
break;
case "type":
type = parser.text();
break;
case "id":
id = parser.text();
break;
case "routing":
routing = parser.textOrNull();
break;
case "path":
path = parser.text();
break;
default:
throw new ParsingException(parseContext, "[terms] query does not support [" + currentFieldName
+ "] within lookup element");
}
}
}
return new TermsLookup(index, type, id, path).routing(routing);
}
@Override
public String toString() {
return index + "/" + type + "/" + id + "/" + path;
@ -103,11 +133,11 @@ public class TermsLookup implements Writeable<TermsLookup>, ToXContent {
@Override
public TermsLookup readFrom(StreamInput in) throws IOException {
TermsLookup termsLookup = new TermsLookup();
termsLookup.index = in.readOptionalString();
termsLookup.type = in.readString();
termsLookup.id = in.readString();
termsLookup.path = in.readString();
String type = in.readString();
String id = in.readString();
String path = in.readString();
String index = in.readOptionalString();
TermsLookup termsLookup = new TermsLookup(index, type, id, path);
termsLookup.routing = in.readOptionalString();
return termsLookup;
}
@ -118,10 +148,10 @@ public class TermsLookup implements Writeable<TermsLookup>, ToXContent {
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeOptionalString(index);
out.writeString(type);
out.writeString(id);
out.writeString(path);
out.writeOptionalString(index);
out.writeOptionalString(routing);
}
@ -159,22 +189,4 @@ public class TermsLookup implements Writeable<TermsLookup>, ToXContent {
Objects.equals(path, other.path) &&
Objects.equals(routing, other.routing);
}
public QueryValidationException validate() {
QueryValidationException validationException = null;
if (id == null) {
validationException = addValidationError("[terms] query lookup element requires specifying the id.", validationException);
}
if (type == null) {
validationException = addValidationError("[terms] query lookup element requires specifying the type.", validationException);
}
if (path == null) {
validationException = addValidationError("[terms] query lookup element requires specifying the path.", validationException);
}
return validationException;
}
private static QueryValidationException addValidationError(String validationError, QueryValidationException validationException) {
return QueryValidationException.addValidationError("terms_lookup", validationError, validationException);
}
}

View File

@ -66,7 +66,7 @@ public class ExternalValuesMapperIntegrationIT extends ESIntegTestCase {
assertThat(response.getHits().totalHits(), equalTo((long) 1));
response = client().prepareSearch("test-idx")
.setPostFilter(QueryBuilders.geoDistanceRangeQuery("field.point").point(42.0, 51.0).to("1km"))
.setPostFilter(QueryBuilders.geoDistanceRangeQuery("field.point", 42.0, 51.0).to("1km"))
.execute().actionGet();
assertThat(response.getHits().totalHits(), equalTo((long) 1));

View File

@ -480,16 +480,6 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
return createShardContext().parseContext();
}
protected static void assertValidate(QueryBuilder queryBuilder, int totalExpectedErrors) {
QueryValidationException queryValidationException = queryBuilder.validate();
if (totalExpectedErrors > 0) {
assertThat(queryValidationException, notNullValue());
assertThat(queryValidationException.validationErrors().size(), equalTo(totalExpectedErrors));
} else {
assertThat(queryValidationException, nullValue());
}
}
/**
* create a random value for either {@link AbstractQueryTestCase#BOOLEAN_FIELD_NAME}, {@link AbstractQueryTestCase#INT_FIELD_NAME},
* {@link AbstractQueryTestCase#DOUBLE_FIELD_NAME}, {@link AbstractQueryTestCase#STRING_FIELD_NAME} or

View File

@ -89,7 +89,6 @@ public class DisMaxQueryBuilderTests extends AbstractQueryTestCase<DisMaxQueryBu
public void testNoInnerQueries() throws IOException {
DisMaxQueryBuilder disMaxBuilder = new DisMaxQueryBuilder();
assertNull(disMaxBuilder.toQuery(createShardContext()));
assertNull(disMaxBuilder.validate());
}
/**

View File

@ -116,14 +116,14 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
try {
query.distance("1", null);
fail("must not be null");
fail("unit must not be null");
} catch (IllegalArgumentException ex) {
// expected
}
try {
query.distance(1, null);
fail("must not be null");
fail("unit must not be null");
} catch (IllegalArgumentException ex) {
// expected
}

View File

@ -24,7 +24,6 @@ import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery;
import org.joda.time.DateTime;
import org.junit.Test;
import java.io.IOException;
@ -32,22 +31,21 @@ import java.io.IOException;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanceRangeQueryBuilder> {
@Override
protected GeoDistanceRangeQueryBuilder doCreateTestQueryBuilder() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
GeoDistanceRangeQueryBuilder builder;
if (randomBoolean()) {
builder.geohash(randomGeohash(1, 12));
builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, randomGeohash(1, 12));
} else {
double lat = randomDouble() * 180 - 90;
double lon = randomDouble() * 360 - 180;
if (randomBoolean()) {
builder.point(lat, lon);
builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, new GeoPoint(lat, lon));
} else {
builder.point(new GeoPoint(lat, lon));
builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, lat, lon);
}
}
int fromValue = randomInt(1000000);
@ -151,97 +149,63 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc
super.testToQuery();
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testNullFieldName() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(null);
builder.geohash(randomGeohash(1, 20));
builder.from(10);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoDistanceRangeQueryBuilder.NAME + "] fieldName must not be null"));
if (randomBoolean()) {
new GeoDistanceRangeQueryBuilder(null, new GeoPoint());
} else {
new GeoDistanceRangeQueryBuilder("", new GeoPoint());
}
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testNoPoint() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
builder.from(10);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoDistanceRangeQueryBuilder.NAME + "] point must not be null"));
if (randomBoolean()) {
new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, (GeoPoint) null);
} else {
new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, (String) null);
}
}
@Test
public void testNoFromOrTo() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
String geohash = randomGeohash(1, 20);
builder.geohash(geohash);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoDistanceRangeQueryBuilder.NAME
+ "] Must define at least one parameter from [from, to]"));
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testInvalidFrom() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
String geohash = randomGeohash(1, 20);
builder.geohash(geohash);
builder.from(new DateTime());
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoDistanceRangeQueryBuilder.NAME
+ "] from must either be a number or a string. Found [" + DateTime.class.getName() + "]"));
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, new GeoPoint());
if (randomBoolean()) {
builder.from((String) null);
} else {
builder.from((Number) null);
}
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testInvalidTo() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
String geohash = randomGeohash(1, 20);
builder.geohash(geohash);
builder.to(new DateTime());
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoDistanceRangeQueryBuilder.NAME
+ "] to must either be a number or a string. Found [" + DateTime.class.getName() + "]"));
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, new GeoPoint());
if (randomBoolean()) {
builder.to((String) null);
} else {
builder.to((Number) null);
}
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testInvalidOptimizeBBox() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
String geohash = randomGeohash(1, 20);
builder.geohash(geohash);
builder.from(10);
builder.optimizeBbox("foo");
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoDistanceRangeQueryBuilder.NAME
+ "] optimizeBbox must be one of [none, memory, indexed]"));
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, new GeoPoint());
if (randomBoolean()) {
builder.optimizeBbox(null);
} else {
builder.optimizeBbox("foo");
}
}
@Test
public void testMultipleValidationErrors() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME);
double lat = randomDouble() * 360 - 180;
double lon = randomDouble() * 360 - 180;
builder.point(lat, lon);
builder.from(new DateTime());
builder.to(new DateTime());
builder.optimizeBbox("foo");
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(3));
@Test(expected=IllegalArgumentException.class)
public void testInvalidGeoDistance() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, new GeoPoint());
builder.geoDistance(null);
}
@Test(expected=IllegalArgumentException.class)
public void testInvalidDistanceUnit() {
GeoDistanceRangeQueryBuilder builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, new GeoPoint());
builder.unit(null);
}
}

View File

@ -39,33 +39,13 @@ import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
public class GeoPolygonQueryBuilderTests extends AbstractQueryTestCase<GeoPolygonQueryBuilder> {
@Override
protected GeoPolygonQueryBuilder doCreateTestQueryBuilder() {
GeoPolygonQueryBuilder builder;
List<GeoPoint> polygon = randomPolygon(randomIntBetween(4, 50));
if (randomBoolean()) {
builder = new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME, polygon);
} else {
builder = new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME);
for (GeoPoint point : polygon) {
int method = randomInt(2);
switch (method) {
case 0:
builder.addPoint(point);
break;
case 1:
builder.addPoint(point.geohash());
break;
case 2:
builder.addPoint(point.lat(), point.lon());
break;
}
}
}
GeoPolygonQueryBuilder builder = new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME, polygon);
builder.coerce(randomBoolean());
builder.ignoreMalformed(randomBoolean());
return builder;
@ -123,45 +103,34 @@ public class GeoPolygonQueryBuilderTests extends AbstractQueryTestCase<GeoPolygo
@Test(expected = IllegalArgumentException.class)
public void testNullFieldName() {
new GeoPolygonQueryBuilder(null);
new GeoPolygonQueryBuilder(null, randomPolygon(5));
}
@Test
@Test(expected = IllegalArgumentException.class)
public void testEmptyPolygon() {
GeoPolygonQueryBuilder builder = new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoPolygonQueryBuilder.NAME
+ "] no points defined for geo_polygon query"));
if (randomBoolean()) {
new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME, new ArrayList<GeoPoint>());
} else {
new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME, null);
}
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testInvalidClosedPolygon() {
GeoPolygonQueryBuilder builder = new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME);
builder.addPoint(new GeoPoint(0, 90));
builder.addPoint(new GeoPoint(90, 90));
builder.addPoint(new GeoPoint(0, 90));
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoPolygonQueryBuilder.NAME
+ "] too few points defined for geo_polygon query"));
List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint(0, 90));
points.add(new GeoPoint(90, 90));
points.add(new GeoPoint(0, 90));
new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME, points);
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testInvalidOpenPolygon() {
GeoPolygonQueryBuilder builder = new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME);
builder.addPoint(new GeoPoint(0, 90));
builder.addPoint(new GeoPoint(90, 90));
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoPolygonQueryBuilder.NAME
+ "] too few points defined for geo_polygon query"));
List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint(0, 90));
points.add(new GeoPoint(90, 90));
new GeoPolygonQueryBuilder(GEO_POINT_FIELD_NAME, points);
}
public void testDeprecatedXContent() throws IOException {

View File

@ -149,13 +149,9 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
public void testNoShape() throws IOException {
try {
GeoShapeQueryBuilder builder = new GeoShapeQueryBuilder(GEO_SHAPE_FIELD_NAME, (ShapeBuilder) null);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoShapeQueryBuilder.NAME + "] No Shape defined"));
} catch (IOException e) {
throw new RuntimeException(e);
fail("exception expected");
} catch (IllegalArgumentException e) {
// expected
}
}
@ -170,18 +166,14 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
}
@Test
public void testNoRelation() {
public void testNoRelation() throws IOException {
ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(getRandom(), null);
try {
GeoShapeQueryBuilder builder = new GeoShapeQueryBuilder(GEO_SHAPE_FIELD_NAME, shape);
builder.relation(null);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeoShapeQueryBuilder.NAME + "] No Shape Relation defined"));
} catch (IOException e) {
throw new RuntimeException(e);
fail("relation cannot be null");
} catch (IllegalArgumentException e) {
// expected
}
}

View File

@ -23,6 +23,7 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.queries.TermsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import org.elasticsearch.index.query.GeohashCellQuery.Builder;
@ -32,14 +33,12 @@ import java.io.IOException;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
public class GeohashCellQueryBuilderTests extends AbstractQueryTestCase<Builder> {
@Override
protected Builder doCreateTestQueryBuilder() {
GeohashCellQuery.Builder builder = new Builder(GEO_POINT_FIELD_NAME);
builder.geohash(randomGeohash(1, 12));
GeohashCellQuery.Builder builder = new Builder(GEO_POINT_FIELD_NAME, randomGeohash(1, 12));
if (randomBoolean()) {
builder.neighbors(randomBoolean());
}
@ -82,38 +81,28 @@ public class GeohashCellQueryBuilderTests extends AbstractQueryTestCase<Builder>
super.testToQuery();
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testNullField() {
GeohashCellQuery.Builder builder = new Builder(null);
builder.geohash(randomGeohash(1, 12));
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeohashCellQuery.NAME + "] fieldName must not be null"));
if (randomBoolean()) {
new Builder(null, new GeoPoint());
} else {
new Builder("", new GeoPoint());
}
}
@Test
public void testNullGeohash() {
GeohashCellQuery.Builder builder = new Builder(GEO_POINT_FIELD_NAME);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeohashCellQuery.NAME + "] geohash or point must be defined"));
@Test(expected=IllegalArgumentException.class)
public void testNullGeoPoint() {
if (randomBoolean()) {
new Builder(GEO_POINT_FIELD_NAME, (GeoPoint) null);
} else {
new Builder(GEO_POINT_FIELD_NAME, "");
}
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testInvalidPrecision() {
GeohashCellQuery.Builder builder = new Builder(GEO_POINT_FIELD_NAME);
builder.geohash(randomGeohash(1, 12));
GeohashCellQuery.Builder builder = new Builder(GEO_POINT_FIELD_NAME, new GeoPoint());
builder.precision(-1);
QueryValidationException exception = builder.validate();
assertThat(exception, notNullValue());
assertThat(exception.validationErrors(), notNullValue());
assertThat(exception.validationErrors().size(), equalTo(1));
assertThat(exception.validationErrors().get(0), equalTo("[" + GeohashCellQuery.NAME + "] precision must be greater than 0. Found ["
+ -1 + "]"));
}
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
@ -31,7 +32,6 @@ import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.get.GetResult;
@ -78,19 +78,14 @@ public class TermsQueryBuilderTests extends AbstractQueryTestCase<TermsQueryBuil
query = new TermsQueryBuilder(fieldName, values);
} else {
// right now the mock service returns us a list of strings
query = new TermsQueryBuilder(randomBoolean() ? randomAsciiOfLengthBetween(1,10) : STRING_FIELD_NAME);
query.termsLookup(randomTermsLookup());
query = new TermsQueryBuilder(randomBoolean() ? randomAsciiOfLengthBetween(1,10) : STRING_FIELD_NAME, randomTermsLookup());
}
return query;
}
private TermsLookup randomTermsLookup() {
return new TermsLookup(
randomBoolean() ? randomAsciiOfLength(10) : null,
randomAsciiOfLength(10),
randomAsciiOfLength(10),
termsPath
).routing(randomBoolean() ? randomAsciiOfLength(10) : null);
return new TermsLookup(randomBoolean() ? randomAsciiOfLength(10) : null, randomAsciiOfLength(10), randomAsciiOfLength(10),
termsPath).routing(randomBoolean() ? randomAsciiOfLength(10) : null);
}
@Override
@ -131,38 +126,18 @@ public class TermsQueryBuilderTests extends AbstractQueryTestCase<TermsQueryBuil
assertEquals(expectedTerms + " vs. " + booleanTerms, expectedTerms, booleanTerms);
}
@Test
public void testValidate() {
TermsQueryBuilder termsQueryBuilder = new TermsQueryBuilder(null, "term");
assertThat(termsQueryBuilder.validate().validationErrors().size(), is(1));
termsQueryBuilder = new TermsQueryBuilder("field", "term").termsLookup(randomTermsLookup());
assertThat(termsQueryBuilder.validate().validationErrors().size(), is(1));
termsQueryBuilder = new TermsQueryBuilder(null, "term").termsLookup(randomTermsLookup());
assertThat(termsQueryBuilder.validate().validationErrors().size(), is(2));
termsQueryBuilder = new TermsQueryBuilder("field", "term");
assertNull(termsQueryBuilder.validate());
@Test(expected=IllegalArgumentException.class)
public void testEmtpyFieldName() {
if (randomBoolean()) {
new TermsQueryBuilder(null, "term");
} else {
new TermsQueryBuilder("", "term");
}
}
@Test
public void testValidateLookupQuery() {
TermsQueryBuilder termsQuery = new TermsQueryBuilder("field").termsLookup(new TermsLookup());
int totalExpectedErrors = 3;
if (randomBoolean()) {
termsQuery.lookupId("id");
totalExpectedErrors--;
}
if (randomBoolean()) {
termsQuery.lookupType("type");
totalExpectedErrors--;
}
if (randomBoolean()) {
termsQuery.lookupPath("path");
totalExpectedErrors--;
}
assertValidate(termsQuery, totalExpectedErrors);
@Test(expected=IllegalArgumentException.class)
public void testEmtpyTermsLookup() {
new TermsQueryBuilder("field", (TermsLookup) null);
}
@Test
@ -197,7 +172,7 @@ public class TermsQueryBuilderTests extends AbstractQueryTestCase<TermsQueryBuil
}
}
@Test
@Test(expected=IllegalArgumentException.class)
public void testBothValuesAndLookupSet() throws IOException {
String query = "{\n" +
" \"terms\": {\n" +
@ -214,7 +189,6 @@ public class TermsQueryBuilderTests extends AbstractQueryTestCase<TermsQueryBuil
" }\n" +
"}";
QueryBuilder termsQueryBuilder = parseQuery(query);
assertThat(termsQueryBuilder.validate().validationErrors().size(), is(1));
}
public void testDeprecatedXContent() throws IOException {

View File

@ -0,0 +1,85 @@
/*
* 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.indices.cache.query.terms;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.test.ESTestCase;
import org.junit.Test;
import java.io.IOException;
public class TermsLookupTests extends ESTestCase {
@Test
public void testTermsLookup() {
String index = randomAsciiOfLengthBetween(1, 10);
String type = randomAsciiOfLengthBetween(1, 10);
String id = randomAsciiOfLengthBetween(1, 10);
String path = randomAsciiOfLengthBetween(1, 10);
String routing = randomAsciiOfLengthBetween(1, 10);
TermsLookup termsLookup = new TermsLookup(index, type, id, path);
termsLookup.routing(routing);
assertEquals(index, termsLookup.index());
assertEquals(type, termsLookup.type());
assertEquals(id, termsLookup.id());
assertEquals(path, termsLookup.path());
assertEquals(routing, termsLookup.routing());
}
@Test(expected=IllegalArgumentException.class)
public void testIllegalArguments() {
String type = randomAsciiOfLength(5);
String id = randomAsciiOfLength(5);
String path = randomAsciiOfLength(5);
switch (randomIntBetween(0, 2)) {
case 0:
type = null; break;
case 1:
id = null; break;
case 2:
path = null; break;
}
new TermsLookup(null, type, id, path);
}
@Test
public void testSerialization() throws IOException {
TermsLookup termsLookup = randomTermsLookup();
try (BytesStreamOutput output = new BytesStreamOutput()) {
termsLookup.writeTo(output);
try (StreamInput in = StreamInput.wrap(output.bytes())) {
TermsLookup deserializedLookup = TermsLookup.readTermsLookupFrom(in);
assertEquals(deserializedLookup, termsLookup);
assertEquals(deserializedLookup.hashCode(), termsLookup.hashCode());
assertNotSame(deserializedLookup, termsLookup);
}
}
}
public static TermsLookup randomTermsLookup() {
return new TermsLookup(
randomBoolean() ? randomAsciiOfLength(10) : null,
randomAsciiOfLength(10),
randomAsciiOfLength(10),
randomAsciiOfLength(10).replace('.', '_')
).routing(randomBoolean() ? randomAsciiOfLength(10) : null);
}
}

View File

@ -171,7 +171,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
}
searchResponse = client().prepareSearch() // from NY
.setQuery(geoDistanceRangeQuery("location").from("1.0km").to("2.0km").point(40.7143528, -74.0059731))
.setQuery(geoDistanceRangeQuery("location", 40.7143528, -74.0059731).from("1.0km").to("2.0km"))
.execute().actionGet();
assertHitCount(searchResponse, 2);
assertThat(searchResponse.getHits().hits().length, equalTo(2));
@ -179,7 +179,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
assertThat(hit.id(), anyOf(equalTo("4"), equalTo("5")));
}
searchResponse = client().prepareSearch() // from NY
.setQuery(geoDistanceRangeQuery("location").from("1.0km").to("2.0km").point(40.7143528, -74.0059731).optimizeBbox("indexed"))
.setQuery(geoDistanceRangeQuery("location", 40.7143528, -74.0059731).from("1.0km").to("2.0km").optimizeBbox("indexed"))
.execute().actionGet();
assertHitCount(searchResponse, 2);
assertThat(searchResponse.getHits().hits().length, equalTo(2));
@ -188,13 +188,13 @@ public class GeoDistanceIT extends ESIntegTestCase {
}
searchResponse = client().prepareSearch() // from NY
.setQuery(geoDistanceRangeQuery("location").to("2.0km").point(40.7143528, -74.0059731))
.setQuery(geoDistanceRangeQuery("location", 40.7143528, -74.0059731).to("2.0km"))
.execute().actionGet();
assertHitCount(searchResponse, 4);
assertThat(searchResponse.getHits().hits().length, equalTo(4));
searchResponse = client().prepareSearch() // from NY
.setQuery(geoDistanceRangeQuery("location").from("2.0km").point(40.7143528, -74.0059731))
.setQuery(geoDistanceRangeQuery("location", 40.7143528, -74.0059731).from("2.0km"))
.execute().actionGet();
assertHitCount(searchResponse, 3);
assertThat(searchResponse.getHits().hits().length, equalTo(3));

View File

@ -20,12 +20,16 @@
package org.elasticsearch.search.geo;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.test.ESIntegTestCase;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.geoPolygonQuery;
@ -49,7 +53,7 @@ public class GeoPolygonIT extends ESIntegTestCase {
indexRandom(true, client().prepareIndex("test", "type1", "1").setSource(jsonBuilder().startObject()
.field("name", "New York")
.startObject("location").field("lat", 40.714).field("lon", -74.006).endObject()
.endObject()),
.endObject()),
// to NY: 5.286 km
client().prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject()
.field("name", "Times Square")
@ -85,14 +89,14 @@ public class GeoPolygonIT extends ESIntegTestCase {
@Test
public void simplePolygonTest() throws Exception {
List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint(40.7, -74.0));
points.add(new GeoPoint(40.7, -74.1));
points.add(new GeoPoint(40.8, -74.1));
points.add(new GeoPoint(40.8, -74.0));
points.add(new GeoPoint(40.7, -74.0));
SearchResponse searchResponse = client().prepareSearch("test") // from NY
.setQuery(boolQuery().must(geoPolygonQuery("location")
.addPoint(40.7, -74.0)
.addPoint(40.7, -74.1)
.addPoint(40.8, -74.1)
.addPoint(40.8, -74.0)
.addPoint(40.7, -74.0)))
.setQuery(boolQuery().must(geoPolygonQuery("location", points)))
.execute().actionGet();
assertHitCount(searchResponse, 4);
assertThat(searchResponse.getHits().hits().length, equalTo(4));
@ -103,13 +107,13 @@ public class GeoPolygonIT extends ESIntegTestCase {
@Test
public void simpleUnclosedPolygon() throws Exception {
List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint(40.7, -74.0));
points.add(new GeoPoint(40.7, -74.1));
points.add(new GeoPoint(40.8, -74.1));
points.add(new GeoPoint(40.8, -74.0));
SearchResponse searchResponse = client().prepareSearch("test") // from NY
.setQuery(boolQuery().must(geoPolygonQuery("location")
.addPoint(40.7, -74.0)
.addPoint(40.7, -74.1)
.addPoint(40.8, -74.1)
.addPoint(40.8, -74.0)))
.execute().actionGet();
.setQuery(boolQuery().must(geoPolygonQuery("location", points))).execute().actionGet();
assertHitCount(searchResponse, 4);
assertThat(searchResponse.getHits().hits().length, equalTo(4));
for (SearchHit hit : searchResponse.getHits()) {

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.search.MatchQuery.Type;
import org.elasticsearch.index.search.MatchQuery;
import org.elasticsearch.indices.cache.query.terms.TermsLookup;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchHit;
@ -1231,63 +1232,54 @@ public class SearchQueryIT extends ESIntegTestCase {
client().prepareIndex("test", "type", "4").setSource("term", "4") );
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup").lookupType("type").lookupId("1").lookupPath("terms")
).get();
.setQuery(termsLookupQuery("term" , new TermsLookup("lookup", "type", "1", "terms"))).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "1", "3");
// same as above, just on the _id...
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("_id").lookupIndex("lookup").lookupType("type").lookupId("1").lookupPath("terms")
.setQuery(termsLookupQuery("_id", new TermsLookup("lookup", "type", "1", "terms"))
).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "1", "3");
// another search with same parameters...
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup").lookupType("type").lookupId("1").lookupPath("terms")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup", "type", "1", "terms"))).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "1", "3");
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup").lookupType("type").lookupId("2").lookupPath("terms")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup", "type", "2", "terms"))).get();
assertHitCount(searchResponse, 1l);
assertFirstHit(searchResponse, hasId("2"));
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup").lookupType("type").lookupId("3").lookupPath("terms")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup", "type", "3", "terms"))).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "2", "4");
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup").lookupType("type").lookupId("4").lookupPath("terms")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup", "type", "4", "terms"))).get();
assertHitCount(searchResponse, 0l);
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup2").lookupType("type").lookupId("1").lookupPath("arr.term")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup2", "type", "1", "arr.term"))).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "1", "3");
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup2").lookupType("type").lookupId("2").lookupPath("arr.term")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup2", "type", "2", "arr.term"))).get();
assertHitCount(searchResponse, 1l);
assertFirstHit(searchResponse, hasId("2"));
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("term").lookupIndex("lookup2").lookupType("type").lookupId("3").lookupPath("arr.term")
).get();
.setQuery(termsLookupQuery("term", new TermsLookup("lookup2", "type", "3", "arr.term"))).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "2", "4");
searchResponse = client().prepareSearch("test")
.setQuery(termsLookupQuery("not_exists").lookupIndex("lookup2").lookupType("type").lookupId("3").lookupPath("arr.term")
).get();
.setQuery(termsLookupQuery("not_exists", new TermsLookup("lookup2", "type", "3", "arr.term"))).get();
assertHitCount(searchResponse, 0l);
}

View File

@ -55,10 +55,10 @@ import org.elasticsearch.index.query.MoreLikeThisQueryBuilder;
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.indices.cache.query.terms.TermsLookup;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.Template;
import org.elasticsearch.script.groovy.GroovyScriptEngineService;
@ -161,7 +161,7 @@ public class ContextAndHeaderTransportIT extends ESIntegTestCase {
.setSource(jsonBuilder().startObject().field("username", "foo").endObject()).get();
transportClient().admin().indices().prepareRefresh(queryIndex, lookupIndex).get();
TermsQueryBuilder termsLookupFilterBuilder = QueryBuilders.termsLookupQuery("username").lookupIndex(lookupIndex).lookupType("type").lookupId("1").lookupPath("followers");
TermsQueryBuilder termsLookupFilterBuilder = QueryBuilders.termsLookupQuery("username", new TermsLookup(lookupIndex, "type", "1", "followers"));
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.matchAllQuery()).must(termsLookupFilterBuilder);
SearchResponse searchResponse = transportClient()

View File

@ -111,9 +111,22 @@ The deprecated `docs(Item... docs)`, `ignoreLike(Item... docs)`,
Removing individual setters for lon() and lat() values, both values should be set together
using point(lon, lat).
==== GeoDistanceRangeQueryBuilder
Removing setters for to(Object ...) and from(Object ...) in favour of the only two allowed input
arguments (String, Number). Removing setter for center point (point(), geohash()) because parameter
is mandatory and should already be set in constructor.
Also removing setters for lt(), lte(), gt(), gte() since they can all be replaced by equivallent
calls to to/from() and inludeLower()/includeUpper().
==== GeoPolygonQueryBuilder
Require shell of polygon already to be specified in constructor instead of adding it pointwise.
This enables validation, but makes it necessary to remove the addPoint() methods.
==== MultiMatchQueryBuilder
Moving MultiMatchQueryBuilder.ZeroTermsQuery enum to MatchQuery..ZeroTermsQuery.
Moving MultiMatchQueryBuilder.ZeroTermsQuery enum to MatchQuery.ZeroTermsQuery.
Also reusing new Operator enum.
Removed ability to pass in boost value using `field(String field)` method in form e.g. `field^2`.
@ -124,3 +137,11 @@ Use the `field(String, float)` method instead.
The two individual setters for existence() and nullValue() were removed in favour of
optional constructor settings in order to better capture and validate their interdependent
settings at construction time.
==== TermsQueryBuilder
Remove the setter for `termsLookup()`, making it only possible to either use a TermsLookUp object or
individual values at constrution time. Also moving individual settings for the TermsLookUp (lookupIndex,
lookupType, lookupId, lookupPath) to the separate TermsLookUp class, using construtor only and moving
checks for validation there.