mirror of https://github.com/apache/lucene.git
fixup main rebase by bringing over index sort opto
This commit is contained in:
parent
67fd647bab
commit
0fb0a63ebc
|
@ -16,19 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.lucene.document;
|
package org.apache.lucene.document;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.LongPredicate;
|
|
||||||
import org.apache.lucene.index.DocValues;
|
import org.apache.lucene.index.DocValues;
|
||||||
import org.apache.lucene.index.DocValuesSkipper;
|
import org.apache.lucene.index.DocValuesSkipper;
|
||||||
import org.apache.lucene.index.LeafReader;
|
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.SortedDocValues;
|
|
||||||
import org.apache.lucene.index.SortedSetDocValues;
|
import org.apache.lucene.index.SortedSetDocValues;
|
||||||
import org.apache.lucene.search.ConstantScoreScorer;
|
|
||||||
import org.apache.lucene.search.ConstantScoreWeight;
|
import org.apache.lucene.search.ConstantScoreWeight;
|
||||||
import org.apache.lucene.search.DocIdSetIterator;
|
|
||||||
import org.apache.lucene.search.DocValuesRangeIterator;
|
|
||||||
import org.apache.lucene.search.FieldExistsQuery;
|
import org.apache.lucene.search.FieldExistsQuery;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
@ -36,12 +28,13 @@ import org.apache.lucene.search.QueryVisitor;
|
||||||
import org.apache.lucene.search.ScoreMode;
|
import org.apache.lucene.search.ScoreMode;
|
||||||
import org.apache.lucene.search.Scorer;
|
import org.apache.lucene.search.Scorer;
|
||||||
import org.apache.lucene.search.ScorerSupplier;
|
import org.apache.lucene.search.ScorerSupplier;
|
||||||
import org.apache.lucene.search.Sort;
|
|
||||||
import org.apache.lucene.search.SortedSetDocValuesRangeScorer;
|
import org.apache.lucene.search.SortedSetDocValuesRangeScorer;
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
|
||||||
import org.apache.lucene.search.Weight;
|
import org.apache.lucene.search.Weight;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
final class SortedSetDocValuesRangeQuery extends Query {
|
final class SortedSetDocValuesRangeQuery extends Query {
|
||||||
|
|
||||||
private final String field;
|
private final String field;
|
||||||
|
@ -155,76 +148,7 @@ final class SortedSetDocValuesRangeQuery extends Query {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SortedSetDocValuesRangeScorer(values, minOrd, maxOrd, scoreMode, score(), skipper);
|
return new SortedSetDocValuesRangeScorer(field, values, minOrd, maxOrd, scoreMode, score(), skipper, context);
|
||||||
|
|
||||||
/**
|
|
||||||
// no terms matched in this segment
|
|
||||||
if (minOrd > maxOrd
|
|
||||||
|| (skipper != null
|
|
||||||
&& (minOrd > skipper.maxValue() || maxOrd < skipper.minValue()))) {
|
|
||||||
return new ConstantScoreScorer(score(), scoreMode, DocIdSetIterator.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
// all terms matched in this segment
|
|
||||||
if (skipper != null
|
|
||||||
&& skipper.docCount() == context.reader().maxDoc()
|
|
||||||
&& skipper.minValue() >= minOrd
|
|
||||||
&& skipper.maxValue() <= maxOrd) {
|
|
||||||
return new ConstantScoreScorer(
|
|
||||||
score(), scoreMode, DocIdSetIterator.all(skipper.docCount()));
|
|
||||||
}
|
|
||||||
|
|
||||||
final SortedDocValues singleton = DocValues.unwrapSingleton(values);
|
|
||||||
TwoPhaseIterator iterator;
|
|
||||||
if (singleton != null) {
|
|
||||||
if (skipper != null) {
|
|
||||||
final DocIdSetIterator psIterator =
|
|
||||||
getDocIdSetIteratorOrNullForPrimarySort(
|
|
||||||
context.reader(), singleton, skipper, minOrd, maxOrd);
|
|
||||||
if (psIterator != null) {
|
|
||||||
return new ConstantScoreScorer(score(), scoreMode, psIterator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator =
|
|
||||||
new TwoPhaseIterator(singleton) {
|
|
||||||
@Override
|
|
||||||
public boolean matches() throws IOException {
|
|
||||||
final long ord = singleton.ordValue();
|
|
||||||
return ord >= minOrd && ord <= maxOrd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float matchCost() {
|
|
||||||
return 2; // 2 comparisons
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
iterator =
|
|
||||||
new TwoPhaseIterator(values) {
|
|
||||||
@Override
|
|
||||||
public boolean matches() throws IOException {
|
|
||||||
for (int i = 0; i < values.docValueCount(); i++) {
|
|
||||||
long ord = values.nextOrd();
|
|
||||||
if (ord < minOrd) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Values are sorted, so the first ord that is >= minOrd is our best
|
|
||||||
// candidate
|
|
||||||
return ord <= maxOrd;
|
|
||||||
}
|
|
||||||
return false; // all ords were < minOrd
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float matchCost() {
|
|
||||||
return 2; // 2 comparisons
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (skipper != null) {
|
|
||||||
iterator = new DocValuesRangeIterator(iterator, skipper, minOrd, maxOrd, false);
|
|
||||||
}
|
|
||||||
return new ConstantScoreScorer(score(), scoreMode, iterator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -232,7 +156,6 @@ final class SortedSetDocValuesRangeQuery extends Query {
|
||||||
return values.cost();
|
return values.cost();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
**/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -241,69 +164,4 @@ final class SortedSetDocValuesRangeQuery extends Query {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private DocIdSetIterator getDocIdSetIteratorOrNullForPrimarySort(
|
|
||||||
LeafReader reader,
|
|
||||||
SortedDocValues sortedDocValues,
|
|
||||||
DocValuesSkipper skipper,
|
|
||||||
long minOrd,
|
|
||||||
long maxOrd)
|
|
||||||
throws IOException {
|
|
||||||
if (skipper.docCount() != reader.maxDoc()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final Sort indexSort = reader.getMetaData().sort();
|
|
||||||
if (indexSort == null
|
|
||||||
|| indexSort.getSort().length == 0
|
|
||||||
|| indexSort.getSort()[0].getField().equals(field) == false) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int minDocID;
|
|
||||||
final int maxDocID;
|
|
||||||
if (indexSort.getSort()[0].getReverse()) {
|
|
||||||
if (skipper.maxValue() <= maxOrd) {
|
|
||||||
minDocID = 0;
|
|
||||||
} else {
|
|
||||||
skipper.advance(Long.MIN_VALUE, maxOrd);
|
|
||||||
minDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l <= maxOrd);
|
|
||||||
}
|
|
||||||
if (skipper.minValue() >= minOrd) {
|
|
||||||
maxDocID = skipper.docCount();
|
|
||||||
} else {
|
|
||||||
skipper.advance(Long.MIN_VALUE, minOrd);
|
|
||||||
maxDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l < minOrd);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (skipper.minValue() >= minOrd) {
|
|
||||||
minDocID = 0;
|
|
||||||
} else {
|
|
||||||
skipper.advance(minOrd, Long.MAX_VALUE);
|
|
||||||
minDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l >= minOrd);
|
|
||||||
}
|
|
||||||
if (skipper.maxValue() <= maxOrd) {
|
|
||||||
maxDocID = skipper.docCount();
|
|
||||||
} else {
|
|
||||||
skipper.advance(maxOrd, Long.MAX_VALUE);
|
|
||||||
maxDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l > maxOrd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return minDocID == maxDocID
|
|
||||||
? DocIdSetIterator.empty()
|
|
||||||
: DocIdSetIterator.range(minDocID, maxDocID);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int nextDoc(int startDoc, SortedDocValues docValues, LongPredicate predicate)
|
|
||||||
throws IOException {
|
|
||||||
int doc = docValues.docID();
|
|
||||||
if (startDoc > doc) {
|
|
||||||
doc = docValues.advance(startDoc);
|
|
||||||
}
|
|
||||||
for (; doc < DocIdSetIterator.NO_MORE_DOCS; doc = docValues.nextDoc()) {
|
|
||||||
if (predicate.test(docValues.ordValue())) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ public final class DocValuesRewriteMethod extends MultiTermQuery.RewriteMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasGaps == false) {
|
if (hasGaps == false) {
|
||||||
return new SortedSetDocValuesRangeScorer(values, minOrd, maxOrd, scoreMode, score(), skipper);
|
return new SortedSetDocValuesRangeScorer(query.field, values, minOrd, maxOrd, scoreMode, score(), skipper, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
final SortedDocValues singleton = DocValues.unwrapSingleton(values);
|
final SortedDocValues singleton = DocValues.unwrapSingleton(values);
|
||||||
|
|
|
@ -1,22 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF 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.apache.lucene.search;
|
package org.apache.lucene.search;
|
||||||
|
|
||||||
import org.apache.lucene.document.DocValuesRangeIterator;
|
|
||||||
import org.apache.lucene.index.DocValues;
|
import org.apache.lucene.index.DocValues;
|
||||||
import org.apache.lucene.index.DocValuesSkipper;
|
import org.apache.lucene.index.DocValuesSkipper;
|
||||||
|
import org.apache.lucene.index.LeafReader;
|
||||||
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.SortedDocValues;
|
import org.apache.lucene.index.SortedDocValues;
|
||||||
import org.apache.lucene.index.SortedSetDocValues;
|
import org.apache.lucene.index.SortedSetDocValues;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.function.LongPredicate;
|
||||||
|
|
||||||
public class SortedSetDocValuesRangeScorer extends Scorer {
|
public class SortedSetDocValuesRangeScorer extends Scorer {
|
||||||
final Scorer delegate;
|
final Scorer delegate;
|
||||||
|
|
||||||
public SortedSetDocValuesRangeScorer(SortedSetDocValues values, long minOrd, long maxOrd, ScoreMode scoreMode, float score, DocValuesSkipper skipper) throws IOException {
|
public SortedSetDocValuesRangeScorer(
|
||||||
delegate = setupScorer(values, minOrd, maxOrd, scoreMode, score, skipper);
|
String field,
|
||||||
|
SortedSetDocValues values,
|
||||||
|
long minOrd,
|
||||||
|
long maxOrd,
|
||||||
|
ScoreMode scoreMode,
|
||||||
|
float score,
|
||||||
|
DocValuesSkipper skipper,
|
||||||
|
LeafReaderContext context) throws IOException {
|
||||||
|
delegate = setupScorer(field, values, minOrd, maxOrd, scoreMode, score, skipper, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scorer setupScorer(SortedSetDocValues values, long minOrd, long maxOrd, ScoreMode scoreMode, float score, DocValuesSkipper skipper) throws IOException {
|
static Scorer setupScorer(
|
||||||
|
String field,
|
||||||
|
SortedSetDocValues values,
|
||||||
|
long minOrd,
|
||||||
|
long maxOrd,
|
||||||
|
ScoreMode scoreMode,
|
||||||
|
float score,
|
||||||
|
DocValuesSkipper skipper,
|
||||||
|
LeafReaderContext context) throws IOException {
|
||||||
// no terms matched in this segment
|
// no terms matched in this segment
|
||||||
if (minOrd > maxOrd
|
if (minOrd > maxOrd
|
||||||
|| (skipper != null
|
|| (skipper != null
|
||||||
|
@ -24,9 +58,26 @@ public class SortedSetDocValuesRangeScorer extends Scorer {
|
||||||
return new ConstantScoreScorer(score, scoreMode, DocIdSetIterator.empty());
|
return new ConstantScoreScorer(score, scoreMode, DocIdSetIterator.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all terms matched in this segment
|
||||||
|
if (skipper != null
|
||||||
|
&& skipper.docCount() == context.reader().maxDoc()
|
||||||
|
&& skipper.minValue() >= minOrd
|
||||||
|
&& skipper.maxValue() <= maxOrd) {
|
||||||
|
return new ConstantScoreScorer(
|
||||||
|
score, scoreMode, DocIdSetIterator.all(skipper.docCount()));
|
||||||
|
}
|
||||||
|
|
||||||
final SortedDocValues singleton = DocValues.unwrapSingleton(values);
|
final SortedDocValues singleton = DocValues.unwrapSingleton(values);
|
||||||
TwoPhaseIterator iterator;
|
TwoPhaseIterator iterator;
|
||||||
if (singleton != null) {
|
if (singleton != null) {
|
||||||
|
if (skipper != null) {
|
||||||
|
final DocIdSetIterator psIterator =
|
||||||
|
getDocIdSetIteratorOrNullForPrimarySort(
|
||||||
|
context.reader(), field, singleton, skipper, minOrd, maxOrd);
|
||||||
|
if (psIterator != null) {
|
||||||
|
return new ConstantScoreScorer(score, scoreMode, psIterator);
|
||||||
|
}
|
||||||
|
}
|
||||||
iterator =
|
iterator =
|
||||||
new TwoPhaseIterator(singleton) {
|
new TwoPhaseIterator(singleton) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,7 +115,7 @@ public class SortedSetDocValuesRangeScorer extends Scorer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (skipper != null) {
|
if (skipper != null) {
|
||||||
iterator = new DocValuesRangeIterator(iterator, skipper, minOrd, maxOrd);
|
iterator = new DocValuesRangeIterator(iterator, skipper, minOrd, maxOrd, false);
|
||||||
}
|
}
|
||||||
return new ConstantScoreScorer(score, scoreMode, iterator);
|
return new ConstantScoreScorer(score, scoreMode, iterator);
|
||||||
}
|
}
|
||||||
|
@ -113,4 +164,70 @@ public class SortedSetDocValuesRangeScorer extends Scorer {
|
||||||
public Collection<ChildScorable> getChildren() throws IOException {
|
public Collection<ChildScorable> getChildren() throws IOException {
|
||||||
return delegate.getChildren();
|
return delegate.getChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DocIdSetIterator getDocIdSetIteratorOrNullForPrimarySort(
|
||||||
|
LeafReader reader,
|
||||||
|
String field,
|
||||||
|
SortedDocValues sortedDocValues,
|
||||||
|
DocValuesSkipper skipper,
|
||||||
|
long minOrd,
|
||||||
|
long maxOrd)
|
||||||
|
throws IOException {
|
||||||
|
if (skipper.docCount() != reader.maxDoc()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Sort indexSort = reader.getMetaData().getSort();
|
||||||
|
if (indexSort == null
|
||||||
|
|| indexSort.getSort().length == 0
|
||||||
|
|| indexSort.getSort()[0].getField().equals(field) == false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int minDocID;
|
||||||
|
final int maxDocID;
|
||||||
|
if (indexSort.getSort()[0].getReverse()) {
|
||||||
|
if (skipper.maxValue() <= maxOrd) {
|
||||||
|
minDocID = 0;
|
||||||
|
} else {
|
||||||
|
skipper.advance(Long.MIN_VALUE, maxOrd);
|
||||||
|
minDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l <= maxOrd);
|
||||||
|
}
|
||||||
|
if (skipper.minValue() >= minOrd) {
|
||||||
|
maxDocID = skipper.docCount();
|
||||||
|
} else {
|
||||||
|
skipper.advance(Long.MIN_VALUE, minOrd);
|
||||||
|
maxDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l < minOrd);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (skipper.minValue() >= minOrd) {
|
||||||
|
minDocID = 0;
|
||||||
|
} else {
|
||||||
|
skipper.advance(minOrd, Long.MAX_VALUE);
|
||||||
|
minDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l >= minOrd);
|
||||||
|
}
|
||||||
|
if (skipper.maxValue() <= maxOrd) {
|
||||||
|
maxDocID = skipper.docCount();
|
||||||
|
} else {
|
||||||
|
skipper.advance(maxOrd, Long.MAX_VALUE);
|
||||||
|
maxDocID = nextDoc(skipper.minDocID(0), sortedDocValues, l -> l > maxOrd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minDocID == maxDocID
|
||||||
|
? DocIdSetIterator.empty()
|
||||||
|
: DocIdSetIterator.range(minDocID, maxDocID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int nextDoc(int startDoc, SortedDocValues docValues, LongPredicate predicate)
|
||||||
|
throws IOException {
|
||||||
|
int doc = docValues.docID();
|
||||||
|
if (startDoc > doc) {
|
||||||
|
doc = docValues.advance(startDoc);
|
||||||
|
}
|
||||||
|
for (; doc < DocIdSetIterator.NO_MORE_DOCS; doc = docValues.nextDoc()) {
|
||||||
|
if (predicate.test(docValues.ordValue())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue