diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/schema/BridgingIndexProgressor.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/schema/BridgingIndexProgressor.java new file mode 100644 index 0000000000000..e988ef8a3b676 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/schema/BridgingIndexProgressor.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002-2018 "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.impl.api.schema; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.neo4j.internal.kernel.api.IndexQuery; +import org.neo4j.kernel.api.schema.index.IndexDescriptor; +import org.neo4j.storageengine.api.schema.IndexProgressor; +import org.neo4j.values.storable.Value; + +/** + * Combine multiple progressor to act like one single logical progressor seen from client's perspective. + */ +public class BridgingIndexProgressor implements IndexProgressor.NodeValueClient, IndexProgressor +{ + private final NodeValueClient client; + private final int[] keys; + // This is a thread-safe queue because it can be used in parallel scenarios. + // The overhead of a concurrent queue in this case is negligable since typically there will be two or a very few number + // of progressors and each progressor has many results each + private final Queue progressors = new ConcurrentLinkedQueue<>(); + private IndexProgressor current; + + public BridgingIndexProgressor( NodeValueClient client, int[] keys ) + { + this.client = client; + this.keys = keys; + } + + @Override + public boolean next() + { + if ( current == null ) + { + current = progressors.poll(); + } + while ( current != null ) + { + if ( current.next() ) + { + return true; + } + else + { + current.close(); + current = progressors.poll(); + } + } + return false; + } + + @Override + public boolean needsValues() + { + return client.needsValues(); + } + + @Override + public void close() + { + progressors.forEach( IndexProgressor::close ); + } + + @Override + public void initialize( IndexDescriptor descriptor, IndexProgressor progressor, IndexQuery[] queries ) + { + assertKeysAlign( descriptor.schema().getPropertyIds() ); + progressors.add( progressor ); + } + + private void assertKeysAlign( int[] keys ) + { + for ( int i = 0; i < this.keys.length; i++ ) + { + if ( this.keys[i] != keys[i] ) + { + throw new UnsupportedOperationException( "Can not chain multiple progressors with different key set." ); + } + } + } + + @Override + public boolean acceptNode( long reference, Value[] values ) + { + return client.acceptNode( reference, values ); + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java index f67dfa6b09b64..0466430e14ee2 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/index/schema/fusion/FusionIndexReader.java @@ -19,9 +19,7 @@ */ package org.neo4j.kernel.impl.index.schema.fusion; -import java.util.ArrayDeque; import java.util.Arrays; -import java.util.Queue; import org.neo4j.collection.primitive.PrimitiveLongResourceCollections; import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; @@ -32,6 +30,7 @@ import org.neo4j.internal.kernel.api.IndexQuery.NumberRangePredicate; import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; import org.neo4j.kernel.api.schema.index.IndexDescriptor; +import org.neo4j.kernel.impl.api.schema.BridgingIndexProgressor; import org.neo4j.kernel.impl.index.schema.fusion.FusionSchemaIndexProvider.Selector; import org.neo4j.storageengine.api.schema.IndexProgressor; import org.neo4j.storageengine.api.schema.IndexReader; @@ -172,80 +171,4 @@ public boolean hasFullNumberPrecision( IndexQuery... predicates ) } return predicates[0] instanceof NumberRangePredicate && nativeReader.hasFullNumberPrecision( predicates ); } - - /** - * Combine multiple progressor to act like one single logical progressor seen from clients perspective. - */ - private static class BridgingIndexProgressor implements IndexProgressor.NodeValueClient, IndexProgressor - { - private final NodeValueClient client; - private final int[] keys; - private final Queue progressors; - private IndexProgressor current; - - BridgingIndexProgressor( NodeValueClient client, int[] keys ) - { - this.client = client; - this.keys = keys; - progressors = new ArrayDeque<>(); - } - - @Override - public boolean next() - { - if ( current == null ) - { - current = progressors.poll(); - } - while ( current != null ) - { - if ( current.next() ) - { - return true; - } - else - { - current.close(); - current = progressors.poll(); - } - } - return false; - } - - @Override - public boolean needsValues() - { - return client.needsValues(); - } - - @Override - public void close() - { - progressors.forEach( IndexProgressor::close ); - } - - @Override - public void initialize( IndexDescriptor descriptor, IndexProgressor progressor, IndexQuery[] queries ) - { - assertKeysAlign( descriptor.schema().getPropertyIds() ); - progressors.add( progressor ); - } - - private void assertKeysAlign( int[] keys ) - { - for ( int i = 0; i < this.keys.length; i++ ) - { - if ( this.keys[i] != keys[i] ) - { - throw new UnsupportedOperationException( "Can not chain multiple progressors with different key set." ); - } - } - } - - @Override - public boolean acceptNode( long reference, Value[] values ) - { - return client.acceptNode( reference, values ); - } - } } diff --git a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/DocValuesCollector.java b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/DocValuesCollector.java index 862cf93330f71..892285b206300 100644 --- a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/DocValuesCollector.java +++ b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/DocValuesCollector.java @@ -48,6 +48,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; import org.neo4j.graphdb.index.IndexHits; @@ -55,6 +56,8 @@ import org.neo4j.helpers.collection.PrefetchingIterator; import org.neo4j.index.impl.lucene.explicit.EmptyIndexHits; import org.neo4j.kernel.impl.api.explicitindex.AbstractIndexHits; +import org.neo4j.storageengine.api.schema.IndexProgressor; +import org.neo4j.values.storable.Value; /** * Collector to record per-segment {@code DocIdSet}s and {@code LeafReaderContext}s for every @@ -102,6 +105,11 @@ public LongValuesIterator getValuesIterator( String field ) return new LongValuesIterator( getMatchingDocs(), getTotalHits(), field ); } + public IndexProgressor getIndexProgressor( String field, IndexProgressor.NodeValueClient client ) + { + return new LongValuesIndexProgressor( getMatchingDocs(), getTotalHits(), field, client ); + } + /** * @param field the field that contains the values * @param sort how the results should be sorted @@ -312,6 +320,92 @@ private void replayTo( Collector collector ) throws IOException } } + /** + * Iterates over all per-segment {@link DocValuesCollector.MatchingDocs}. + * Provides base functionality for extracting entity ids and other values from documents. + */ + private abstract static class LongValuesSource + { + private final Iterator matchingDocs; + private final String field; + final int totalHits; + final Map docValuesCache; + + DocIdSetIterator currentIdIterator; + NumericDocValues currentDocValues; + DocValuesCollector.MatchingDocs currentDocs; + int index; + long next; + + LongValuesSource( Iterable allMatchingDocs, int totalHits, String field ) + { + this.totalHits = totalHits; + this.field = field; + matchingDocs = allMatchingDocs.iterator(); + docValuesCache = new HashMap<>(); + } + + /** + * @return true if it was able to make sure, that currentDisi is valid + */ + boolean ensureValidDisi() + { + try + { + while ( currentIdIterator == null ) + { + if ( matchingDocs.hasNext() ) + { + currentDocs = matchingDocs.next(); + currentIdIterator = currentDocs.docIdSet.iterator(); + if ( currentIdIterator != null ) + { + docValuesCache.clear(); + currentDocValues = currentDocs.readDocValues( field ); + } + } + else + { + return false; + } + } + return true; + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + boolean fetchNextEntityId() + { + try + { + if ( ensureValidDisi() ) + { + int nextDoc = currentIdIterator.nextDoc(); + if ( nextDoc != DocIdSetIterator.NO_MORE_DOCS ) + { + index++; + next = currentDocValues.get( nextDoc ); + return true; + } + else + { + currentIdIterator = null; + return fetchNextEntityId(); + } + } + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + + return false; + } + } + /** * Iterates over all per-segment {@link DocValuesCollector.MatchingDocs}. Supports two kinds of lookups. * One, iterate over all long values of the given field (constructor argument). @@ -323,14 +417,10 @@ private void replayTo( Collector collector ) throws IOException * is crossed; one thread might think it is reading from one segment while another thread has * already advanced this Iterator to the next segment, having raced the first thread. */ - public static class LongValuesIterator extends ValuesIterator implements PrimitiveLongResourceIterator + public static class LongValuesIterator extends LongValuesSource implements ValuesIterator, PrimitiveLongResourceIterator { - private final Iterator matchingDocs; - private final String field; - private DocIdSetIterator currentIdIterator; - private NumericDocValues currentDocValues; - private DocValuesCollector.MatchingDocs currentDocs; - private final Map docValuesCache; + private boolean hasNext; + private boolean hasNextDecided; /** * @param allMatchingDocs all {@link DocValuesCollector.MatchingDocs} across all segments @@ -339,10 +429,7 @@ public static class LongValuesIterator extends ValuesIterator implements Primiti */ public LongValuesIterator( Iterable allMatchingDocs, int totalHits, String field ) { - super( totalHits ); - this.field = field; - matchingDocs = allMatchingDocs.iterator(); - docValuesCache = new HashMap<>(); + super( allMatchingDocs, totalHits, field ); } @Override @@ -382,69 +469,67 @@ public long getValue( String field ) } @Override - protected boolean fetchNext() + public boolean hasNext() { - try + if ( !hasNextDecided ) { - if ( ensureValidDisi() ) - { - int nextDoc = currentIdIterator.nextDoc(); - if ( nextDoc != DocIdSetIterator.NO_MORE_DOCS ) - { - index++; - return next( currentDocValues.get( nextDoc ) ); - } - else - { - currentIdIterator = null; - return fetchNext(); - } - } + hasNext = fetchNextEntityId(); + hasNextDecided = true; } - catch ( IOException e ) + return hasNext; + } + + @Override + public long next() + { + if ( !hasNext() ) { - throw new RuntimeException( e ); + throw new NoSuchElementException(); } + hasNextDecided = false; + return next; + } - return false; + @Override + public int remaining() + { + return totalHits - index; } - /** - * @return true if it was able to make sure, that currentDisi is valid - */ - private boolean ensureValidDisi() + @Override + public void close() { - try + // nothing to close + } + } + + private static class LongValuesIndexProgressor extends LongValuesSource implements IndexProgressor + { + private final NodeValueClient client; + + LongValuesIndexProgressor( Iterable allMatchingDocs, int totalHits, String field, NodeValueClient client ) + { + super( allMatchingDocs, totalHits, field ); + this.client = client; + } + + @Override + public boolean next() + { + while ( fetchNextEntityId() ) { - while ( currentIdIterator == null ) + if ( client.acceptNode( next, (Value[]) null ) ) { - if ( matchingDocs.hasNext() ) - { - currentDocs = matchingDocs.next(); - currentIdIterator = currentDocs.docIdSet.iterator(); - if ( currentIdIterator != null ) - { - docValuesCache.clear(); - currentDocValues = currentDocs.readDocValues( field ); - } - } - else - { - return false; - } + return true; } - return true; - } - catch ( IOException e ) - { - throw new RuntimeException( e ); } + return false; } @Override public void close() { - //nothing to close + // nothing to close } } @@ -761,7 +846,7 @@ private void updateCurrentDocument( int docID, LeafReader reader ) } } - private static final class TopDocsValuesIterator extends ValuesIterator + private static final class TopDocsValuesIterator extends ValuesIterator.Adapter { private final ScoreDocsIterator scoreDocs; private final String field; diff --git a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/ValuesIterator.java b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/ValuesIterator.java index 9d4bd0153f18f..3085f38c0d31f 100644 --- a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/ValuesIterator.java +++ b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/index/collector/ValuesIterator.java @@ -20,22 +20,20 @@ package org.neo4j.kernel.api.impl.index.collector; import org.neo4j.collection.primitive.PrimitiveLongCollections; +import org.neo4j.collection.primitive.PrimitiveLongIterator; /** * Document values iterators that are primitive long iterators that can access value by field from document * and provides information about how many items remains in the underlying source. */ -public abstract class ValuesIterator extends PrimitiveLongCollections.PrimitiveLongBaseIterator - implements DocValuesAccess +public interface ValuesIterator extends PrimitiveLongIterator, DocValuesAccess { - public static final ValuesIterator EMPTY = new ValuesIterator( 0 ) - { - @Override - public int remaining() - { - return 0; - } + int remaining(); + + float currentScore(); + ValuesIterator EMPTY = new ValuesIterator.Adapter( 0 ) + { @Override protected boolean fetchNext() { @@ -61,25 +59,29 @@ public long getValue( String field ) } }; - protected final int size; - protected int index; + abstract class Adapter extends PrimitiveLongCollections.PrimitiveLongBaseIterator implements ValuesIterator + { + protected final int size; + protected int index; - /** - * Gets the score for the current iterator position. - * @return The score of the value, or 0 if scoring is not kept or applicable. - */ - public abstract float currentScore(); + /** + * Gets the score for the current iterator position. + * + * @return The score of the value, or 0 if scoring is not kept or applicable. + */ + public abstract float currentScore(); - ValuesIterator( int size ) - { - this.size = size; - } + Adapter( int size ) + { + this.size = size; + } - /** - * @return the number of docs left in this iterator. - */ - public int remaining() - { - return size - index; + /** + * @return the number of docs left in this iterator. + */ + public int remaining() + { + return size - index; + } } } diff --git a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/PartitionedIndexReader.java b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/PartitionedIndexReader.java index 1c5457e38eaed..1e95ecd94f015 100644 --- a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/PartitionedIndexReader.java +++ b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/PartitionedIndexReader.java @@ -27,14 +27,17 @@ import org.neo4j.collection.primitive.PrimitiveLongResourceCollections; import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; import org.neo4j.helpers.TaskCoordinator; +import org.neo4j.internal.kernel.api.IndexOrder; +import org.neo4j.internal.kernel.api.IndexQuery; import org.neo4j.io.IOUtils; import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; import org.neo4j.kernel.api.impl.index.partition.PartitionSearcher; import org.neo4j.kernel.api.impl.index.sampler.AggregatingIndexSampler; -import org.neo4j.internal.kernel.api.IndexQuery; import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; +import org.neo4j.kernel.impl.api.schema.BridgingIndexProgressor; import org.neo4j.storageengine.api.schema.AbstractIndexReader; +import org.neo4j.storageengine.api.schema.IndexProgressor; import org.neo4j.storageengine.api.schema.IndexReader; import org.neo4j.storageengine.api.schema.IndexSampler; import org.neo4j.values.storable.Value; @@ -80,6 +83,31 @@ public PrimitiveLongResourceIterator query( IndexQuery... predicates ) throws In } } + @Override + public void query( IndexProgressor.NodeValueClient client, IndexOrder indexOrder, IndexQuery... query ) throws IndexNotApplicableKernelException + { + try + { + BridgingIndexProgressor bridgingIndexProgressor = new BridgingIndexProgressor( client, descriptor.schema().getPropertyIds() ); + indexReaders.parallelStream().forEach( reader -> + { + try + { + reader.query( bridgingIndexProgressor, indexOrder, query ); + } + catch ( IndexNotApplicableKernelException e ) + { + throw new InnerException( e ); + } + } ); + client.initialize( descriptor, bridgingIndexProgressor, query ); + } + catch ( InnerException e ) + { + throw e.getCause(); + } + } + @Override public boolean hasFullNumberPrecision( IndexQuery... predicates ) { diff --git a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/SimpleIndexReader.java b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/SimpleIndexReader.java index de1ef8162e4e0..88492a3c6bdb5 100644 --- a/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/SimpleIndexReader.java +++ b/community/lucene-index/src/main/java/org/neo4j/kernel/api/impl/schema/reader/SimpleIndexReader.java @@ -32,6 +32,7 @@ import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; import org.neo4j.helpers.TaskControl; import org.neo4j.helpers.TaskCoordinator; +import org.neo4j.internal.kernel.api.IndexOrder; import org.neo4j.internal.kernel.api.IndexQuery; import org.neo4j.internal.kernel.api.IndexQuery.IndexQueryType; import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; @@ -43,6 +44,7 @@ import org.neo4j.kernel.api.schema.index.IndexDescriptor; import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig; import org.neo4j.storageengine.api.schema.AbstractIndexReader; +import org.neo4j.storageengine.api.schema.IndexProgressor; import org.neo4j.storageengine.api.schema.IndexSampler; import org.neo4j.values.storable.Value; @@ -88,8 +90,35 @@ public IndexSampler createSampler() } } + @Override + public void query( IndexProgressor.NodeValueClient client, IndexOrder indexOrder, IndexQuery... predicates ) throws IndexNotApplicableKernelException + { + Query query = toLuceneQuery( predicates ); + client.initialize( descriptor, search( query ).getIndexProgressor( NODE_ID_KEY, client ), predicates ); + } + @Override public PrimitiveLongResourceIterator query( IndexQuery... predicates ) throws IndexNotApplicableKernelException + { + Query query = toLuceneQuery( predicates ); + return search( query ).getValuesIterator( NODE_ID_KEY ); + } + + private DocValuesCollector search( Query query ) + { + try + { + DocValuesCollector docValuesCollector = new DocValuesCollector(); + getIndexSearcher().search( query, docValuesCollector ); + return docValuesCollector; + } + catch ( IOException e ) + { + throw new RuntimeException( e ); + } + } + + private Query toLuceneQuery( IndexQuery... predicates ) throws IndexNotApplicableKernelException { IndexQuery predicate = predicates[0]; switch ( predicate.type() ) @@ -102,7 +131,7 @@ public PrimitiveLongResourceIterator query( IndexQuery... predicates ) throws In "Exact followed by another query predicate type is not supported at this moment."; values[i] = ((IndexQuery.ExactPredicate) predicates[i]).value(); } - return seek( values ); + return LuceneDocumentStructure.newSeekQuery( values ); case exists: for ( IndexQuery p : predicates ) { @@ -112,27 +141,27 @@ public PrimitiveLongResourceIterator query( IndexQuery... predicates ) throws In "Exists followed by another query predicate type is not supported." ); } } - return scan(); + return LuceneDocumentStructure.newScanQuery(); case rangeNumeric: assertNotComposite( predicates ); IndexQuery.NumberRangePredicate np = (IndexQuery.NumberRangePredicate) predicate; - return rangeSeekByNumberInclusive( np.from(), np.to() ); + return LuceneDocumentStructure.newInclusiveNumericRangeSeekQuery( np.from(), np.to() ); case rangeString: assertNotComposite( predicates ); IndexQuery.StringRangePredicate sp = (IndexQuery.StringRangePredicate) predicate; - return rangeSeekByString( sp.from(), sp.fromInclusive(), sp.to(), sp.toInclusive() ); + return LuceneDocumentStructure.newRangeSeekByStringQuery( sp.from(), sp.fromInclusive(), sp.to(), sp.toInclusive() ); case stringPrefix: assertNotComposite( predicates ); IndexQuery.StringPrefixPredicate spp = (IndexQuery.StringPrefixPredicate) predicate; - return rangeSeekByPrefix( spp.prefix() ); + return LuceneDocumentStructure.newRangeSeekByPrefixQuery( spp.prefix() ); case stringContains: assertNotComposite( predicates ); IndexQuery.StringContainsPredicate scp = (IndexQuery.StringContainsPredicate) predicate; - return containsString( scp.contains() ); + return LuceneDocumentStructure.newWildCardStringQuery( scp.contains() ); case stringSuffix: assertNotComposite( predicates ); IndexQuery.StringSuffixPredicate ssp = (IndexQuery.StringSuffixPredicate) predicate; - return endsWith( ssp.suffix() ); + return LuceneDocumentStructure.newSuffixStringQuery( ssp.suffix() ); default: // todo figure out a more specific exception throw new RuntimeException( "Index query not supported: " + Arrays.toString( predicates ) ); @@ -150,42 +179,6 @@ private void assertNotComposite( IndexQuery[] predicates ) assert predicates.length == 1 : "composite indexes not yet supported for this operation"; } - private PrimitiveLongResourceIterator seek( Value... values ) - { - return query( LuceneDocumentStructure.newSeekQuery( values ) ); - } - - private PrimitiveLongResourceIterator rangeSeekByNumberInclusive( Number lower, Number upper ) - { - return query( LuceneDocumentStructure.newInclusiveNumericRangeSeekQuery( lower, upper ) ); - } - - private PrimitiveLongResourceIterator rangeSeekByString( String lower, boolean includeLower, - String upper, boolean includeUpper ) - { - return query( LuceneDocumentStructure.newRangeSeekByStringQuery( lower, includeLower, upper, includeUpper ) ); - } - - private PrimitiveLongResourceIterator rangeSeekByPrefix( String prefix ) - { - return query( LuceneDocumentStructure.newRangeSeekByPrefixQuery( prefix ) ); - } - - private PrimitiveLongResourceIterator scan() - { - return query( LuceneDocumentStructure.newScanQuery() ); - } - - private PrimitiveLongResourceIterator containsString( String exactTerm ) - { - return query( LuceneDocumentStructure.newWildCardStringQuery( exactTerm ) ); - } - - private PrimitiveLongResourceIterator endsWith( String suffix ) - { - return query( LuceneDocumentStructure.newSuffixStringQuery( suffix ) ); - } - @Override public long countIndexedNodes( long nodeId, Value... propertyValues ) { @@ -220,20 +213,6 @@ public void close() } } - protected PrimitiveLongResourceIterator query( Query query ) - { - try - { - DocValuesCollector docValuesCollector = new DocValuesCollector(); - getIndexSearcher().search( query, docValuesCollector ); - return docValuesCollector.getValuesIterator( NODE_ID_KEY ); - } - catch ( IOException e ) - { - throw new RuntimeException( e ); - } - } - private IndexSearcher getIndexSearcher() { return partitionSearcher.getIndexSearcher();