Neo4j Implement PathExpander Sequence

Hi All,

After took some rest for a while, I would like to post some kind of simple implementation of pathexpander since it is really hard to find the sample. I hope it could give some ideas on how the pathexpander works.

As you know that each node in the graph could have many relationship types to other nodes, So when you use the neo4j traversal you must be interested to how to choose the path to be traversed effectively. Neo4j provides pathexpander and evaluators to manage which nodes to be included but I do really love to use the pathexpander to implement on which relationship to be traversed and evaluator only to manage traversal depth, node field check and etc.

I used to have the code integrated with the springdata as the integrator between my code and neo4j. So the code would be as below.

1. Setup the maven with .pom. Put attention to the neo4j dependency, Although I put there neo4j rest, I dont use it since some of the function in the evaluator and pathexpander have not yet implemented. So I decided to use the embedded graphdataabse which mostly of the functions are ready to do the task.

</code></pre>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

<groupId>neo4j</groupId>
 <artifactId>mytraversal</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

<name>mytraversal</name>
 <url>http://maven.apache.org</url>

<properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

<repositories>
 <repository>
 <snapshots>
 <enabled>false</enabled>
 </snapshots>
 <id>central</id>
 <name>Maven Repository Switchboard</name>
 <url>http://repo1.maven.org/maven2</url>
 </repository>

<repository>
 <id>springsource-repo</id>
 <name>SpringSource Repository</name>
 <url>http://repo.springsource.org/release</url>
 </repository>
 <repository>
 <id>spring-snapshot</id>
 <name>Spring Maven SNAPSHOT Repository</name>
 <url>http://repo.springsource.org/libs-milestone</url>
 </repository>

</repositories>
 <dependencies>
 <dependency>
 <groupId>cglib</groupId>
 <artifactId>cglib</artifactId>
 <version>3.0</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>3.2.3.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.2.3.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.hibernate</groupId>
 <artifactId>hibernate-validator</artifactId>
 <version>5.0.1.Final</version>
 </dependency>
 <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>1.2.17</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.data</groupId>
 <artifactId>spring-data-neo4j-rest</artifactId>
 <version>2.2.2.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.data</groupId>
 <artifactId>spring-data-neo4j</artifactId>
 <version>2.3.0.M1</version>
 </dependency>
 </dependencies>
</project>

<code>

2. Create the applicationContext-spring.xml to manage the connection and bean creation for the neo4j to talk to springdata. Today I don’t use the rest server but the embedded graph to get full functionality of the springdata.

</span>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
 http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<context:spring-configured />
 <context:annotation-config />
 <context:component-scan base-package="neo4j.mytraversal" />
 <neo4j:repositories base-package="neo4j.mytraversal" />

<neo4j:config
 storeDirectory="C://Users//Rio Asmara Suryadi//Documents//ne4j//neo4j-community-1.9.2//data//graph.db" />
</beans>

3. Create the necessary file as below in the picture where I will show you the full code in this text traversal

4. Create class Runner as the as the object to execute the traversal

package neo4j.mytraversal;

import java.util.Iterator;
import java.util.List;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.traversal.Evaluation;
import org.neo4j.graphdb.traversal.Evaluator;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.kernel.StandardExpander;
import org.neo4j.kernel.Uniqueness;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.support.Neo4jTemplate;

public class Runner {

enum Rels implements RelationshipType {
 BUY
 }

@Autowired
 Neo4jTemplate template;

public void check() {
 final MeExpander test = new MeExpander();
 test.addRelationName("BUY");
 test.addRelationName("PURCHASED_ITEM");
 if (template != null) {
 TraversalDescription desc = template.traversalDescription()
 .breadthFirst().evaluator(new Evaluator() {
 public Evaluation evaluate(Path path) {
 if (path.length() == test.getSize()) {
 return Evaluation.INCLUDE_AND_PRUNE;
 }
 return Evaluation.EXCLUDE_AND_CONTINUE;
 }
 }).expand(test);

long start_time = System.currentTimeMillis();
 Iterator<Path> path = desc.traverse(template.getNode(1)).iterator();

while (path.hasNext()) {
 nodePropertyPrint(path.next().endNode());
 }

long end_time = System.currentTimeMillis();
 System.out.println("Traversal Time : "
 + String.valueOf(end_time - start_time) + " ms");

}

}

public void nodePropertyPrint(Node node) {
 Iterator<String> it = node.getPropertyKeys().iterator();
 while (it.hasNext()) {
 String field = it.next();
 System.out.println(field + ":" + node.getProperty(field));
 }

}

}

5. Implementing the traversal, Create the MeExpander class. MeExpander.class is java class which implement the pathexpander. You need to implement the “expand” function as below

</pre>
package neo4j.mytraversal;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.PathExpander;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.traversal.BranchState;

public class MeExpander implements PathExpander {

List<DynamicRelationshipType> dynamicRelationshipTypes;

public MeExpander() {
 dynamicRelationshipTypes = new ArrayList<DynamicRelationshipType>();
 }

public Iterable expand(Path path, BranchState state) {
 return path.endNode().getRelationships(Direction.OUTGOING,
 dynamicRelationshipTypes.get(path.length()));
 }

public void addRelationName(String name) {
 dynamicRelationshipTypes.add(DynamicRelationshipType.withName(name));
 }

 int getSize(){
 return dynamicRelationshipTypes.size();
 }

public PathExpander reverse() {
 // TODO Auto-generated method stub
 return null;
 }

}
<pre>

6. Here is the screen capture of my graph database. Just focus to the node called Rio and its relationship. So whenever I run the code it will start from the node Rio and traverse to the depth 2 and return the node in the depth 2.

GraphCapture

7. So the output of the this simple apps is

CONSOLE OUT

name:Supermie
Traversal Time : 25 ms

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s