Skip to content

Commit

Permalink
migrate GraphDatabaseFacade.getNodesByLabelAndPropertyWithoutIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd committed Feb 2, 2018
1 parent 19ffc7c commit bc5bd8b
Showing 1 changed file with 101 additions and 49 deletions.
Expand Up @@ -27,9 +27,7 @@
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;


import org.neo4j.collection.primitive.PrimitiveLongCollections;
import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.function.Suppliers; import org.neo4j.function.Suppliers;
import org.neo4j.graphdb.ConstraintViolationException; import org.neo4j.graphdb.ConstraintViolationException;
import org.neo4j.graphdb.DependencyResolver; import org.neo4j.graphdb.DependencyResolver;
Expand Down Expand Up @@ -63,6 +61,7 @@
import org.neo4j.internal.kernel.api.NodeIndexCursor; import org.neo4j.internal.kernel.api.NodeIndexCursor;
import org.neo4j.internal.kernel.api.NodeLabelIndexCursor; import org.neo4j.internal.kernel.api.NodeLabelIndexCursor;
import org.neo4j.internal.kernel.api.NodeValueIndexCursor; import org.neo4j.internal.kernel.api.NodeValueIndexCursor;
import org.neo4j.internal.kernel.api.PropertyCursor;
import org.neo4j.internal.kernel.api.Read; import org.neo4j.internal.kernel.api.Read;
import org.neo4j.internal.kernel.api.RelationshipScanCursor; import org.neo4j.internal.kernel.api.RelationshipScanCursor;
import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.internal.kernel.api.TokenRead;
Expand All @@ -75,7 +74,6 @@
import org.neo4j.io.IOUtils; import org.neo4j.io.IOUtils;
import org.neo4j.kernel.GraphDatabaseQueryService; import org.neo4j.kernel.GraphDatabaseQueryService;
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.exceptions.Status;
Expand Down Expand Up @@ -652,9 +650,15 @@ private ResourceIterator<Node> nodesByLabelAndProperty( Label myLabel, String ke
private ResourceIterator<Node> getNodesByLabelAndPropertyWithoutIndex( int propertyId, Value value, private ResourceIterator<Node> getNodesByLabelAndPropertyWithoutIndex( int propertyId, Value value,
Statement statement, int labelId ) Statement statement, int labelId )
{ {
PrimitiveLongResourceIterator nodeIds = statement.readOperations().nodesGetForLabel( labelId ); KernelTransaction transaction = statementContext.getKernelTransactionBoundToThisThread( true );
return map2nodes( new PropertyValueFilteringNodeIdIterator( nodeIds, statement.readOperations(), propertyId, value ),
statement, nodeIds ); NodeLabelIndexCursor nodeLabelCursor = transaction.cursors().allocateNodeLabelIndexCursor();
NodeCursor nodeCursor = transaction.cursors().allocateNodeCursor();
PropertyCursor propertyCursor = transaction.cursors().allocatePropertyCursor();

transaction.dataRead().nodeLabelScan( labelId, nodeLabelCursor );

return new NodeLabelPropertyIterator( transaction.dataRead(), nodeLabelCursor, nodeCursor, propertyCursor, statement, propertyId, value );
} }


private ResourceIterator<Node> allNodesWithLabel( final Label myLabel ) private ResourceIterator<Node> allNodesWithLabel( final Label myLabel )
Expand Down Expand Up @@ -760,43 +764,73 @@ public String toString()
return spi.name() + " [" + getStoreDir() + "]"; return spi.name() + " [" + getStoreDir() + "]";
} }


private static class PropertyValueFilteringNodeIdIterator extends PrimitiveLongCollections.PrimitiveLongBaseIterator private class NodeLabelPropertyIterator extends PrefetchingNodeResourceIterator
{ {
private final PrimitiveLongIterator nodesWithLabel; private final Read read;
private final ReadOperations statement; private final NodeLabelIndexCursor nodeLabelCursor;
private final NodeCursor nodeCursor;
private final PropertyCursor propertyCursor;
private final int propertyKeyId; private final int propertyKeyId;
private final Value value; private final Value value;


PropertyValueFilteringNodeIdIterator( PrimitiveLongIterator nodesWithLabel, ReadOperations statement, NodeLabelPropertyIterator(
int propertyKeyId, Value value ) Read read,
NodeLabelIndexCursor nodeLabelCursor,
NodeCursor nodeCursor,
PropertyCursor propertyCursor,
Statement statement,
int propertyKeyId,
Value value )
{ {
this.nodesWithLabel = nodesWithLabel; super( statement );
this.statement = statement; this.read = read;
this.nodeLabelCursor = nodeLabelCursor;
this.nodeCursor = nodeCursor;
this.propertyCursor = propertyCursor;
this.propertyKeyId = propertyKeyId; this.propertyKeyId = propertyKeyId;
this.value = value; this.value = value;
} }


@Override @Override
protected boolean fetchNext() protected long fetchNext()
{ {
for ( boolean hasNext = nodesWithLabel.hasNext(); hasNext; hasNext = nodesWithLabel.hasNext() ) boolean hasNext;
do
{ {
long nextValue = nodesWithLabel.next(); hasNext = nodeLabelCursor.next();
try
} while ( hasNext && !hasPropertyWithValue() );

if ( hasNext )
{
return nodeLabelCursor.nodeReference();
}
else
{
close();
return NO_ID;
}
}

@Override
void closeResources( Statement statement )
{
IOUtils.closeAllSilently( statement, nodeLabelCursor, nodeCursor, propertyCursor );
}

private boolean hasPropertyWithValue()
{
read.singleNode( nodeLabelCursor.nodeReference(), nodeCursor );
if ( nodeCursor.next() )
{
nodeCursor.properties( propertyCursor );
while ( propertyCursor.next() )
{ {
Value propertyValue = statement.nodeGetProperty( nextValue, propertyKeyId ); if ( propertyCursor.propertyKey() == propertyKeyId && propertyCursor.propertyValue().equals( value ) )
if ( propertyValue != null )
{ {
if ( propertyValue.equals( value ) ) return true;
{
return next( nextValue );
}
} }
} }
catch ( EntityNotFoundException e )
{
// continue to the next node
}
} }
return false; return false;
} }
Expand Down Expand Up @@ -888,21 +922,48 @@ public GraphPropertiesProxy newGraphPropertiesProxy()
{ {
return new GraphPropertiesProxy( this ); return new GraphPropertiesProxy( this );
} }
private static final long UNINITIALIZED = -2L;
private static final long NO_ID = -1L;


private final class NodeCursorResourceIterator<CURSOR extends NodeIndexCursor> implements ResourceIterator<Node> private final class NodeCursorResourceIterator<CURSOR extends NodeIndexCursor> extends PrefetchingNodeResourceIterator
{ {

private final CURSOR cursor; private final CURSOR cursor;

NodeCursorResourceIterator( CURSOR cursor, Statement statement )
{
super( statement );
this.cursor = cursor;
}

long fetchNext()
{
if ( cursor.next() )
{
return cursor.nodeReference();
}
else
{
close();
return NO_ID;
}
}

@Override
void closeResources( Statement statement )
{
IOUtils.closeAllSilently( statement, cursor );
}
}

private abstract class PrefetchingNodeResourceIterator implements ResourceIterator<Node>
{
private final Statement statement; private final Statement statement;
private long next; private long next;
private boolean closed; private boolean closed;

private static final long NOT_INITIALIZED = -2L; private static final long NOT_INITIALIZED = -2L;
protected static final long NO_ID = -1L;


NodeCursorResourceIterator( CURSOR cursor, Statement statement ) PrefetchingNodeResourceIterator( Statement statement )
{ {
this.cursor = cursor;
this.statement = statement; this.statement = statement;
this.next = NOT_INITIALIZED; this.next = NOT_INITIALIZED;
} }
Expand All @@ -912,7 +973,7 @@ public boolean hasNext()
{ {
if ( next == NOT_INITIALIZED ) if ( next == NOT_INITIALIZED )
{ {
fetchNext(); next = fetchNext();
} }
return next != NO_ID; return next != NO_ID;
} }
Expand All @@ -926,31 +987,22 @@ public Node next()
throw new NoSuchElementException( ); throw new NoSuchElementException( );
} }
Node nodeProxy = newNodeProxy( next ); Node nodeProxy = newNodeProxy( next );
fetchNext(); next = fetchNext();
return nodeProxy; return nodeProxy;
} }


private void fetchNext()
{
if ( cursor.next() )
{
next = cursor.nodeReference();
}
else
{
close();
}
}

@Override
public void close() public void close()
{ {
if ( !closed ) if ( !closed )
{ {
next = NO_ID; next = NO_ID;
IOUtils.closeAllSilently( statement, cursor ); closeResources( statement );
closed = true; closed = true;
} }
} }

abstract long fetchNext();

abstract void closeResources( Statement statement );
} }
} }

0 comments on commit bc5bd8b

Please sign in to comment.