Last active
February 28, 2021 00:07
-
-
Save mneedham/a35f146dbe09266d574d to your computer and use it in GitHub Desktop.
All different ways of searching relationships in Neo4j
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | |
xmlns="http://maven.apache.org/POM/4.0.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>org.neo4j</groupId> | |
<artifactId>vague</artifactId> | |
<version>1.0</version> | |
<name>Vague</name> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-jar-plugin</artifactId> | |
<configuration> | |
<archive> | |
<manifestFile> | |
src/main/resources/META-INF/MANIFEST.MF | |
</manifestFile> | |
</archive> | |
</configuration> | |
</plugin> | |
<plugin> | |
<artifactId>maven-assembly-plugin</artifactId> | |
<configuration> | |
<archive> | |
<manifest> | |
<mainClass>fully.qualified.MainClass</mainClass> | |
</manifest> | |
</archive> | |
<descriptorRefs> | |
<descriptorRef>jar-with-dependencies</descriptorRef> | |
</descriptorRefs> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
<properties> | |
<maven.compiler.source>1.7</maven.compiler.source> | |
<maven.compiler.target>1.7</maven.compiler.target> | |
</properties> | |
<dependencies> | |
<dependency> | |
<groupId>org.neo4j</groupId> | |
<artifactId>neo4j-kernel</artifactId> | |
<version>2.1.4</version> | |
<type>test-jar</type> | |
</dependency> | |
<dependency> | |
<groupId>org.neo4j</groupId> | |
<artifactId>neo4j-kernel</artifactId> | |
<version>2.1.4</version> | |
</dependency> | |
<dependency> | |
<groupId>org.neo4j</groupId> | |
<artifactId>neo4j-lucene-index</artifactId> | |
<version>2.1.4</version> | |
</dependency> | |
<dependency> | |
<groupId>org.neo4j.app</groupId> | |
<artifactId>neo4j-server</artifactId> | |
<version>2.1.4</version> | |
</dependency> | |
<dependency> | |
<groupId>org.neo4j.app</groupId> | |
<artifactId>neo4j-server</artifactId> | |
<version>2.1.4</version> | |
<type>test-jar</type> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.commons</groupId> | |
<artifactId>commons-math3</artifactId> | |
<version>3.3</version> | |
</dependency> | |
</dependencies> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File; | |
import java.io.IOException; | |
import org.apache.commons.io.FileUtils; | |
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; | |
import org.neo4j.graphdb.Direction; | |
import org.neo4j.graphdb.DynamicLabel; | |
import org.neo4j.graphdb.DynamicRelationshipType; | |
import org.neo4j.graphdb.GraphDatabaseService; | |
import org.neo4j.graphdb.Label; | |
import org.neo4j.graphdb.Node; | |
import org.neo4j.graphdb.Relationship; | |
import org.neo4j.graphdb.Transaction; | |
import org.neo4j.graphdb.factory.GraphDatabaseFactory; | |
import static org.neo4j.graphdb.DynamicRelationshipType.withName; | |
public class VagueRelationshipTypes | |
{ | |
private static final DynamicRelationshipType HAS = withName( "HAS" ); | |
private static final DynamicRelationshipType HAS_ADDRESS = withName( "HAS_ADDRESS" ); | |
private static final DynamicRelationshipType HAS_FRIEND = withName( "HAS_FRIEND" ); | |
private static final Label ADDRESS = DynamicLabel.label( "Address" ); | |
private static final Label FRIEND = DynamicLabel.label( "Friend" ); | |
private static final int ITERATIONS = 100; | |
private static final int RELATIONSHIPS_TO_CREATE = 10_000; | |
private static final int OTHER_RELATIONSHIPS_TO_CREATE = 50_000; | |
public static void main( String[] args ) throws IOException | |
{ | |
GraphDatabaseService propertyCheckDb = dbWithPropertiesOnEndNode(); | |
GraphDatabaseService labelDb = dbWithLabels(); | |
GraphDatabaseService relationshipNameDb = dbWithSpecificRelationshipNames(); | |
GraphDatabaseService propertyOnRelDb = dbWithPropertiesOnRel(); | |
printPercentiles( queryPropertyOnEndNode( propertyCheckDb ) ); | |
printPercentiles( queryPropertyOnRel( propertyOnRelDb ) ); | |
printPercentiles( queryOnLabels( labelDb ) ); | |
printPercentiles( queryOnRelName( relationshipNameDb ) ); | |
labelDb.shutdown(); | |
propertyCheckDb.shutdown(); | |
relationshipNameDb.shutdown(); | |
propertyOnRelDb.shutdown(); | |
} | |
public static String padRight(String s, int n) { | |
return String.format("%1$-" + n + "s", s); | |
} | |
private static void printPercentiles( DescriptiveStatistics stats ) | |
{ | |
System.out.println(padRight( "50%ile: " + stats.getPercentile( 50 ), 15 ) + | |
padRight( "75%ile: " + stats.getPercentile( 75 ), 15 ) + | |
padRight( "99%ile: " + stats.getPercentile( 99 ), 15 )); | |
} | |
private static DescriptiveStatistics queryOnRelName( GraphDatabaseService db ) | |
{ | |
System.out.println(); | |
System.out.println("relationship name"); | |
DescriptiveStatistics stats = new DescriptiveStatistics(); | |
for ( int i = 0; i < ITERATIONS; i++ ) | |
{ | |
long start = System.currentTimeMillis(); | |
int numberOfAddresses = 0; | |
try(Transaction tx = db.beginTx()) { | |
Node startNode = db.getNodeById( 0 ); | |
Iterable<Relationship> relationships = startNode.getRelationships( Direction.OUTGOING, HAS_ADDRESS ); | |
for ( Relationship relationship : relationships ) | |
{ | |
numberOfAddresses++; | |
} | |
tx.failure(); | |
} | |
long runningTime = System.currentTimeMillis() - start; | |
stats.addValue( runningTime ); | |
// System.out.println(numberOfAddresses + " " + runningTime ); | |
} | |
return stats; | |
} | |
private static DescriptiveStatistics queryOnLabels( GraphDatabaseService db ) | |
{ | |
DescriptiveStatistics stats = new DescriptiveStatistics(); | |
System.out.println(); | |
System.out.println("labels"); | |
for ( int i = 0; i < ITERATIONS; i++ ) | |
{ | |
long start = System.currentTimeMillis(); | |
int numberOfAddresses = 0; | |
try(Transaction tx = db.beginTx()) { | |
Node startNode = db.getNodeById( 0 ); | |
Iterable<Relationship> relationships = startNode.getRelationships( Direction.OUTGOING, HAS ); | |
for ( Relationship relationship : relationships ) | |
{ | |
if(relationship.getEndNode().hasLabel( ADDRESS )) { | |
numberOfAddresses++; | |
} | |
} | |
tx.failure(); | |
} | |
long runningTime = System.currentTimeMillis() - start; | |
stats.addValue( runningTime ); | |
// System.out.println(numberOfAddresses + " " + runningTime ); | |
} | |
return stats; | |
} | |
private static DescriptiveStatistics queryPropertyOnRel( GraphDatabaseService db ) | |
{ | |
System.out.println(); | |
System.out.println("property on rel"); | |
DescriptiveStatistics stats = new DescriptiveStatistics(); | |
for ( int i = 0; i < ITERATIONS; i++ ) | |
{ | |
long start = System.currentTimeMillis(); | |
int numberOfAddresses = 0; | |
try(Transaction tx = db.beginTx()) { | |
Node startNode = db.getNodeById( 0 ); | |
Iterable<Relationship> relationships = startNode.getRelationships( Direction.OUTGOING, HAS ); | |
for ( Relationship relationship : relationships ) | |
{ | |
if(relationship.getProperty( "type" ).toString().equals( "address" )) { | |
numberOfAddresses++; | |
} | |
} | |
tx.failure(); | |
} | |
long runningTime = System.currentTimeMillis() - start; | |
stats.addValue( runningTime ); | |
// System.out.println(numberOfAddresses + " " + runningTime ); | |
} | |
return stats; | |
} | |
private static DescriptiveStatistics queryPropertyOnEndNode( GraphDatabaseService db ) | |
{ | |
DescriptiveStatistics stats = new DescriptiveStatistics(); | |
System.out.println("property on end node"); | |
for ( int i = 0; i < ITERATIONS; i++ ) | |
{ | |
long start = System.currentTimeMillis(); | |
int numberOfAddresses = 0; | |
try(Transaction tx = db.beginTx()) { | |
Node startNode = db.getNodeById( 0 ); | |
Iterable<Relationship> relationships = startNode.getRelationships( Direction.OUTGOING, HAS ); | |
for ( Relationship relationship : relationships ) | |
{ | |
if(relationship.getEndNode().getProperty( "type" ).toString().equals( "address" )) { | |
numberOfAddresses++; | |
} | |
} | |
tx.failure(); | |
} | |
long runningTime = System.currentTimeMillis() - start; | |
stats.addValue( runningTime); | |
// System.err.println(numberOfAddresses + " " + runningTime ); | |
} | |
return stats; | |
} | |
private static GraphDatabaseService dbWithPropertiesOnRel() throws IOException | |
{ | |
String path = "/tmp/properties-on-rel"; | |
FileUtils.deleteDirectory( new File(path) ); | |
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); | |
try(Transaction tx = db.beginTx()) { | |
Node node = db.createNode(); | |
for ( int i = 0; i < RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
Relationship rel = node.createRelationshipTo( otherNode, HAS ); | |
rel.setProperty( "type", "address" ); | |
} | |
for ( int i = 0; i < OTHER_RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
Relationship rel = node.createRelationshipTo( otherNode, HAS ); | |
rel.setProperty( "type", "friend" ); | |
} | |
tx.success(); | |
} | |
return db; | |
} | |
private static GraphDatabaseService dbWithPropertiesOnEndNode() throws IOException | |
{ | |
String path = "/tmp/properties"; | |
FileUtils.deleteDirectory( new File(path) ); | |
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); | |
try(Transaction tx = db.beginTx()) { | |
Node node = db.createNode(); | |
for ( int i = 0; i < RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
otherNode.setProperty( "type", "address" ); | |
node.createRelationshipTo( otherNode, HAS ); | |
} | |
for ( int i = 0; i < OTHER_RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
otherNode.setProperty( "type", "friend" ); | |
node.createRelationshipTo( otherNode, HAS ); | |
} | |
tx.success(); | |
} | |
return db; | |
} | |
private static GraphDatabaseService dbWithLabels() throws IOException | |
{ | |
String path = "/tmp/labels"; | |
FileUtils.deleteDirectory( new File(path) ); | |
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); | |
try(Transaction tx = db.beginTx()) { | |
Node node = db.createNode(); | |
for ( int i = 0; i < RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
otherNode.addLabel( ADDRESS ); | |
node.createRelationshipTo( otherNode, HAS ); | |
} | |
for ( int i = 0; i < OTHER_RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
otherNode.addLabel( FRIEND ); | |
node.createRelationshipTo( otherNode, HAS ); | |
} | |
tx.success(); | |
} | |
return db; | |
} | |
private static GraphDatabaseService dbWithSpecificRelationshipNames() throws IOException | |
{ | |
String path = "/tmp/specific-rel-names"; | |
FileUtils.deleteDirectory( new File(path) ); | |
GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); | |
try(Transaction tx = db.beginTx()) { | |
Node node = db.createNode(); | |
for ( int i = 0; i < 10_000; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
node.createRelationshipTo( otherNode, HAS_ADDRESS ); | |
} | |
for ( int i = 0; i < OTHER_RELATIONSHIPS_TO_CREATE; i++ ) | |
{ | |
Node otherNode = db.createNode(); | |
node.createRelationshipTo( otherNode, HAS_FRIEND ); | |
} | |
tx.success(); | |
} | |
return db; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment