Fix two unreleased percolator query analyze bugs
* If in a range query upper is smaller than lower then ignore the range query * If two empty range extractions are compared don't fail with NoSuchElementException
This commit is contained in:
parent
2ad3608245
commit
77bbe99102
|
@ -45,6 +45,7 @@ import org.apache.lucene.search.spans.SpanQuery;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.NumericUtils;
|
import org.apache.lucene.util.NumericUtils;
|
||||||
|
import org.apache.lucene.util.UnicodeUtil;
|
||||||
import org.elasticsearch.common.logging.LoggerMessageFormat;
|
import org.elasticsearch.common.logging.LoggerMessageFormat;
|
||||||
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
|
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
|
||||||
|
|
||||||
|
@ -361,6 +362,13 @@ final class QueryAnalyzer {
|
||||||
|
|
||||||
byte[] lowerPoint = pointRangeQuery.getLowerPoint();
|
byte[] lowerPoint = pointRangeQuery.getLowerPoint();
|
||||||
byte[] upperPoint = pointRangeQuery.getUpperPoint();
|
byte[] upperPoint = pointRangeQuery.getUpperPoint();
|
||||||
|
|
||||||
|
// Need to check whether upper is not smaller than lower, otherwise NumericUtils.subtract(...) fails IAE
|
||||||
|
// If upper is really smaller than lower then we deal with like MatchNoDocsQuery. (verified and no extractions)
|
||||||
|
if (new BytesRef(lowerPoint).compareTo(new BytesRef(upperPoint)) > 0) {
|
||||||
|
return new Result(true, Collections.emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
byte[] interval = new byte[16];
|
byte[] interval = new byte[16];
|
||||||
NumericUtils.subtract(16, 0, prepad(upperPoint), prepad(lowerPoint), interval);
|
NumericUtils.subtract(16, 0, prepad(upperPoint), prepad(lowerPoint), interval);
|
||||||
return new Result(false, Collections.singleton(new QueryExtraction(
|
return new Result(false, Collections.singleton(new QueryExtraction(
|
||||||
|
@ -453,6 +461,12 @@ final class QueryAnalyzer {
|
||||||
if (onlyRangeBasedExtractions) {
|
if (onlyRangeBasedExtractions) {
|
||||||
BytesRef extraction1SmallestRange = smallestRange(filtered1);
|
BytesRef extraction1SmallestRange = smallestRange(filtered1);
|
||||||
BytesRef extraction2SmallestRange = smallestRange(filtered2);
|
BytesRef extraction2SmallestRange = smallestRange(filtered2);
|
||||||
|
if (extraction1SmallestRange == null) {
|
||||||
|
return extractions2;
|
||||||
|
} else if (extraction2SmallestRange == null) {
|
||||||
|
return extractions1;
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the clause with smallest range, this is likely to be the rarest.
|
// Keep the clause with smallest range, this is likely to be the rarest.
|
||||||
if (extraction1SmallestRange.compareTo(extraction2SmallestRange) <= 0) {
|
if (extraction1SmallestRange.compareTo(extraction2SmallestRange) <= 0) {
|
||||||
return extractions1;
|
return extractions1;
|
||||||
|
@ -500,10 +514,10 @@ final class QueryAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BytesRef smallestRange(Set<QueryExtraction> terms) {
|
private static BytesRef smallestRange(Set<QueryExtraction> terms) {
|
||||||
BytesRef min = terms.iterator().next().range.interval;
|
BytesRef min = null;
|
||||||
for (QueryExtraction qt : terms) {
|
for (QueryExtraction qt : terms) {
|
||||||
if (qt.range != null) {
|
if (qt.range != null) {
|
||||||
if (qt.range.interval.compareTo(min) < 0) {
|
if (min == null || qt.range.interval.compareTo(min) < 0) {
|
||||||
min = qt.range.interval;
|
min = qt.range.interval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,6 +589,21 @@ public class QueryAnalyzerTests extends ESTestCase {
|
||||||
queryTerms2 = terms(new int[]{2, 3, 4}, "1", "456");
|
queryTerms2 = terms(new int[]{2, 3, 4}, "1", "456");
|
||||||
result = selectBestExtraction(Collections.emptyMap(), queryTerms1, queryTerms2);
|
result = selectBestExtraction(Collections.emptyMap(), queryTerms1, queryTerms2);
|
||||||
assertSame("Ignoring ranges, so then prefer queryTerms1, because it has the longest shortest term", queryTerms1, result);
|
assertSame("Ignoring ranges, so then prefer queryTerms1, because it has the longest shortest term", queryTerms1, result);
|
||||||
|
|
||||||
|
queryTerms1 = terms(new int[]{});
|
||||||
|
queryTerms2 = terms(new int[]{});
|
||||||
|
result = selectBestExtraction(Collections.emptyMap(), queryTerms1, queryTerms2);
|
||||||
|
assertSame("In case query extractions are empty", queryTerms2, result);
|
||||||
|
|
||||||
|
queryTerms1 = terms(new int[]{1});
|
||||||
|
queryTerms2 = terms(new int[]{});
|
||||||
|
result = selectBestExtraction(Collections.emptyMap(), queryTerms1, queryTerms2);
|
||||||
|
assertSame("In case query a single extraction is empty", queryTerms1, result);
|
||||||
|
|
||||||
|
queryTerms1 = terms(new int[]{});
|
||||||
|
queryTerms2 = terms(new int[]{1});
|
||||||
|
result = selectBestExtraction(Collections.emptyMap(), queryTerms1, queryTerms2);
|
||||||
|
assertSame("In case query a single extraction is empty", queryTerms2, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSelectBestExtraction_boostFields() {
|
public void testSelectBestExtraction_boostFields() {
|
||||||
|
@ -753,6 +768,13 @@ public class QueryAnalyzerTests extends ESTestCase {
|
||||||
expectThrows(UnsupportedQueryException.class, () -> analyze(query2, Collections.emptyMap()));
|
expectThrows(UnsupportedQueryException.class, () -> analyze(query2, Collections.emptyMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPointRangeQuery_lowerUpperReversed() {
|
||||||
|
Query query = IntPoint.newRangeQuery("_field", 20, 10);
|
||||||
|
Result result = analyze(query, Collections.emptyMap());
|
||||||
|
assertTrue(result.verified);
|
||||||
|
assertThat(result.extractions.size(), equalTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
public void testIndexOrDocValuesQuery() {
|
public void testIndexOrDocValuesQuery() {
|
||||||
Query query = new IndexOrDocValuesQuery(IntPoint.newRangeQuery("_field", 10, 20),
|
Query query = new IndexOrDocValuesQuery(IntPoint.newRangeQuery("_field", 10, 20),
|
||||||
SortedNumericDocValuesField.newSlowRangeQuery("_field", 10, 20));
|
SortedNumericDocValuesField.newSlowRangeQuery("_field", 10, 20));
|
||||||
|
|
Loading…
Reference in New Issue