mirror of https://github.com/apache/lucene.git
LUCENE-6645: Remove BitDocIdSetBuilder from lucene-spatial as well.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1691335 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
05363e169d
commit
9342ddc392
lucene/spatial/src/java/org/apache/lucene/spatial
|
@ -38,9 +38,8 @@ import org.apache.lucene.search.Weight;
|
||||||
import org.apache.lucene.spatial.prefix.AbstractVisitingPrefixTreeFilter;
|
import org.apache.lucene.spatial.prefix.AbstractVisitingPrefixTreeFilter;
|
||||||
import org.apache.lucene.spatial.prefix.tree.Cell;
|
import org.apache.lucene.spatial.prefix.tree.Cell;
|
||||||
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
|
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
|
||||||
import org.apache.lucene.spatial.util.BitDocIdSetBuilder;
|
|
||||||
import org.apache.lucene.util.BitDocIdSet;
|
|
||||||
import org.apache.lucene.util.Bits;
|
import org.apache.lucene.util.Bits;
|
||||||
|
import org.apache.lucene.util.DocIdSetBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A spatial Intersects predicate that distinguishes an approximated match from an exact match based on which cells
|
* A spatial Intersects predicate that distinguishes an approximated match from an exact match based on which cells
|
||||||
|
@ -103,16 +102,16 @@ public class IntersectsRPTVerifyQuery extends Query {
|
||||||
if (approxDISI == null) {
|
if (approxDISI == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final Bits exactDocBits;
|
final DocIdSetIterator exactIterator;
|
||||||
if (result.exactDocIdSet != null) {
|
if (result.exactDocIdSet != null) {
|
||||||
// If both sets are the same, there's nothing to verify; we needn't return a TwoPhaseIterator
|
// If both sets are the same, there's nothing to verify; we needn't return a TwoPhaseIterator
|
||||||
if (result.approxDocIdSet.equals(result.exactDocIdSet)) {
|
if (result.approxDocIdSet == result.exactDocIdSet) {
|
||||||
return new ConstantScoreScorer(this, score(), approxDISI);
|
return new ConstantScoreScorer(this, score(), approxDISI);
|
||||||
}
|
}
|
||||||
exactDocBits = result.exactDocIdSet.bits();
|
exactIterator = result.exactDocIdSet.iterator();
|
||||||
assert exactDocBits != null;
|
assert exactIterator != null;
|
||||||
} else {
|
} else {
|
||||||
exactDocBits = null;
|
exactIterator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final FunctionValues predFuncValues = predicateValueSource.getValues(valueSourceContext, context);
|
final FunctionValues predFuncValues = predicateValueSource.getValues(valueSourceContext, context);
|
||||||
|
@ -120,11 +119,17 @@ public class IntersectsRPTVerifyQuery extends Query {
|
||||||
final TwoPhaseIterator twoPhaseIterator = new TwoPhaseIterator(approxDISI) {
|
final TwoPhaseIterator twoPhaseIterator = new TwoPhaseIterator(approxDISI) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches() throws IOException {
|
public boolean matches() throws IOException {
|
||||||
if (exactDocBits != null && exactDocBits.get(approxDISI.docID())) {
|
final int doc = approxDISI.docID();
|
||||||
return true;
|
if (exactIterator != null) {
|
||||||
|
if (exactIterator.docID() < doc) {
|
||||||
|
exactIterator.advance(doc);
|
||||||
|
}
|
||||||
|
if (exactIterator.docID() == doc) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return predFuncValues.boolVal(approxDISI.docID());
|
return predFuncValues.boolVal(doc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,10 +158,12 @@ public class IntersectsRPTVerifyQuery extends Query {
|
||||||
// TODO consider if IntersectsPrefixTreeFilter should simply do this and provide both sets
|
// TODO consider if IntersectsPrefixTreeFilter should simply do this and provide both sets
|
||||||
|
|
||||||
class IntersectsDifferentiatingVisitor extends VisitorTemplate {
|
class IntersectsDifferentiatingVisitor extends VisitorTemplate {
|
||||||
BitDocIdSetBuilder approxBuilder = new BitDocIdSetBuilder(maxDoc);
|
DocIdSetBuilder approxBuilder = new DocIdSetBuilder(maxDoc);
|
||||||
BitDocIdSetBuilder exactBuilder = new BitDocIdSetBuilder(maxDoc);
|
DocIdSetBuilder exactBuilder = new DocIdSetBuilder(maxDoc);
|
||||||
BitDocIdSet exactDocIdSet;
|
boolean approxIsEmpty = true;
|
||||||
BitDocIdSet approxDocIdSet;
|
boolean exactIsEmpty = true;
|
||||||
|
DocIdSet exactDocIdSet;
|
||||||
|
DocIdSet approxDocIdSet;
|
||||||
|
|
||||||
public IntersectsDifferentiatingVisitor(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
public IntersectsDifferentiatingVisitor(LeafReaderContext context, Bits acceptDocs) throws IOException {
|
||||||
super(context, acceptDocs);
|
super(context, acceptDocs);
|
||||||
|
@ -168,12 +175,16 @@ public class IntersectsRPTVerifyQuery extends Query {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DocIdSet finish() throws IOException {
|
protected DocIdSet finish() throws IOException {
|
||||||
exactDocIdSet = exactBuilder.build();
|
if (exactIsEmpty) {
|
||||||
if (approxBuilder.isDefinitelyEmpty()) {
|
exactDocIdSet = null;
|
||||||
|
} else {
|
||||||
|
exactDocIdSet = exactBuilder.build();
|
||||||
|
}
|
||||||
|
if (approxIsEmpty) {
|
||||||
approxDocIdSet = exactDocIdSet;//optimization
|
approxDocIdSet = exactDocIdSet;//optimization
|
||||||
} else {
|
} else {
|
||||||
if (exactDocIdSet != null) {
|
if (exactDocIdSet != null) {
|
||||||
approxBuilder.or(exactDocIdSet.iterator());
|
approxBuilder.add(exactDocIdSet.iterator());
|
||||||
}
|
}
|
||||||
approxDocIdSet = approxBuilder.build();
|
approxDocIdSet = approxBuilder.build();
|
||||||
}
|
}
|
||||||
|
@ -183,9 +194,11 @@ public class IntersectsRPTVerifyQuery extends Query {
|
||||||
@Override
|
@Override
|
||||||
protected boolean visitPrefix(Cell cell) throws IOException {
|
protected boolean visitPrefix(Cell cell) throws IOException {
|
||||||
if (cell.getShapeRel() == SpatialRelation.WITHIN) {
|
if (cell.getShapeRel() == SpatialRelation.WITHIN) {
|
||||||
|
exactIsEmpty = false;
|
||||||
collectDocs(exactBuilder);//note: we'll add exact to approx on finish()
|
collectDocs(exactBuilder);//note: we'll add exact to approx on finish()
|
||||||
return false;
|
return false;
|
||||||
} else if (cell.getLevel() == detailLevel) {
|
} else if (cell.getLevel() == detailLevel) {
|
||||||
|
approxIsEmpty = false;
|
||||||
collectDocs(approxBuilder);
|
collectDocs(approxBuilder);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -195,8 +208,10 @@ public class IntersectsRPTVerifyQuery extends Query {
|
||||||
@Override
|
@Override
|
||||||
protected void visitLeaf(Cell cell) throws IOException {
|
protected void visitLeaf(Cell cell) throws IOException {
|
||||||
if (cell.getShapeRel() == SpatialRelation.WITHIN) {
|
if (cell.getShapeRel() == SpatialRelation.WITHIN) {
|
||||||
|
exactIsEmpty = false;
|
||||||
collectDocs(exactBuilder);//note: we'll add exact to approx on finish()
|
collectDocs(exactBuilder);//note: we'll add exact to approx on finish()
|
||||||
} else {
|
} else {
|
||||||
|
approxIsEmpty = false;
|
||||||
collectDocs(approxBuilder);
|
collectDocs(approxBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.index.TermsEnum;
|
import org.apache.lucene.index.TermsEnum;
|
||||||
import org.apache.lucene.search.Filter;
|
import org.apache.lucene.search.Filter;
|
||||||
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
|
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
|
||||||
import org.apache.lucene.spatial.util.BitDocIdSetBuilder;
|
|
||||||
import org.apache.lucene.util.BitSet;
|
import org.apache.lucene.util.BitSet;
|
||||||
import org.apache.lucene.util.Bits;
|
import org.apache.lucene.util.Bits;
|
||||||
|
import org.apache.lucene.util.DocIdSetBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Lucene Filters on SpatialPrefixTree fields.
|
* Base class for Lucene Filters on SpatialPrefixTree fields.
|
||||||
|
@ -102,10 +102,10 @@ public abstract class AbstractPrefixTreeFilter extends Filter {
|
||||||
bitSet.or(wrap(postingsEnum, acceptDocs));
|
bitSet.or(wrap(postingsEnum, acceptDocs));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void collectDocs(BitDocIdSetBuilder bitSetBuilder) throws IOException {
|
protected void collectDocs(DocIdSetBuilder docSetBuilder) throws IOException {
|
||||||
assert termsEnum != null;
|
assert termsEnum != null;
|
||||||
postingsEnum = termsEnum.postings(postingsEnum, PostingsEnum.NONE);
|
postingsEnum = termsEnum.postings(postingsEnum, PostingsEnum.NONE);
|
||||||
bitSetBuilder.or(wrap(postingsEnum, acceptDocs));
|
docSetBuilder.add(wrap(postingsEnum, acceptDocs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
package org.apache.lucene.spatial.util;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.lucene.search.DocIdSet;
|
|
||||||
import org.apache.lucene.search.DocIdSetIterator;
|
|
||||||
import org.apache.lucene.util.BitDocIdSet;
|
|
||||||
import org.apache.lucene.util.BitSetIterator;
|
|
||||||
import org.apache.lucene.util.FixedBitSet;
|
|
||||||
import org.apache.lucene.util.SparseFixedBitSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder of {@link DocIdSet}s that supports random access.
|
|
||||||
* @lucene.internal
|
|
||||||
*/
|
|
||||||
public final class BitDocIdSetBuilder {
|
|
||||||
|
|
||||||
private final int maxDoc;
|
|
||||||
private final int threshold;
|
|
||||||
private SparseFixedBitSet sparseSet;
|
|
||||||
private FixedBitSet denseSet;
|
|
||||||
|
|
||||||
// we cache an upper bound of the cost of this builder so that we don't have
|
|
||||||
// to re-compute approximateCardinality on the sparse set every time
|
|
||||||
private long costUpperBound;
|
|
||||||
|
|
||||||
/** Create a new empty instance. */
|
|
||||||
public BitDocIdSetBuilder(int maxDoc) {
|
|
||||||
this.maxDoc = maxDoc;
|
|
||||||
threshold = maxDoc >>> 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pkg-private for testing
|
|
||||||
boolean dense() {
|
|
||||||
return denseSet != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this builder definitely empty? If so, {@link #build()} will return null. This is usually the same as
|
|
||||||
* simply being empty but if this builder was constructed with the {@code full} option or if an iterator was passed
|
|
||||||
* that iterated over no documents, then we're not sure.
|
|
||||||
*/
|
|
||||||
public boolean isDefinitelyEmpty() {
|
|
||||||
return sparseSet == null && denseSet == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the content of the provided {@link DocIdSetIterator} to this builder.
|
|
||||||
*/
|
|
||||||
public void or(DocIdSetIterator it) throws IOException {
|
|
||||||
if (denseSet != null) {
|
|
||||||
// already upgraded
|
|
||||||
denseSet.or(it);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final long itCost = it.cost();
|
|
||||||
costUpperBound += itCost;
|
|
||||||
if (costUpperBound >= threshold) {
|
|
||||||
costUpperBound = (sparseSet == null ? 0 : sparseSet.approximateCardinality()) + itCost;
|
|
||||||
|
|
||||||
if (costUpperBound >= threshold) {
|
|
||||||
// upgrade
|
|
||||||
denseSet = new FixedBitSet(maxDoc);
|
|
||||||
denseSet.or(it);
|
|
||||||
if (sparseSet != null) {
|
|
||||||
denseSet.or(new BitSetIterator(sparseSet, 0L));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we are still sparse
|
|
||||||
if (sparseSet == null) {
|
|
||||||
sparseSet = new SparseFixedBitSet(maxDoc);
|
|
||||||
}
|
|
||||||
sparseSet.or(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a {@link DocIdSet} that contains all doc ids that have been added.
|
|
||||||
* This method may return <tt>null</tt> if no documents were addded to this
|
|
||||||
* builder.
|
|
||||||
* NOTE: this is a destructive operation, the builder should not be used
|
|
||||||
* anymore after this method has been called.
|
|
||||||
*/
|
|
||||||
public BitDocIdSet build() {
|
|
||||||
final BitDocIdSet result;
|
|
||||||
if (denseSet != null) {
|
|
||||||
result = new BitDocIdSet(denseSet);
|
|
||||||
} else if (sparseSet != null) {
|
|
||||||
result = new BitDocIdSet(sparseSet);
|
|
||||||
} else {
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
denseSet = null;
|
|
||||||
sparseSet = null;
|
|
||||||
costUpperBound = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue