Merge pull request #11137 from jpountz/enhancement/geo_queries

Query DSL: Make geo filters queries.
This commit is contained in:
Adrien Grand 2015-05-13 17:27:15 +02:00
commit b64e54c424
13 changed files with 326 additions and 769 deletions

View File

@ -1,216 +0,0 @@
/*
* 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.common.lucene.docset;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BitSet;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.InPlaceMergeSorter;
import org.apache.lucene.util.RamUsageEstimator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
*
*/
public class AndDocIdSet extends DocIdSet {
private final DocIdSet[] sets;
public AndDocIdSet(DocIdSet[] sets) {
this.sets = sets;
}
@Override
public boolean isCacheable() {
for (DocIdSet set : sets) {
if (!set.isCacheable()) {
return false;
}
}
return true;
}
@Override
public long ramBytesUsed() {
long ramBytesUsed = RamUsageEstimator.NUM_BYTES_OBJECT_REF + RamUsageEstimator.NUM_BYTES_ARRAY_HEADER;
for (DocIdSet set : sets) {
ramBytesUsed += RamUsageEstimator.NUM_BYTES_OBJECT_REF + set.ramBytesUsed();
}
return ramBytesUsed;
}
@Override
public Bits bits() throws IOException {
Bits[] bits = new Bits[sets.length];
for (int i = 0; i < sets.length; i++) {
bits[i] = sets[i].bits();
if (bits[i] == null) {
return null;
}
}
return new AndBits(bits);
}
@Override
public DocIdSetIterator iterator() throws IOException {
// we try and be smart here, if we can iterate through docsets quickly, prefer to iterate
// over them as much as possible, before actually going to "bits" based ones to check
List<DocIdSetIterator> iterators = new ArrayList<>(sets.length);
List<Bits> bits = new ArrayList<>(sets.length);
for (DocIdSet set : sets) {
if (DocIdSets.isEmpty(set)) {
return DocIdSetIterator.empty();
}
DocIdSetIterator it = set.iterator();
if (it == null) {
return DocIdSetIterator.empty();
}
Bits bit = set.bits();
if (bit != null && bit instanceof BitSet == false) {
bits.add(bit);
} else {
iterators.add(it);
}
}
if (bits.isEmpty()) {
return IteratorBasedIterator.newDocIdSetIterator(iterators);
}
if (iterators.isEmpty()) {
return new BitsDocIdSetIterator(new AndBits(bits.toArray(new Bits[bits.size()])));
}
// combination of both..., first iterating over the "fast" ones, and then checking on the more
// expensive ones
return new BitsDocIdSetIterator.FilteredIterator(
IteratorBasedIterator.newDocIdSetIterator(iterators),
new AndBits(bits.toArray(new Bits[bits.size()]))
);
}
/** A conjunction between several {@link Bits} instances with short-circuit logic. */
public static class AndBits implements Bits {
private final Bits[] bits;
public AndBits(Bits[] bits) {
this.bits = bits;
}
@Override
public boolean get(int index) {
for (Bits bit : bits) {
if (!bit.get(index)) {
return false;
}
}
return true;
}
@Override
public int length() {
return bits[0].length();
}
}
static class IteratorBasedIterator extends DocIdSetIterator {
private int doc = -1;
private final DocIdSetIterator lead;
private final DocIdSetIterator[] otherIterators;
public static DocIdSetIterator newDocIdSetIterator(Collection<DocIdSetIterator> iterators) throws IOException {
if (iterators.isEmpty()) {
return DocIdSetIterator.empty();
}
if (iterators.size() == 1) {
// shortcut if there is only one valid iterator.
return iterators.iterator().next();
}
return new IteratorBasedIterator(iterators);
}
private IteratorBasedIterator(Collection<DocIdSetIterator> iterators) throws IOException {
final DocIdSetIterator[] sortedIterators = iterators.toArray(new DocIdSetIterator[iterators.size()]);
new InPlaceMergeSorter() {
@Override
protected int compare(int i, int j) {
return Long.compare(sortedIterators[i].cost(), sortedIterators[j].cost());
}
@Override
protected void swap(int i, int j) {
ArrayUtil.swap(sortedIterators, i, j);
}
}.sort(0, sortedIterators.length);
lead = sortedIterators[0];
this.otherIterators = Arrays.copyOfRange(sortedIterators, 1, sortedIterators.length);
}
@Override
public final int docID() {
return doc;
}
@Override
public final int nextDoc() throws IOException {
doc = lead.nextDoc();
return doNext();
}
@Override
public final int advance(int target) throws IOException {
doc = lead.advance(target);
return doNext();
}
private int doNext() throws IOException {
main:
while (true) {
for (DocIdSetIterator otherIterator : otherIterators) {
// the following assert is the invariant of the loop
assert otherIterator.docID() <= doc;
// the current doc might already be equal to doc if it broke the loop
// at the previous iteration
if (otherIterator.docID() < doc) {
final int advanced = otherIterator.advance(doc);
if (advanced > doc) {
doc = lead.advance(advanced);
continue main;
}
}
}
return doc;
}
}
@Override
public long cost() {
return lead.cost();
}
}
}

View File

@ -29,8 +29,8 @@ import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import org.elasticsearch.index.search.geo.InMemoryGeoBoundingBoxFilter;
import org.elasticsearch.index.search.geo.IndexedGeoBoundingBoxFilter;
import org.elasticsearch.index.search.geo.InMemoryGeoBoundingBoxQuery;
import org.elasticsearch.index.search.geo.IndexedGeoBoundingBoxQuery;
import java.io.IOException;
@ -173,10 +173,10 @@ public class GeoBoundingBoxQueryParser implements QueryParser {
Query filter;
if ("indexed".equals(type)) {
filter = IndexedGeoBoundingBoxFilter.create(topLeft, bottomRight, geoMapper);
filter = IndexedGeoBoundingBoxQuery.create(topLeft, bottomRight, geoMapper);
} else if ("memory".equals(type)) {
IndexGeoPointFieldData indexFieldData = parseContext.getForField(mapper);
filter = new InMemoryGeoBoundingBoxFilter(topLeft, bottomRight, indexFieldData);
filter = new InMemoryGeoBoundingBoxQuery(topLeft, bottomRight, indexFieldData);
} else {
throw new QueryParsingException(parseContext, "geo bounding box type [" + type
+ "] not supported, either 'indexed' or 'memory' are allowed");

View File

@ -31,7 +31,7 @@ import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import org.elasticsearch.index.search.geo.GeoDistanceFilter;
import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery;
import java.io.IOException;
@ -160,7 +160,7 @@ public class GeoDistanceQueryParser implements QueryParser {
IndexGeoPointFieldData indexFieldData = parseContext.getForField(mapper);
Query query = new GeoDistanceFilter(point.lat(), point.lon(), distance, geoDistance, indexFieldData, geoMapper, optimizeBbox);
Query query = new GeoDistanceRangeQuery(point, null, distance, true, false, geoDistance, geoMapper, indexFieldData, optimizeBbox);
if (queryName != null) {
parseContext.addNamedQuery(queryName, query);
}

View File

@ -31,7 +31,7 @@ import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import org.elasticsearch.index.search.geo.GeoDistanceRangeFilter;
import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery;
import java.io.IOException;
@ -199,7 +199,7 @@ public class GeoDistanceRangeQueryParser implements QueryParser {
GeoPointFieldMapper geoMapper = ((GeoPointFieldMapper) mapper);
IndexGeoPointFieldData indexFieldData = parseContext.getForField(mapper);
Query query = new GeoDistanceRangeFilter(point, from, to, includeLower, includeUpper, geoDistance, geoMapper, indexFieldData, optimizeBbox);
Query query = new GeoDistanceRangeQuery(point, from, to, includeLower, includeUpper, geoDistance, geoMapper, indexFieldData, optimizeBbox);
if (queryName != null) {
parseContext.addNamedQuery(queryName, query);
}

View File

@ -31,7 +31,7 @@ import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import org.elasticsearch.index.search.geo.GeoPolygonFilter;
import org.elasticsearch.index.search.geo.GeoPolygonQuery;
import java.io.IOException;
import java.util.List;
@ -147,7 +147,7 @@ public class GeoPolygonQueryParser implements QueryParser {
}
IndexGeoPointFieldData indexFieldData = parseContext.getForField(mapper);
Query query = new GeoPolygonFilter(indexFieldData, shell.toArray(new GeoPoint[shell.size()]));
Query query = new GeoPolygonQuery(indexFieldData, shell.toArray(new GeoPoint[shell.size()]));
if (queryName != null) {
parseContext.addNamedQuery(queryName, query);
}

View File

@ -1,191 +0,0 @@
/*
* 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.index.search.geo;
import java.io.IOException;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocValuesDocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.Bits;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.lucene.docset.AndDocIdSet;
import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
/**
*/
public class GeoDistanceFilter extends Filter {
private final double lat;
private final double lon;
private final double distance; // in miles
private final GeoDistance geoDistance;
private final IndexGeoPointFieldData indexFieldData;
private final GeoDistance.FixedSourceDistance fixedSourceDistance;
private final GeoDistance.DistanceBoundingCheck distanceBoundingCheck;
private final Filter boundingBoxFilter;
public GeoDistanceFilter(double lat, double lon, double distance, GeoDistance geoDistance, IndexGeoPointFieldData indexFieldData, GeoPointFieldMapper mapper,
String optimizeBbox) {
this.lat = lat;
this.lon = lon;
this.distance = distance;
this.geoDistance = geoDistance;
this.indexFieldData = indexFieldData;
this.fixedSourceDistance = geoDistance.fixedSourceDistance(lat, lon, DistanceUnit.DEFAULT);
GeoDistance.DistanceBoundingCheck distanceBoundingCheck = null;
if (optimizeBbox != null && !"none".equals(optimizeBbox)) {
distanceBoundingCheck = GeoDistance.distanceBoundingCheck(lat, lon, distance, DistanceUnit.DEFAULT);
if ("memory".equals(optimizeBbox)) {
boundingBoxFilter = null;
} else if ("indexed".equals(optimizeBbox)) {
boundingBoxFilter = IndexedGeoBoundingBoxFilter.create(distanceBoundingCheck.topLeft(), distanceBoundingCheck.bottomRight(), mapper);
distanceBoundingCheck = GeoDistance.ALWAYS_INSTANCE; // fine, we do the bounding box check using the filter
} else {
throw new IllegalArgumentException("type [" + optimizeBbox + "] for bounding box optimization not supported");
}
} else {
distanceBoundingCheck = GeoDistance.ALWAYS_INSTANCE;
boundingBoxFilter = null;
}
this.distanceBoundingCheck = distanceBoundingCheck;
}
public double lat() {
return lat;
}
public double lon() {
return lon;
}
public double distance() {
return distance;
}
public GeoDistance geoDistance() {
return geoDistance;
}
public String fieldName() {
return indexFieldData.getFieldNames().indexName();
}
@Override
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptedDocs) throws IOException {
DocIdSet boundingBoxDocSet = null;
if (boundingBoxFilter != null) {
boundingBoxDocSet = boundingBoxFilter.getDocIdSet(context, null);
if (DocIdSets.isEmpty(boundingBoxDocSet)) {
return null;
}
}
final MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
GeoDistanceDocSet distDocSet = new GeoDistanceDocSet(context.reader().maxDoc(), acceptedDocs, values, fixedSourceDistance, distanceBoundingCheck, distance);
if (boundingBoxDocSet == null) {
return distDocSet;
} else {
return new AndDocIdSet(new DocIdSet[]{boundingBoxDocSet, distDocSet});
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (super.equals(o) == false) return false;
GeoDistanceFilter filter = (GeoDistanceFilter) o;
if (Double.compare(filter.distance, distance) != 0) return false;
if (Double.compare(filter.lat, lat) != 0) return false;
if (Double.compare(filter.lon, lon) != 0) return false;
if (!indexFieldData.getFieldNames().indexName().equals(filter.indexFieldData.getFieldNames().indexName()))
return false;
if (geoDistance != filter.geoDistance) return false;
return true;
}
@Override
public String toString(String field) {
return "GeoDistanceFilter(" + indexFieldData.getFieldNames().indexName() + ", " + geoDistance + ", " + distance + ", " + lat + ", " + lon + ")";
}
@Override
public int hashCode() {
int result = super.hashCode();
long temp;
temp = lat != +0.0d ? Double.doubleToLongBits(lat) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = lon != +0.0d ? Double.doubleToLongBits(lon) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = distance != +0.0d ? Double.doubleToLongBits(distance) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (geoDistance != null ? geoDistance.hashCode() : 0);
result = 31 * result + indexFieldData.getFieldNames().indexName().hashCode();
return result;
}
public static class GeoDistanceDocSet extends DocValuesDocIdSet {
private final double distance; // in miles
private final MultiGeoPointValues values;
private final GeoDistance.FixedSourceDistance fixedSourceDistance;
private final GeoDistance.DistanceBoundingCheck distanceBoundingCheck;
public GeoDistanceDocSet(int maxDoc, @Nullable Bits acceptDocs, MultiGeoPointValues values, GeoDistance.FixedSourceDistance fixedSourceDistance, GeoDistance.DistanceBoundingCheck distanceBoundingCheck,
double distance) {
super(maxDoc, acceptDocs);
this.values = values;
this.fixedSourceDistance = fixedSourceDistance;
this.distanceBoundingCheck = distanceBoundingCheck;
this.distance = distance;
}
@Override
protected boolean matchDoc(int doc) {
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
GeoPoint point = values.valueAt(i);
if (distanceBoundingCheck.isWithin(point.lat(), point.lon())) {
double d = fixedSourceDistance.calculate(point.lat(), point.lon());
if (d < distance) {
return true;
}
}
}
return false;
}
}
}

View File

@ -19,28 +19,30 @@
package org.elasticsearch.index.search.geo;
import java.io.IOException;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocValuesDocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.ConstantScoreScorer;
import org.apache.lucene.search.ConstantScoreWeight;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.TwoPhaseIterator;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.NumericUtils;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.lucene.docset.AndDocIdSet;
import org.elasticsearch.common.lucene.docset.DocIdSets;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
import java.io.IOException;
/**
*
*/
public class GeoDistanceRangeFilter extends Filter {
public class GeoDistanceRangeQuery extends Query {
private final double lat;
private final double lon;
@ -51,11 +53,11 @@ public class GeoDistanceRangeFilter extends Filter {
private final GeoDistance geoDistance;
private final GeoDistance.FixedSourceDistance fixedSourceDistance;
private GeoDistance.DistanceBoundingCheck distanceBoundingCheck;
private final Filter boundingBoxFilter;
private final Query boundingBoxFilter;
private final IndexGeoPointFieldData indexFieldData;
public GeoDistanceRangeFilter(GeoPoint point, Double lowerVal, Double upperVal, boolean includeLower, boolean includeUpper, GeoDistance geoDistance, GeoPointFieldMapper mapper, IndexGeoPointFieldData indexFieldData,
public GeoDistanceRangeQuery(GeoPoint point, Double lowerVal, Double upperVal, boolean includeLower, boolean includeUpper, GeoDistance geoDistance, GeoPointFieldMapper mapper, IndexGeoPointFieldData indexFieldData,
String optimizeBbox) {
this.lat = point.lat();
this.lon = point.lon();
@ -88,7 +90,7 @@ public class GeoDistanceRangeFilter extends Filter {
if ("memory".equals(optimizeBbox)) {
boundingBoxFilter = null;
} else if ("indexed".equals(optimizeBbox)) {
boundingBoxFilter = IndexedGeoBoundingBoxFilter.create(distanceBoundingCheck.topLeft(), distanceBoundingCheck.bottomRight(), mapper);
boundingBoxFilter = IndexedGeoBoundingBoxQuery.create(distanceBoundingCheck.topLeft(), distanceBoundingCheck.bottomRight(), mapper);
distanceBoundingCheck = GeoDistance.ALWAYS_INSTANCE; // fine, we do the bounding box check using the filter
} else {
throw new IllegalArgumentException("type [" + optimizeBbox + "] for bounding box optimization not supported");
@ -111,22 +113,64 @@ public class GeoDistanceRangeFilter extends Filter {
return geoDistance;
}
public double minInclusiveDistance() {
return inclusiveLowerPoint;
}
public double maxInclusiveDistance() {
return inclusiveUpperPoint;
}
public String fieldName() {
return indexFieldData.getFieldNames().indexName();
}
@Override
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptedDocs) throws IOException {
DocIdSet boundingBoxDocSet = null;
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
final Weight boundingBoxWeight;
if (boundingBoxFilter != null) {
boundingBoxDocSet = boundingBoxFilter.getDocIdSet(context, null);
if (DocIdSets.isEmpty(boundingBoxDocSet)) {
return null;
}
}
MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
GeoDistanceRangeDocSet distDocSet = new GeoDistanceRangeDocSet(context.reader().maxDoc(), acceptedDocs, values, fixedSourceDistance, distanceBoundingCheck, inclusiveLowerPoint, inclusiveUpperPoint);
if (boundingBoxDocSet == null) {
return distDocSet;
boundingBoxWeight = boundingBoxFilter.createWeight(searcher, false);
} else {
return new AndDocIdSet(new DocIdSet[]{boundingBoxDocSet, distDocSet});
boundingBoxWeight = null;
}
return new ConstantScoreWeight(this) {
@Override
public Scorer scorer(LeafReaderContext context, final Bits acceptDocs) throws IOException {
final DocIdSetIterator approximation;
if (boundingBoxWeight != null) {
approximation = boundingBoxWeight.scorer(context, null);
} else {
approximation = DocIdSetIterator.all(context.reader().maxDoc());
}
if (approximation == null) {
// if the approximation does not match anything, we're done
return null;
}
final MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
final TwoPhaseIterator twoPhaseIterator = new TwoPhaseIterator(approximation) {
@Override
public boolean matches() throws IOException {
final int doc = approximation.docID();
if (acceptDocs != null && acceptDocs.get(doc) == false) {
return false;
}
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
GeoPoint point = values.valueAt(i);
if (distanceBoundingCheck.isWithin(point.lat(), point.lon())) {
double d = fixedSourceDistance.calculate(point.lat(), point.lon());
if (d >= inclusiveLowerPoint && d <= inclusiveUpperPoint) {
return true;
}
}
}
return false;
}
};
return new ConstantScoreScorer(this, score(), twoPhaseIterator);
}
};
}
@Override
@ -134,7 +178,7 @@ public class GeoDistanceRangeFilter extends Filter {
if (this == o) return true;
if (super.equals(o) == false) return false;
GeoDistanceRangeFilter filter = (GeoDistanceRangeFilter) o;
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) o;
if (Double.compare(filter.inclusiveLowerPoint, inclusiveLowerPoint) != 0) return false;
if (Double.compare(filter.inclusiveUpperPoint, inclusiveUpperPoint) != 0) return false;
@ -169,38 +213,4 @@ public class GeoDistanceRangeFilter extends Filter {
return result;
}
public static class GeoDistanceRangeDocSet extends DocValuesDocIdSet {
private final MultiGeoPointValues values;
private final GeoDistance.FixedSourceDistance fixedSourceDistance;
private final GeoDistance.DistanceBoundingCheck distanceBoundingCheck;
private final double inclusiveLowerPoint; // in miles
private final double inclusiveUpperPoint; // in miles
public GeoDistanceRangeDocSet(int maxDoc, @Nullable Bits acceptDocs, MultiGeoPointValues values, GeoDistance.FixedSourceDistance fixedSourceDistance, GeoDistance.DistanceBoundingCheck distanceBoundingCheck,
double inclusiveLowerPoint, double inclusiveUpperPoint) {
super(maxDoc, acceptDocs);
this.values = values;
this.fixedSourceDistance = fixedSourceDistance;
this.distanceBoundingCheck = distanceBoundingCheck;
this.inclusiveLowerPoint = inclusiveLowerPoint;
this.inclusiveUpperPoint = inclusiveUpperPoint;
}
@Override
protected boolean matchDoc(int doc) {
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
GeoPoint point = values.valueAt(i);
if (distanceBoundingCheck.isWithin(point.lat(), point.lon())) {
double d = fixedSourceDistance.calculate(point.lat(), point.lon());
if (d >= inclusiveLowerPoint && d <= inclusiveUpperPoint) {
return true;
}
}
}
return false;
}
}
}

View File

@ -1,109 +0,0 @@
/*
* 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.index.search.geo;
import java.io.IOException;
import java.util.Arrays;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocValuesDocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.util.Bits;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
/**
*
*/
public class GeoPolygonFilter extends Filter {
private final GeoPoint[] points;
private final IndexGeoPointFieldData indexFieldData;
public GeoPolygonFilter(IndexGeoPointFieldData indexFieldData, GeoPoint...points) {
this.points = points;
this.indexFieldData = indexFieldData;
}
public GeoPoint[] points() {
return points;
}
public String fieldName() {
return indexFieldData.getFieldNames().indexName();
}
@Override
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptedDocs) throws IOException {
final MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
return new GeoPolygonDocIdSet(context.reader().maxDoc(), acceptedDocs, values, points);
}
@Override
public String toString(String field) {
StringBuilder sb = new StringBuilder("GeoPolygonFilter(");
sb.append(indexFieldData.getFieldNames().indexName());
sb.append(", ").append(Arrays.toString(points)).append(')');
return sb.toString();
}
public static class GeoPolygonDocIdSet extends DocValuesDocIdSet {
private final MultiGeoPointValues values;
private final GeoPoint[] points;
public GeoPolygonDocIdSet(int maxDoc, @Nullable Bits acceptDocs, MultiGeoPointValues values, GeoPoint[] points) {
super(maxDoc, acceptDocs);
this.values = values;
this.points = points;
}
@Override
protected boolean matchDoc(int doc) {
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
GeoPoint point = values.valueAt(i);
if (pointInPolygon(points, point.lat(), point.lon())) {
return true;
}
}
return false;
}
private static boolean pointInPolygon(GeoPoint[] points, double lat, double lon) {
boolean inPoly = false;
for (int i = 1; i < points.length; i++) {
if (points[i].lon() < lon && points[i-1].lon() >= lon
|| points[i-1].lon() < lon && points[i].lon() >= lon) {
if (points[i].lat() + (lon - points[i].lon()) /
(points[i-1].lon() - points[i].lon()) * (points[i-1].lat() - points[i].lat()) < lat) {
inPoly = !inPoly;
}
}
}
return inPoly;
}
}
}

View File

@ -0,0 +1,129 @@
/*
* 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.index.search.geo;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RandomAccessWeight;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.Bits;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import java.io.IOException;
import java.util.Arrays;
/**
*
*/
public class GeoPolygonQuery extends Query {
private final GeoPoint[] points;
private final IndexGeoPointFieldData indexFieldData;
public GeoPolygonQuery(IndexGeoPointFieldData indexFieldData, GeoPoint...points) {
this.points = points;
this.indexFieldData = indexFieldData;
}
public GeoPoint[] points() {
return points;
}
public String fieldName() {
return indexFieldData.getFieldNames().indexName();
}
@Override
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
return new RandomAccessWeight(this) {
@Override
protected Bits getMatchingDocs(LeafReaderContext context) throws IOException {
final int maxDoc = context.reader().maxDoc();
final MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
return new Bits() {
private boolean pointInPolygon(GeoPoint[] points, double lat, double lon) {
boolean inPoly = false;
for (int i = 1; i < points.length; i++) {
if (points[i].lon() < lon && points[i-1].lon() >= lon
|| points[i-1].lon() < lon && points[i].lon() >= lon) {
if (points[i].lat() + (lon - points[i].lon()) /
(points[i-1].lon() - points[i].lon()) * (points[i-1].lat() - points[i].lat()) < lat) {
inPoly = !inPoly;
}
}
}
return inPoly;
}
@Override
public boolean get(int doc) {
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
GeoPoint point = values.valueAt(i);
if (pointInPolygon(points, point.lat(), point.lon())) {
return true;
}
}
return false;
}
@Override
public int length() {
return maxDoc;
}
};
}
};
}
@Override
public String toString(String field) {
StringBuilder sb = new StringBuilder("GeoPolygonFilter(");
sb.append(indexFieldData.getFieldNames().indexName());
sb.append(", ").append(Arrays.toString(points)).append(')');
return sb.toString();
}
@Override
public boolean equals(Object obj) {
if (super.equals(obj) == false) {
return false;
}
GeoPolygonQuery that = (GeoPolygonQuery) obj;
return indexFieldData.getFieldNames().indexName().equals(that.indexFieldData.getFieldNames().indexName())
&& Arrays.equals(points, that.points);
}
@Override
public int hashCode() {
int h = super.hashCode();
h = 31 * h + indexFieldData.getFieldNames().indexName().hashCode();
h = 31 * h + Arrays.hashCode(points);
return h;
}
}

View File

@ -19,29 +19,29 @@
package org.elasticsearch.index.search.geo;
import java.io.IOException;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocValuesDocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RandomAccessWeight;
import org.apache.lucene.search.Weight;
import org.apache.lucene.util.Bits;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import java.io.IOException;
/**
*
*/
public class InMemoryGeoBoundingBoxFilter extends Filter {
public class InMemoryGeoBoundingBoxQuery extends Query {
private final GeoPoint topLeft;
private final GeoPoint bottomRight;
private final IndexGeoPointFieldData indexFieldData;
public InMemoryGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, IndexGeoPointFieldData indexFieldData) {
public InMemoryGeoBoundingBoxQuery(GeoPoint topLeft, GeoPoint bottomRight, IndexGeoPointFieldData indexFieldData) {
this.topLeft = topLeft;
this.bottomRight = bottomRight;
this.indexFieldData = indexFieldData;
@ -60,15 +60,20 @@ public class InMemoryGeoBoundingBoxFilter extends Filter {
}
@Override
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptedDocs) throws IOException {
final MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
//checks to see if bounding box crosses 180 degrees
if (topLeft.lon() > bottomRight.lon()) {
return new Meridian180GeoBoundingBoxDocSet(context.reader().maxDoc(), acceptedDocs, values, topLeft, bottomRight);
} else {
return new GeoBoundingBoxDocSet(context.reader().maxDoc(), acceptedDocs, values, topLeft, bottomRight);
}
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
return new RandomAccessWeight(this) {
@Override
protected Bits getMatchingDocs(LeafReaderContext context) throws IOException {
final int maxDoc = context.reader().maxDoc();
final MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
// checks to see if bounding box crosses 180 degrees
if (topLeft.lon() > bottomRight.lon()) {
return new Meridian180GeoBoundingBoxBits(maxDoc, values, topLeft, bottomRight);
} else {
return new GeoBoundingBoxBits(maxDoc, values, topLeft, bottomRight);
}
}
};
}
@Override
@ -81,7 +86,7 @@ public class InMemoryGeoBoundingBoxFilter extends Filter {
if (super.equals(obj) == false) {
return false;
}
InMemoryGeoBoundingBoxFilter other = (InMemoryGeoBoundingBoxFilter) obj;
InMemoryGeoBoundingBoxQuery other = (InMemoryGeoBoundingBoxQuery) obj;
return fieldName().equalsIgnoreCase(other.fieldName())
&& topLeft.equals(other.topLeft)
&& bottomRight.equals(other.bottomRight);
@ -96,20 +101,21 @@ public class InMemoryGeoBoundingBoxFilter extends Filter {
return h;
}
public static class Meridian180GeoBoundingBoxDocSet extends DocValuesDocIdSet {
private static class Meridian180GeoBoundingBoxBits implements Bits {
private final int maxDoc;
private final MultiGeoPointValues values;
private final GeoPoint topLeft;
private final GeoPoint bottomRight;
public Meridian180GeoBoundingBoxDocSet(int maxDoc, @Nullable Bits acceptDocs, MultiGeoPointValues values, GeoPoint topLeft, GeoPoint bottomRight) {
super(maxDoc, acceptDocs);
public Meridian180GeoBoundingBoxBits(int maxDoc, MultiGeoPointValues values, GeoPoint topLeft, GeoPoint bottomRight) {
this.maxDoc = maxDoc;
this.values = values;
this.topLeft = topLeft;
this.bottomRight = bottomRight;
}
@Override
protected boolean matchDoc(int doc) {
public boolean get(int doc) {
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
@ -121,22 +127,28 @@ public class InMemoryGeoBoundingBoxFilter extends Filter {
}
return false;
}
@Override
public int length() {
return maxDoc;
}
}
public static class GeoBoundingBoxDocSet extends DocValuesDocIdSet {
private static class GeoBoundingBoxBits implements Bits {
private final int maxDoc;
private final MultiGeoPointValues values;
private final GeoPoint topLeft;
private final GeoPoint bottomRight;
public GeoBoundingBoxDocSet(int maxDoc, @Nullable Bits acceptDocs, MultiGeoPointValues values, GeoPoint topLeft, GeoPoint bottomRight) {
super(maxDoc, acceptDocs);
public GeoBoundingBoxBits(int maxDoc, MultiGeoPointValues values, GeoPoint topLeft, GeoPoint bottomRight) {
this.maxDoc = maxDoc;
this.values = values;
this.topLeft = topLeft;
this.bottomRight = bottomRight;
}
@Override
protected boolean matchDoc(int doc) {
public boolean get(int doc) {
values.setDocument(doc);
final int length = values.count();
for (int i = 0; i < length; i++) {
@ -148,5 +160,10 @@ public class InMemoryGeoBoundingBoxFilter extends Filter {
}
return false;
}
@Override
public int length() {
return maxDoc;
}
}
}

View File

@ -21,16 +21,16 @@ package org.elasticsearch.index.search.geo;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.QueryWrapperFilter;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
/**
*/
public class IndexedGeoBoundingBoxFilter {
public class IndexedGeoBoundingBoxQuery {
public static Filter create(GeoPoint topLeft, GeoPoint bottomRight, GeoPointFieldMapper fieldMapper) {
public static Query create(GeoPoint topLeft, GeoPoint bottomRight, GeoPointFieldMapper fieldMapper) {
if (!fieldMapper.isEnableLatLon()) {
throw new IllegalArgumentException("lat/lon is not enabled (indexed) for field [" + fieldMapper.name() + "], can't use indexed filter on it");
}
@ -42,19 +42,19 @@ public class IndexedGeoBoundingBoxFilter {
}
}
private static Filter westGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, GeoPointFieldMapper fieldMapper) {
private static Query westGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, GeoPointFieldMapper fieldMapper) {
BooleanQuery filter = new BooleanQuery();
filter.setMinimumNumberShouldMatch(1);
filter.add(fieldMapper.lonMapper().rangeFilter(null, bottomRight.lon(), true, true), Occur.SHOULD);
filter.add(fieldMapper.lonMapper().rangeFilter(topLeft.lon(), null, true, true), Occur.SHOULD);
filter.add(fieldMapper.latMapper().rangeFilter(bottomRight.lat(), topLeft.lat(), true, true), Occur.MUST);
return new QueryWrapperFilter(filter);
return new ConstantScoreQuery(filter);
}
private static Filter eastGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, GeoPointFieldMapper fieldMapper) {
private static Query eastGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, GeoPointFieldMapper fieldMapper) {
BooleanQuery filter = new BooleanQuery();
filter.add(fieldMapper.lonMapper().rangeFilter(topLeft.lon(), bottomRight.lon(), true, true), Occur.MUST);
filter.add(fieldMapper.latMapper().rangeFilter(bottomRight.lat(), topLeft.lat(), true, true), Occur.MUST);
return new QueryWrapperFilter(filter);
return new ConstantScoreQuery(filter);
}
}

View File

@ -1,96 +0,0 @@
/*
* 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.common.lucene.search;
import java.io.IOException;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.DocValuesDocIdSet;
import org.apache.lucene.util.BitDocIdSet;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
import org.elasticsearch.common.lucene.docset.AndDocIdSet;
import org.elasticsearch.test.ElasticsearchTestCase;
public class AndDocIdSetTests extends ElasticsearchTestCase {
private static FixedBitSet randomBitSet(int numDocs) {
FixedBitSet b = new FixedBitSet(numDocs);
for (int i = 0; i < numDocs; ++i) {
if (random().nextBoolean()) {
b.set(i);
}
}
return b;
}
public void testDuel() throws IOException {
for (int iter = 0; iter < 1000; ++iter) {
final int numSets = 1 + random().nextInt(5);
final int numDocs = 1 + random().nextInt(1000);
FixedBitSet anded = new FixedBitSet(numDocs);
anded.set(0, numDocs);
final DocIdSet[] sets = new DocIdSet[numSets];
for (int i = 0; i < numSets; ++i) {
final FixedBitSet randomSet = randomBitSet(numDocs);
anded.and(randomSet);
if (random().nextBoolean()) {
// will be considered 'fast' by AndDocIdSet
sets[i] = new BitDocIdSet(randomSet);
} else {
// will be considered 'slow' by AndDocIdSet
sets[i] = new DocValuesDocIdSet(numDocs, null) {
@Override
protected boolean matchDoc(int doc) {
return randomSet.get(doc);
}
};
}
}
AndDocIdSet andSet = new AndDocIdSet(sets);
Bits andBits = andSet.bits();
if (andBits != null) {
for (int i = 0; i < numDocs; ++i) {
assertEquals(anded.get(i), andBits.get(i));
}
}
DocIdSetIterator andIt = andSet.iterator();
if (andIt == null) {
assertEquals(0, anded.cardinality());
} else {
int previous = -1;
for (int doc = andIt.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = andIt.nextDoc()) {
for (int j = previous + 1; j < doc; ++j) {
assertFalse(anded.get(j));
}
assertTrue(anded.get(doc));
previous = doc;
}
for (int j = previous + 1; j < numDocs; ++j) {
assertFalse(anded.get(j));
}
}
}
}
}

View File

@ -92,9 +92,9 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
import org.elasticsearch.index.search.child.ParentConstantScoreQuery;
import org.elasticsearch.index.search.geo.GeoDistanceFilter;
import org.elasticsearch.index.search.geo.GeoPolygonFilter;
import org.elasticsearch.index.search.geo.InMemoryGeoBoundingBoxFilter;
import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery;
import org.elasticsearch.index.search.geo.GeoPolygonQuery;
import org.elasticsearch.index.search.geo.InMemoryGeoBoundingBoxQuery;
import org.elasticsearch.index.search.morelikethis.MoreLikeThisFetchService;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
@ -1811,186 +1811,199 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
}
@Test
public void testGeoDistanceFilterNamed() throws IOException {
public void testGeoDistanceRangeQueryNamed() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance-named.json");
ParsedQuery parsedQuery = queryParser.parse(query);
assertThat(parsedQuery.namedFilters().containsKey("test"), equalTo(true));
assertThat(parsedQuery.query(), instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery.query();
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter1() throws IOException {
public void testGeoDistanceRangeQuery1() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance1.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter2() throws IOException {
public void testGeoDistanceRangeQuery2() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance2.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter3() throws IOException {
public void testGeoDistanceRangeQuery3() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance3.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter4() throws IOException {
public void testGeoDistanceRangeQuery4() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance4.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter5() throws IOException {
public void testGeoDistanceRangeQuery5() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance5.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter6() throws IOException {
public void testGeoDistanceRangeQuery6() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance6.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter7() throws IOException {
public void testGeoDistanceRangeQuery7() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance7.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(0.012, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(0.012, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter8() throws IOException {
public void testGeoDistanceRangeQuery8() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance8.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.KILOMETERS.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.KILOMETERS.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter9() throws IOException {
public void testGeoDistanceRangeQuery9() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance9.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter10() throws IOException {
public void testGeoDistanceRangeQuery10() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance10.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter11() throws IOException {
public void testGeoDistanceRangeQuery11() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance11.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
public void testGeoDistanceFilter12() throws IOException {
public void testGeoDistanceRangeQuery12() throws IOException {
IndexQueryParserService queryParser = queryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/geo_distance12.json");
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoDistanceFilter filter = (GeoDistanceFilter) constantScoreQuery.getQuery();
GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.lat(), closeTo(40, 0.00001));
assertThat(filter.lon(), closeTo(-70, 0.00001));
assertThat(filter.distance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
}
@Test
@ -2001,7 +2014,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
assertThat(parsedQuery.query(), instanceOf(ConstantScoreQuery.class));
assertThat(parsedQuery.namedFilters().containsKey("test"), equalTo(true));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery.query();
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2017,7 +2030,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2032,7 +2045,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2047,7 +2060,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2062,7 +2075,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2077,7 +2090,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2092,7 +2105,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
InMemoryGeoBoundingBoxFilter filter = (InMemoryGeoBoundingBoxFilter) constantScoreQuery.getQuery();
InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
@ -2109,7 +2122,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
assertThat(parsedQuery.namedFilters().containsKey("test"), equalTo(true));
assertThat(parsedQuery.query(), instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery.query();
GeoPolygonFilter filter = (GeoPolygonFilter) constantScoreQuery.getQuery();
GeoPolygonQuery filter = (GeoPolygonQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.points().length, equalTo(4));
assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));
@ -2150,7 +2163,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoPolygonFilter filter = (GeoPolygonFilter) constantScoreQuery.getQuery();
GeoPolygonQuery filter = (GeoPolygonQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.points().length, equalTo(4));
assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));
@ -2168,7 +2181,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoPolygonFilter filter = (GeoPolygonFilter) constantScoreQuery.getQuery();
GeoPolygonQuery filter = (GeoPolygonQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.points().length, equalTo(4));
assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));
@ -2186,7 +2199,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoPolygonFilter filter = (GeoPolygonFilter) constantScoreQuery.getQuery();
GeoPolygonQuery filter = (GeoPolygonQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.points().length, equalTo(4));
assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));
@ -2204,7 +2217,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest {
Query parsedQuery = queryParser.parse(query).query();
assertThat(parsedQuery, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) parsedQuery;
GeoPolygonFilter filter = (GeoPolygonFilter) constantScoreQuery.getQuery();
GeoPolygonQuery filter = (GeoPolygonQuery) constantScoreQuery.getQuery();
assertThat(filter.fieldName(), equalTo("location"));
assertThat(filter.points().length, equalTo(4));
assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));