Anwar Shaikh Anwar Shaikh - 1 month ago 6
Java Question

In Neo4j, is there any way to restrict nodes and relation types in path while using Java API?

I have source node and destination node I want to put restriction on nodes and relation types in the path. I am using Neo4j Java API.

Consider following toy example,

We have three person nodes A, B & C.

Source Node: A & Destination Node: B. There are many other kind of paths may exists between them. I want to restrict paths to specific format like-

(person) -[worksAt]-> (company) -[CompetitorOf]-> (company) <-[worksAt]- (person)


This can be very easily achieved from cypher query, but I want to know is there any way we can do it using Java API.

enter image description here

NOTE:


  1. Kindly do not suggest putting restriction on path length, that
    doesn't solve the problem. I want to restrict the node and relation
    types in path.

  2. Example mentioned above is toy example. Graph I am trying to work is more complex and there are many possible paths not feasible to traverse and validate individual paths.


Answer

After reading the Neo4j java documentation carefully and experimenting with the code I got following solution working-

To filter path explored by PathFinder create a custom PathExpander using PathExpanderBuilder.

PathExpanderBuilder pathExpanderBuilder = PathExpanderBuilder.empty();

pathExpanderBuilder.add(RelationshipType.withName("worksat"), Direction.OUTGOING);
pathExpanderBuilder.add(RelationshipType.withName("competitorof"), Direction.BOTH);
pathExpanderBuilder.add(RelationshipType.withName("worksat"), Direction.INCOMING);

PathExpander<Object> pathExpander pathExpander = pathExpanderBuilder.build();

Once you create a custom PathExpander you can use it to create appropriate PathFinder which will filter traversal by the PathFinder.

PathFinder<Path> allPathFinder = GraphAlgoFactory.allSimplePaths(this.pathExpander, 4);


Iterable<Path> allPaths = allPathFinder.findAllPaths(sourceNode, targetNode);

In our example sourceNode would be Node 'A' and targetNode would be Node 'B'.