diff --git a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/FirstHitCollector.java b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/FirstHitCollector.java new file mode 100644 index 0000000000000..a53e48b955b4e --- /dev/null +++ b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/FirstHitCollector.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.api.impl.index; + +import org.apache.lucene.search.CollectionTerminatedException; +import org.apache.lucene.search.SimpleCollector; + +import java.io.IOException; + +/** + * A {@code Collector} that terminates the collection after the very first hit. + * As a consequence, additional collectors in this search that require a complete run over the index, + * such as {@code TotalHitCountCollector} or {@link DocValuesCollector}, won't work as expected. + */ +public final class FirstHitCollector extends SimpleCollector +{ + public static final int NO_MATCH = -1; + + private int result = NO_MATCH; + + /** + * @return true when this collector got a match, otherwise false. + */ + public boolean hasMatched() + { + return result != NO_MATCH; + } + + /** + * @return the docId if this collector got a match, otherwise {@link FirstHitCollector#NO_MATCH}. + */ + public int getMatchedDoc() + { + return result; + } + + @Override + public void collect( int doc ) throws IOException + { + result = doc; + throw new CollectionTerminatedException(); + } + + @Override + public boolean needsScores() + { + return false; + } +} diff --git a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/LuceneLabelScanWriter.java b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/LuceneLabelScanWriter.java index 5b223e9decabe..5627422f5f3a4 100644 --- a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/LuceneLabelScanWriter.java +++ b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/LuceneLabelScanWriter.java @@ -24,7 +24,6 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.TopDocs; import java.io.IOException; import java.util.ArrayList; @@ -110,12 +109,14 @@ public void close() throws IOException private Map readLabelBitMapsInRange( IndexSearcher searcher, long range ) throws IOException { - Map fields = new HashMap<>(); + Map fields = new HashMap<>(); Term documentTerm = format.rangeTerm( range ); - TopDocs docs = searcher.search( new TermQuery( documentTerm ), 1 ); - if ( docs != null && docs.totalHits != 0 ) + TermQuery query = new TermQuery( documentTerm ); + FirstHitCollector hitCollector = new FirstHitCollector(); + searcher.search( query, hitCollector ); + if ( hitCollector.hasMatched() ) { - Document document = searcher.doc( docs.scoreDocs[0].doc ); + Document document = searcher.doc( hitCollector.getMatchedDoc() ); for ( IndexableField field : document.getFields() ) { if ( !format.isRangeField( field ) )