Query DSL: Make geo filters queries.
This commit replaces geo filters with queries that support two-phase iteration.
This commit is contained in:
parent
842608c396
commit
f22935b1a8
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,30 +113,72 @@ 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)) {
|
||||
boundingBoxWeight = boundingBoxFilter.createWeight(searcher, false);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
MultiGeoPointValues values = indexFieldData.load(context).getGeoPointValues();
|
||||
GeoDistanceRangeDocSet distDocSet = new GeoDistanceRangeDocSet(context.reader().maxDoc(), acceptedDocs, values, fixedSourceDistance, distanceBoundingCheck, inclusiveLowerPoint, inclusiveUpperPoint);
|
||||
if (boundingBoxDocSet == null) {
|
||||
return distDocSet;
|
||||
} else {
|
||||
return new AndDocIdSet(new DocIdSet[]{boundingBoxDocSet, distDocSet});
|
||||
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
|
||||
public boolean equals(Object o) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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,16 +60,21 @@ public class InMemoryGeoBoundingBoxFilter extends Filter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptedDocs) throws IOException {
|
||||
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
|
||||
// checks to see if bounding box crosses 180 degrees
|
||||
if (topLeft.lon() > bottomRight.lon()) {
|
||||
return new Meridian180GeoBoundingBoxDocSet(context.reader().maxDoc(), acceptedDocs, values, topLeft, bottomRight);
|
||||
return new Meridian180GeoBoundingBoxBits(maxDoc, values, topLeft, bottomRight);
|
||||
} else {
|
||||
return new GeoBoundingBoxDocSet(context.reader().maxDoc(), acceptedDocs, values, topLeft, bottomRight);
|
||||
return new GeoBoundingBoxBits(maxDoc, values, topLeft, bottomRight);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -90,9 +90,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;
|
||||
|
@ -134,7 +134,6 @@ import static org.elasticsearch.index.query.QueryBuilders.spanTermQuery;
|
|||
import static org.elasticsearch.index.query.QueryBuilders.spanWithinQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.wildcardQuery;
|
||||
import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.factorFunction;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertBooleanSubQuery;
|
||||
|
@ -1803,186 +1802,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
|
||||
|
@ -1993,7 +2005,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));
|
||||
|
@ -2009,7 +2021,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));
|
||||
|
@ -2024,7 +2036,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));
|
||||
|
@ -2039,7 +2051,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));
|
||||
|
@ -2054,7 +2066,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));
|
||||
|
@ -2069,7 +2081,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));
|
||||
|
@ -2084,7 +2096,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));
|
||||
|
@ -2101,7 +2113,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));
|
||||
|
@ -2142,7 +2154,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));
|
||||
|
@ -2160,7 +2172,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));
|
||||
|
@ -2178,7 +2190,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));
|
||||
|
@ -2196,7 +2208,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));
|
||||
|
|
Loading…
Reference in New Issue