Skip to content

Commit

Permalink
Improved on documentation and layout of NodeValueIndexCursorTestBase
Browse files Browse the repository at this point in the history
  • Loading branch information
burqen authored and tinwelint committed Feb 6, 2019
1 parent a2a903f commit 9adc863
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 69 deletions.
Expand Up @@ -19,14 +19,22 @@
*/
package org.neo4j.kernel.impl.newapi;

import org.neo4j.gis.spatial.index.curves.SpaceFillingCurve;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.internal.kernel.api.NodeValueIndexCursorTestBase;
import org.neo4j.internal.kernel.api.SchemaWrite;
import org.neo4j.internal.kernel.api.TokenWrite;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.schema.SchemaDescriptorFactory;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge;
import org.neo4j.kernel.impl.index.schema.config.ConfiguredSpaceFillingCurveSettingsCache;
import org.neo4j.kernel.impl.index.schema.config.SpaceFillingCurveSettings;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.values.storable.CoordinateReferenceSystem;
import org.neo4j.values.storable.PointValue;

import static org.junit.Assert.assertEquals;

abstract class AbstractNodeValueIndexCursorTest extends NodeValueIndexCursorTestBase<ReadTestSupport>
{
Expand All @@ -45,4 +53,13 @@ protected void createCompositeIndex( GraphDatabaseService graphDb, String label,
token.propertyKeyGetOrCreateForName( "firstname" ),
token.propertyKeyGetOrCreateForName( "surname" ) ) );
}

@Override
protected void assertSameDerivedValue( PointValue p1, PointValue p2 )
{
ConfiguredSpaceFillingCurveSettingsCache settingsFactory = new ConfiguredSpaceFillingCurveSettingsCache( Config.defaults() );
SpaceFillingCurveSettings spaceFillingCurveSettings = settingsFactory.forCRS( CoordinateReferenceSystem.WGS84 );
SpaceFillingCurve curve = spaceFillingCurveSettings.curve();
assertEquals( curve.derivedValueFor( p1.coordinate() ), curve.derivedValueFor( p2.coordinate() ) );
}
}
Expand Up @@ -45,8 +45,16 @@ void nodeIndexSeek( IndexReference index, NodeValueIndexCursor cursor, IndexOrde
throws KernelException;

/**
* Access all distinct counts in an index. Entries fed to the {@code cursor} will be (count,Value[]).
* For merely counting distinct values in an index, loop over and sum all counts.
* Access all distinct counts in an index. Entries fed to the {@code cursor} will be (count,Value[]),
* where the count (number of nodes having the particular value) will be accessed using {@link NodeValueIndexCursor#nodeReference()}
* and the value (if the index can provide it) using {@link NodeValueIndexCursor#propertyValue(int)}.
* Before accessing a property value the caller should check {@link NodeValueIndexCursor#hasValue()} to see
* whether or not the index could yield values.
*
* For merely counting distinct values in an index, loop over and sum iterations.
* For counting number of indexed nodes in an index, loop over and sum all counts.
*
* NOTE spatial values may not return 100% correctly in that some actually distinct points may be returned multiple times.
*
* @param index {@link IndexReference} referencing index.
* @param cursor {@link NodeValueIndexCursor} receiving distinct count data.
Expand Down
Expand Up @@ -25,10 +25,8 @@
import org.eclipse.collections.impl.set.mutable.primitive.LongHashSet;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
Expand Down Expand Up @@ -74,13 +72,22 @@ public abstract class NodeValueIndexCursorTestBase<G extends KernelAPIReadTestSu
private static long[] nodesOfAllPropertyTypes;
private static long whateverPoint;

private static final int STRING_AND_NUMBER_DISTINCT_VALUES = 100;
private static Map<Value,Set<Long>> stringAndNumberDistinctValues = new HashMap<>();

private static final PointValue POINT_1 =
PointValue.parse( "{latitude: 40.7128, longitude: -74.0060, crs: 'wgs-84'}" );
private static final PointValue POINT_2 =
PointValue.parse( "{latitude: 40.7128, longitude: -74.006000001, crs: 'wgs-84'}" );

@Override
public void createTestGraph( GraphDatabaseService graphDb )
{
try ( Transaction tx = graphDb.beginTx() )
{
graphDb.schema().indexFor( label( "Node" ) ).on( "prop" ).create();
graphDb.schema().indexFor( label( "Node" ) ).on( "prop2" ).create();
graphDb.schema().indexFor( label( "Node" ) ).on( "prop3" ).create();
tx.success();
}
try ( Transaction tx = graphDb.beginTx() )
Expand Down Expand Up @@ -158,6 +165,20 @@ public void createTestGraph( GraphDatabaseService graphDb )
listOfIds.add(nodeWithWhatever( graphDb, new String[]{"first", "second", "third"} ));

nodesOfAllPropertyTypes = listOfIds.toArray();

ThreadLocalRandom random = ThreadLocalRandom.current();
for ( int i = 0; i < STRING_AND_NUMBER_DISTINCT_VALUES; i++ )
{
Object value = random.nextBoolean() ? String.valueOf( i % 10 ) : (i % 10);
long nodeId = nodeWithProp( graphDb, "prop2", value );
stringAndNumberDistinctValues.computeIfAbsent( Values.of( value ), v -> new HashSet<>() ).add( nodeId );
}

assertSameDerivedValue( POINT_1, POINT_2 );
nodeWithProp( graphDb, "prop3", POINT_1.asObjectCopy() );
nodeWithProp( graphDb, "prop3", POINT_2.asObjectCopy() );
nodeWithProp( graphDb, "prop3", POINT_2.asObjectCopy() );

tx.success();
}
}
Expand Down Expand Up @@ -190,6 +211,7 @@ protected boolean indexProvidesTemporalValues()
{
return true;
}
protected abstract void assertSameDerivedValue( PointValue p1, PointValue p2 );

protected boolean indexProvidesSpatialValues()
{
Expand Down Expand Up @@ -1446,24 +1468,7 @@ public void shouldCountDistinctValues() throws Exception
int label = token.nodeLabel( "Node" );
int key = token.propertyKey( "prop2" );
IndexReference index = schemaRead.index( label, key );
Map<Value,Set<Long>> expected = new HashMap<>();
int expectedTotalCount = 100;
List<Long> createdNodes = new ArrayList<>();
try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction() )
{
ThreadLocalRandom random = ThreadLocalRandom.current();
Write write = tx.dataWrite();
for ( int i = 0; i < expectedTotalCount; i++ )
{
long nodeId = write.nodeCreate();
write.nodeAddLabel( nodeId, label );
Value value = Values.of( random.nextBoolean() ? String.valueOf( i % 10 ) : (i % 10) );
write.nodeSetProperty( nodeId, key, value );
expected.computeIfAbsent( value, v -> new HashSet<>() ).add( nodeId );
createdNodes.add( nodeId );
}
tx.success();
}
Map<Value,Set<Long>> expected = new HashMap<>( stringAndNumberDistinctValues );

// then
try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction();
Expand Down Expand Up @@ -1494,53 +1499,22 @@ public void shouldCountDistinctValues() throws Exception
{
assertTrue( expected.toString(), expected.isEmpty() );
}
assertEquals( expectedTotalCount, totalCount );
assertEquals( STRING_AND_NUMBER_DISTINCT_VALUES, totalCount );
}
// the tests in this class share and modify the very same graph, so restore it
deleteNodes( createdNodes );
}

@Test
public void shouldCountDistinctButSimilarPointValues() throws Exception
{
// given
int label = token.nodeLabel( "Node" );
int key = token.propertyKey( "prop2" );
int key = token.propertyKey( "prop3" );
IndexReference index = schemaRead.index( label, key );
Value p1 = PointValue.parse( "{latitude: 40.7128, longitude: -74.0060, crs: 'wgs-84'}" );
Value p2 = PointValue.parse( "{latitude: 40.7128, longitude: -74.006000001, crs: 'wgs-84'}" );
List<Long> createdNodes = new ArrayList<>();
try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction() )
{
Write write = tx.dataWrite();
// point 1
{
long node1 = write.nodeCreate();
write.nodeAddLabel( node1, label );
write.nodeSetProperty( node1, key, p1 );
createdNodes.add( node1 );
}
// point 2
{
long node2 = write.nodeCreate();
write.nodeAddLabel( node2, label );
write.nodeSetProperty( node2, key, p2 );
createdNodes.add( node2 );
}
// point 2
{
long node3 = write.nodeCreate();
write.nodeAddLabel( node3, label );
write.nodeSetProperty( node3, key, p2 );
createdNodes.add( node3 );
}
tx.success();
}

// when
Map<Value,Integer> expected = new HashMap<>();
expected.put( p1, 1 );
expected.put( p2, 2 );
expected.put( POINT_1, 1 );
expected.put( POINT_2, 2 );
try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction();
NodeValueIndexCursor node = cursors.allocateNodeValueIndexCursor() )
{
Expand All @@ -1555,25 +1529,17 @@ public void shouldCountDistinctButSimilarPointValues() throws Exception
}
assertTrue( expected.isEmpty() );
}
deleteNodes( createdNodes );
}

private void deleteNodes( List<Long> createdNodes ) throws Exception
private long nodeWithProp( GraphDatabaseService graphDb, Object value )
{
try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction() )
{
for ( Long createdNode : createdNodes )
{
tx.dataWrite().nodeDelete( createdNode );
}
tx.success();
}
return nodeWithProp( graphDb, "prop", value );
}

private long nodeWithProp( GraphDatabaseService graphDb, Object value )
private long nodeWithProp( GraphDatabaseService graphDb, String key, Object value )
{
Node node = graphDb.createNode( label( "Node" ) );
node.setProperty( "prop", value );
node.setProperty( key, value );
return node.getId();
}

Expand Down

0 comments on commit 9adc863

Please sign in to comment.