mirror of https://github.com/apache/lucene.git
LUCENE-6560: BKDPointInBBOxQuery now handles dateline crossing correctly
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1685526 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a1876da5ee
commit
0ef770fcd0
|
@ -122,6 +122,9 @@ Bug fixes
|
|||
* LUCENE-6558: Highlighters now work with CustomScoreQuery (Cao Manh
|
||||
Dat via Mike McCandless)
|
||||
|
||||
* LUCENE-6560: BKDPointInBBoxQuery now handles "dateline crossing"
|
||||
correctly (Nick Knize, Mike McCandless)
|
||||
|
||||
Changes in Runtime Behavior
|
||||
|
||||
* LUCENE-6501: The subreader structure in ParallelCompositeReader
|
||||
|
|
|
@ -17,13 +17,13 @@ package org.apache.lucene.bkdtree;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedNumericDocValues;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.DocIdSet;
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.search.Explanation;
|
||||
|
@ -34,6 +34,9 @@ import org.apache.lucene.search.Weight;
|
|||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/** Finds all previously indexed points that fall within the specified boundings box.
|
||||
*
|
||||
* <p>The field must be indexed with {@link BKDTreeDocValuesFormat}, and {@link BKDPointField} added per document.
|
||||
|
@ -163,6 +166,28 @@ public class BKDPointInBBoxQuery extends Query {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query rewrite(IndexReader reader) throws IOException {
|
||||
// Crosses date line: we just rewrite into OR of two bboxes:
|
||||
if (maxLon < minLon) {
|
||||
|
||||
// Disable coord here because a multi-valued doc could match both rects and get unfairly boosted:
|
||||
BooleanQuery q = new BooleanQuery(true);
|
||||
|
||||
// E.g.: maxLon = -179, minLon = 179
|
||||
BKDPointInBBoxQuery left = new BKDPointInBBoxQuery(field, minLat, maxLat, BKDTreeWriter.MIN_LON_INCL, maxLon);
|
||||
left.setBoost(getBoost());
|
||||
q.add(new BooleanClause(left, BooleanClause.Occur.SHOULD));
|
||||
BKDPointInBBoxQuery right = new BKDPointInBBoxQuery(field, minLat, maxLat, minLon, BKDTreeWriter.MAX_LON_INCL);
|
||||
right.setBoost(getBoost());
|
||||
q.add(new BooleanClause(right, BooleanClause.Occur.SHOULD));
|
||||
return q;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
|
|
|
@ -452,18 +452,27 @@ public class TestBKDTree extends LuceneTestCase {
|
|||
lat1 = x;
|
||||
}
|
||||
|
||||
boolean crossesDateLine;
|
||||
if (lon1 < lon0) {
|
||||
if (random().nextBoolean()) {
|
||||
double x = lon0;
|
||||
lon0 = lon1;
|
||||
lon1 = x;
|
||||
crossesDateLine = false;
|
||||
} else {
|
||||
crossesDateLine = true;
|
||||
}
|
||||
} else {
|
||||
crossesDateLine = false;
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("\nTEST: iter=" + iter + " lat=" + lat0 + " TO " + lat1 + " lon=" + lon0 + " TO " + lon1);
|
||||
System.out.println("\nTEST: iter=" + iter + " lat=" + lat0 + " TO " + lat1 + " lon=" + lon0 + " TO " + lon1 + " crossesDateLine=" + crossesDateLine);
|
||||
}
|
||||
|
||||
Query query;
|
||||
if (random().nextBoolean()) {
|
||||
// TODO: get poly query working with dateline crossing too (how?)!
|
||||
if (crossesDateLine || random().nextBoolean()) {
|
||||
query = new BKDPointInBBoxQuery("point", lat0, lat1, lon0, lon1);
|
||||
} else {
|
||||
double[] lats = new double[5];
|
||||
|
@ -522,7 +531,7 @@ public class TestBKDTree extends LuceneTestCase {
|
|||
// The poly check quantizes slightly differently, so we allow for boundary cases to disagree
|
||||
} else {
|
||||
// We do exact quantized comparison so the bbox query should never disagree:
|
||||
fail(Thread.currentThread().getName() + ": iter=" + iter + " id=" + id + " docID=" + docID + " lat=" + lats[id] + " lon=" + lons[id] + " (bbox: lat=" + lat0 + " TO " + lat1 + " lon=" + lon0 + " TO " + lon1 + ") expected " + expected + " but got: " + hits.get(docID) + " deleted?=" + deleted.contains(id) + " query=" + query);
|
||||
fail(Thread.currentThread().getName() + ": iter=" + iter + " id=" + id + " docID=" + docID + " lat=" + lats[id] + " lon=" + lons[id] + " (bbox: lat=" + lat0 + " TO " + lat1 + " lon=" + lon0 + " TO " + lon1 + ") expected " + expected + " but got: " + hits.get(docID) + " deleted?=" + deleted.contains(id) + " query=" + query + " crossesDateLine=" + crossesDateLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -553,10 +562,18 @@ public class TestBKDTree extends LuceneTestCase {
|
|||
int pointLatEnc = BKDTreeWriter.encodeLat(pointLat);
|
||||
int pointLonEnc = BKDTreeWriter.encodeLon(pointLon);
|
||||
|
||||
if (rectLonMin < rectLonMax) {
|
||||
return pointLatEnc >= rectLatMinEnc &&
|
||||
pointLatEnc < rectLatMaxEnc &&
|
||||
pointLonEnc >= rectLonMinEnc &&
|
||||
pointLonEnc < rectLonMaxEnc;
|
||||
} else {
|
||||
// Rect crosses dateline:
|
||||
return pointLatEnc >= rectLatMinEnc &&
|
||||
pointLatEnc < rectLatMaxEnc &&
|
||||
(pointLonEnc >= rectLonMinEnc ||
|
||||
pointLonEnc < rectLonMaxEnc);
|
||||
}
|
||||
}
|
||||
|
||||
private static double randomLat() {
|
||||
|
|
Loading…
Reference in New Issue