LUCENE-5529: Spatial RPT optimization to skip intersection test on redundant cells. Other small changes too.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1578868 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David Wayne Smiley 2014-03-18 13:31:02 +00:00
parent 7e8e19b7c0
commit 51235d2e2a
4 changed files with 20 additions and 17 deletions

View File

@ -157,6 +157,9 @@ Optimizations
* LUCENE-5515: Improved TopDocs#merge to create a merged ScoreDoc * LUCENE-5515: Improved TopDocs#merge to create a merged ScoreDoc
array with length of at most equal to the specified size instead of length array with length of at most equal to the specified size instead of length
equal to at most from + size as was before. (Martijn van Groningen) equal to at most from + size as was before. (Martijn van Groningen)
* LUCENE-5529: Spatial search of non-point indexed shapes should be a little
faster due to skipping intersection tests on redundant cells. (David Smiley)
Bug fixes Bug fixes

View File

@ -17,9 +17,7 @@ package org.apache.lucene.spatial.prefix;
* limitations under the License. * limitations under the License.
*/ */
import java.io.IOException; import com.spatial4j.core.shape.Shape;
import java.util.Iterator;
import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.TermsEnum; import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.DocIdSet;
@ -28,7 +26,9 @@ import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.util.Bits; import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.StringHelper; import org.apache.lucene.util.StringHelper;
import com.spatial4j.core.shape.Shape;
import java.io.IOException;
import java.util.Iterator;
/** /**
* Traverses a {@link SpatialPrefixTree} indexed field, using the template & * Traverses a {@link SpatialPrefixTree} indexed field, using the template &
@ -60,9 +60,7 @@ public abstract class AbstractVisitingPrefixTreeFilter extends AbstractPrefixTre
public boolean equals(Object o) { public boolean equals(Object o) {
if (!super.equals(o)) return false;//checks getClass == o.getClass & instanceof if (!super.equals(o)) return false;//checks getClass == o.getClass & instanceof
AbstractVisitingPrefixTreeFilter that = (AbstractVisitingPrefixTreeFilter) o; //Ignore prefixGridScanLevel as it is merely a tuning parameter.
if (prefixGridScanLevel != that.prefixGridScanLevel) return false;
return true; return true;
} }
@ -70,7 +68,6 @@ public abstract class AbstractVisitingPrefixTreeFilter extends AbstractPrefixTre
@Override @Override
public int hashCode() { public int hashCode() {
int result = super.hashCode(); int result = super.hashCode();
result = 31 * result + prefixGridScanLevel;
return result; return result;
} }
@ -90,7 +87,7 @@ public abstract class AbstractVisitingPrefixTreeFilter extends AbstractPrefixTre
* method then it's short-circuited until it finds one, at which point * method then it's short-circuited until it finds one, at which point
* {@link #visit(org.apache.lucene.spatial.prefix.tree.Cell)} is called. At * {@link #visit(org.apache.lucene.spatial.prefix.tree.Cell)} is called. At
* some depths, of the tree, the algorithm switches to a scanning mode that * some depths, of the tree, the algorithm switches to a scanning mode that
* finds calls {@link #visitScanned(org.apache.lucene.spatial.prefix.tree.Cell)} * calls {@link #visitScanned(org.apache.lucene.spatial.prefix.tree.Cell)}
* for each leaf cell found. * for each leaf cell found.
* *
* @lucene.internal * @lucene.internal
@ -218,7 +215,7 @@ public abstract class AbstractVisitingPrefixTreeFilter extends AbstractPrefixTre
if (hasIndexedLeaves && cell.getLevel() != 0) { if (hasIndexedLeaves && cell.getLevel() != 0) {
//If the next indexed term just adds a leaf marker ('+') to cell, //If the next indexed term just adds a leaf marker ('+') to cell,
// then add all of those docs // then add all of those docs
assert StringHelper.startsWith(thisTerm, curVNodeTerm); assert StringHelper.startsWith(thisTerm, curVNodeTerm);//TODO refactor to use method on curVNode.cell
scanCell = grid.getCell(thisTerm.bytes, thisTerm.offset, thisTerm.length, scanCell); scanCell = grid.getCell(thisTerm.bytes, thisTerm.offset, thisTerm.length, scanCell);
if (scanCell.getLevel() == cell.getLevel() && scanCell.isLeaf()) { if (scanCell.getLevel() == cell.getLevel() && scanCell.isLeaf()) {
visitLeaf(scanCell); visitLeaf(scanCell);
@ -268,15 +265,17 @@ public abstract class AbstractVisitingPrefixTreeFilter extends AbstractPrefixTre
*/ */
protected void scan(int scanDetailLevel) throws IOException { protected void scan(int scanDetailLevel) throws IOException {
for (; for (;
thisTerm != null && StringHelper.startsWith(thisTerm, curVNodeTerm); thisTerm != null && StringHelper.startsWith(thisTerm, curVNodeTerm);//TODO refactor to use method on curVNode.cell
thisTerm = termsEnum.next()) { thisTerm = termsEnum.next()) {
scanCell = grid.getCell(thisTerm.bytes, thisTerm.offset, thisTerm.length, scanCell); scanCell = grid.getCell(thisTerm.bytes, thisTerm.offset, thisTerm.length, scanCell);
int termLevel = scanCell.getLevel(); int termLevel = scanCell.getLevel();
if (termLevel > scanDetailLevel) if (termLevel < scanDetailLevel) {
continue; if (scanCell.isLeaf())
if (termLevel == scanDetailLevel || scanCell.isLeaf()) { visitScanned(scanCell);
visitScanned(scanCell); } else if (termLevel == scanDetailLevel) {
if (!scanCell.isLeaf())//LUCENE-5529
visitScanned(scanCell);
} }
}//term loop }//term loop
} }

View File

@ -61,7 +61,7 @@ public class TermQueryPrefixTreeStrategy extends PrefixTreeStrategy {
BytesRef[] terms = new BytesRef[cells.size()]; BytesRef[] terms = new BytesRef[cells.size()];
int i = 0; int i = 0;
for (Cell cell : cells) { for (Cell cell : cells) {
terms[i++] = new BytesRef(cell.getTokenString()); terms[i++] = new BytesRef(cell.getTokenString());//TODO use cell.getTokenBytes()
} }
return new TermsFilter(getFieldName(), terms); return new TermsFilter(getFieldName(), terms);
} }

View File

@ -228,7 +228,7 @@ public abstract class SpatialPrefixTree {
assert endToken.length() == detailLevel; assert endToken.length() == detailLevel;
List<Cell> cells = new ArrayList<>(detailLevel); List<Cell> cells = new ArrayList<>(detailLevel);
for (int i = 1; i < detailLevel; i++) { for (int i = 1; i < detailLevel; i++) {
cells.add(getCell(endToken.substring(0, i))); cells.add(getCell(endToken.substring(0, i)));//TODO refactor: add a cell.getParent()
} }
cells.add(cell); cells.add(cell);
return cells; return cells;
@ -236,6 +236,7 @@ public abstract class SpatialPrefixTree {
/** /**
* Will add the trailing leaf byte for leaves. This isn't particularly efficient. * Will add the trailing leaf byte for leaves. This isn't particularly efficient.
* @deprecated TODO remove; not used and not interesting, don't need collection in & out
*/ */
public static List<String> cellsToTokenStrings(Collection<Cell> cells) { public static List<String> cellsToTokenStrings(Collection<Cell> cells) {
List<String> tokens = new ArrayList<>((cells.size())); List<String> tokens = new ArrayList<>((cells.size()));