You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by jp...@apache.org on 2017/05/23 16:47:00 UTC
lucene-solr:master: LUCENE-7847: Fix the all-docs-match optimization
of range queries on range fields.
Repository: lucene-solr
Updated Branches:
refs/heads/master 31e02e93a -> 14320a584
LUCENE-7847: Fix the all-docs-match optimization of range queries on range fields.
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/14320a58
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/14320a58
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/14320a58
Branch: refs/heads/master
Commit: 14320a584c7771c63fba4de868c51ee9a5cf06de
Parents: 31e02e9
Author: Adrien Grand <jp...@gmail.com>
Authored: Tue May 23 18:37:01 2017 +0200
Committer: Adrien Grand <jp...@gmail.com>
Committed: Tue May 23 18:46:50 2017 +0200
----------------------------------------------------------------------
lucene/CHANGES.txt | 3 ++
.../apache/lucene/document/RangeFieldQuery.java | 48 ++++++++++----------
.../search/TestDoubleRangeFieldQueries.java | 15 ++++--
.../search/TestFloatRangeFieldQueries.java | 15 ++++--
.../lucene/search/TestIntRangeFieldQueries.java | 23 ++++++++--
.../search/TestLongRangeFieldQueries.java | 23 ++++++++--
.../search/TestInetAddressRangeQueries.java | 18 ++++++--
.../search/BaseRangeFieldQueryTestCase.java | 4 +-
8 files changed, 104 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 2138321..3951cea 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -155,6 +155,9 @@ Bug Fixes
* LUCENE-7833: ToParentBlockJoinQuery computed the min score instead of the max
score with ScoreMode.MAX. (Adrien Grand)
+* LUCENE-7847: Fixed all-docs-match optimization of range queries on range
+ fields. (Adrien Grand)
+
Improvements
* LUCENE-7782: OfflineSorter now passes the total number of items it
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/core/src/java/org/apache/lucene/document/RangeFieldQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/RangeFieldQuery.java b/lucene/core/src/java/org/apache/lucene/document/RangeFieldQuery.java
index 10f10fa..750189d 100644
--- a/lucene/core/src/java/org/apache/lucene/document/RangeFieldQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/document/RangeFieldQuery.java
@@ -112,6 +112,7 @@ abstract class RangeFieldQuery extends Query {
public final Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
return new ConstantScoreWeight(this, boost) {
final RangeFieldComparator target = new RangeFieldComparator();
+
private DocIdSet buildMatchingDocIdSet(LeafReader reader, PointValues values) throws IOException {
DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc(), values, field);
values.intersect(
@@ -133,25 +134,29 @@ abstract class RangeFieldQuery extends Query {
}
@Override
public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) {
- byte[] node = getInternalRange(minPackedValue, maxPackedValue);
- // compute range relation for BKD traversal
- if (target.intersects(node) == false) {
- return Relation.CELL_OUTSIDE_QUERY;
- } else if (target.within(node)) {
- // target within cell; continue traversing:
- return Relation.CELL_CROSSES_QUERY;
- } else if (target.contains(node)) {
- // target contains cell; add iff queryType is not a CONTAINS or CROSSES query:
- return (queryType == QueryType.CONTAINS || queryType == QueryType.CROSSES) ?
- Relation.CELL_OUTSIDE_QUERY : Relation.CELL_INSIDE_QUERY;
- }
- // target intersects cell; continue traversing:
- return Relation.CELL_CROSSES_QUERY;
+ return compareRange(minPackedValue, maxPackedValue);
}
});
return result.build();
}
+ private Relation compareRange(byte[] minPackedValue, byte[] maxPackedValue) {
+ byte[] node = getInternalRange(minPackedValue, maxPackedValue);
+ // compute range relation for BKD traversal
+ if (target.intersects(node) == false) {
+ return Relation.CELL_OUTSIDE_QUERY;
+ } else if (target.within(node)) {
+ // target within cell; continue traversing:
+ return Relation.CELL_CROSSES_QUERY;
+ } else if (target.contains(node)) {
+ // target contains cell; add iff queryType is not a CONTAINS or CROSSES query:
+ return (queryType == QueryType.CONTAINS || queryType == QueryType.CROSSES) ?
+ Relation.CELL_OUTSIDE_QUERY : Relation.CELL_INSIDE_QUERY;
+ }
+ // target intersects cell; continue traversing:
+ return Relation.CELL_CROSSES_QUERY;
+ }
+
@Override
public Scorer scorer(LeafReaderContext context) throws IOException {
LeafReader reader = context.reader();
@@ -166,17 +171,10 @@ abstract class RangeFieldQuery extends Query {
return null;
}
checkFieldInfo(fieldInfo);
- boolean allDocsMatch = true;
- if (values.getDocCount() == reader.maxDoc()) {
- // if query crosses, docs need to be further scrutinized
- byte[] range = getInternalRange(values.getMinPackedValue(), values.getMaxPackedValue());
- // if the internal node is not equal and not contained by the query, all docs do not match
- if (queryType == QueryType.CROSSES || (!Arrays.equals(ranges, range)
- && (target.contains(range) == false || queryType != QueryType.WITHIN))) {
- allDocsMatch = false;
- }
- } else {
- allDocsMatch = false;
+ boolean allDocsMatch = false;
+ if (values.getDocCount() == reader.maxDoc()
+ && compareRange(values.getMinPackedValue(), values.getMaxPackedValue()) == Relation.CELL_INSIDE_QUERY) {
+ allDocsMatch = true;
}
DocIdSetIterator iterator = allDocsMatch == true ?
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/core/src/test/org/apache/lucene/search/TestDoubleRangeFieldQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDoubleRangeFieldQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestDoubleRangeFieldQueries.java
index 49ca710..a5cbed6 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDoubleRangeFieldQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDoubleRangeFieldQueries.java
@@ -31,11 +31,18 @@ public class TestDoubleRangeFieldQueries extends BaseRangeFieldQueryTestCase {
private static final String FIELD_NAME = "doubleRangeField";
private double nextDoubleInternal() {
- if (rarely()) {
- return random().nextBoolean() ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
+ switch (random().nextInt(5)) {
+ case 0:
+ return Double.NEGATIVE_INFINITY;
+ case 1:
+ return Double.POSITIVE_INFINITY;
+ default:
+ if (random().nextBoolean()) {
+ return random().nextDouble();
+ } else {
+ return (random().nextInt(15) - 7) / 3d;
+ }
}
- double max = Double.MAX_VALUE / 2;
- return (max + max) * random().nextDouble() - max;
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/core/src/test/org/apache/lucene/search/TestFloatRangeFieldQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestFloatRangeFieldQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestFloatRangeFieldQueries.java
index 6dc5907..6eda4de 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestFloatRangeFieldQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestFloatRangeFieldQueries.java
@@ -31,11 +31,18 @@ public class TestFloatRangeFieldQueries extends BaseRangeFieldQueryTestCase {
private static final String FIELD_NAME = "floatRangeField";
private float nextFloatInternal() {
- if (rarely()) {
- return random().nextBoolean() ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ switch (random().nextInt(5)) {
+ case 0:
+ return Float.NEGATIVE_INFINITY;
+ case 1:
+ return Float.POSITIVE_INFINITY;
+ default:
+ if (random().nextBoolean()) {
+ return random().nextFloat();
+ } else {
+ return (random().nextInt(15) - 7) / 3f;
+ }
}
- float max = Float.MAX_VALUE / 2;
- return (max + max) * random().nextFloat() - max;
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/core/src/test/org/apache/lucene/search/TestIntRangeFieldQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestIntRangeFieldQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestIntRangeFieldQueries.java
index 14771c9..ecbd55b 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestIntRangeFieldQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestIntRangeFieldQueries.java
@@ -23,6 +23,7 @@ import org.apache.lucene.document.IntRange;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.TestUtil;
/**
* Random testing for IntRange Queries.
@@ -31,11 +32,25 @@ public class TestIntRangeFieldQueries extends BaseRangeFieldQueryTestCase {
private static final String FIELD_NAME = "intRangeField";
private int nextIntInternal() {
- if (rarely()) {
- return random().nextBoolean() ? Integer.MAX_VALUE : Integer.MIN_VALUE;
+ switch (random().nextInt(5)) {
+ case 0:
+ return Integer.MIN_VALUE;
+ case 1:
+ return Integer.MAX_VALUE;
+ default:
+ int bpv = random().nextInt(32);
+ switch (bpv) {
+ case 32:
+ return random().nextInt();
+ default:
+ int v = TestUtil.nextInt(random(), 0, (1 << bpv) - 1);
+ if (bpv > 0) {
+ // negative values sometimes
+ v -= 1 << (bpv - 1);
+ }
+ return v;
+ }
}
- int max = Integer.MAX_VALUE / 2;
- return (max + max) * random().nextInt() - max;
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/core/src/test/org/apache/lucene/search/TestLongRangeFieldQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLongRangeFieldQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestLongRangeFieldQueries.java
index 60d7ea3..3ad34b5 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestLongRangeFieldQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestLongRangeFieldQueries.java
@@ -23,6 +23,7 @@ import org.apache.lucene.document.LongRange;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.TestUtil;
/**
* Random testing for LongRange Queries.
@@ -31,11 +32,25 @@ public class TestLongRangeFieldQueries extends BaseRangeFieldQueryTestCase {
private static final String FIELD_NAME = "longRangeField";
private long nextLongInternal() {
- if (rarely()) {
- return random().nextBoolean() ? Long.MAX_VALUE : Long.MIN_VALUE;
+ switch (random().nextInt(5)) {
+ case 0:
+ return Long.MIN_VALUE;
+ case 1:
+ return Long.MAX_VALUE;
+ default:
+ int bpv = random().nextInt(64);
+ switch (bpv) {
+ case 64:
+ return random().nextLong();
+ default:
+ long v = TestUtil.nextLong(random(), 0, (1L << bpv) - 1);
+ if (bpv > 0) {
+ // negative values sometimes
+ v -= 1L << (bpv - 1);
+ }
+ return v;
+ }
}
- long max = Long.MAX_VALUE / 2;
- return (max + max) * random().nextLong() - max;
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/misc/src/test/org/apache/lucene/search/TestInetAddressRangeQueries.java
----------------------------------------------------------------------
diff --git a/lucene/misc/src/test/org/apache/lucene/search/TestInetAddressRangeQueries.java b/lucene/misc/src/test/org/apache/lucene/search/TestInetAddressRangeQueries.java
index 252162c..907ba55 100644
--- a/lucene/misc/src/test/org/apache/lucene/search/TestInetAddressRangeQueries.java
+++ b/lucene/misc/src/test/org/apache/lucene/search/TestInetAddressRangeQueries.java
@@ -18,6 +18,7 @@ package org.apache.lucene.search;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.Arrays;
import org.apache.lucene.document.InetAddressPoint;
import org.apache.lucene.document.InetAddressRange;
@@ -44,8 +45,19 @@ public class TestInetAddressRangeQueries extends BaseRangeFieldQueryTestCase {
/** return random IPv4 or IPv6 address */
private InetAddress nextInetaddress() throws UnknownHostException {
byte[] b = random().nextBoolean() ? new byte[4] : new byte[16];
- random().nextBytes(b);
- return InetAddress.getByAddress(b);
+ switch (random().nextInt(5)) {
+ case 0:
+ return InetAddress.getByAddress(b);
+ case 1:
+ Arrays.fill(b, (byte) 0xff);
+ return InetAddress.getByAddress(b);
+ case 2:
+ Arrays.fill(b, (byte) 42);
+ return InetAddress.getByAddress(b);
+ default:
+ random().nextBytes(b);
+ return InetAddress.getByAddress(b);
+ }
}
@Override
@@ -159,7 +171,7 @@ public class TestInetAddressRangeQueries extends BaseRangeFieldQueryTestCase {
@Override
protected boolean isEqual(Range o) {
IpRange other = (IpRange)o;
- return this.min.equals(other.min) && this.max.equals(other.max);
+ return Arrays.equals(min, other.min) && Arrays.equals(max, other.max);
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/14320a58/lucene/test-framework/src/java/org/apache/lucene/search/BaseRangeFieldQueryTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/BaseRangeFieldQueryTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/search/BaseRangeFieldQueryTestCase.java
index 76de732..7d21eb3 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/search/BaseRangeFieldQueryTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/search/BaseRangeFieldQueryTestCase.java
@@ -61,7 +61,9 @@ public abstract class BaseRangeFieldQueryTestCase extends LuceneTestCase {
public void testRandomTiny() throws Exception {
// Make sure single-leaf-node case is OK:
- doTestRandom(10, false);
+ for (int i = 0; i < 10; ++i) {
+ doTestRandom(10, false);
+ }
}
public void testRandomMedium() throws Exception {