I need to find shortest paths between nodes, but with some restrictions on relations types in good paths.
I have two relation types: A & B. Path is considered bad if it has two or more consecutive relation of type B:
Good path: ()-A->()-A->()<-A-()-B->()-A->()-B->()
Bad path: ()-A->()-A->()<-A-()-B->()<-B-()-A->()
The Cypher query:
MATCH path=allShortestPaths( (p:P{idp:123})-[rel:A|B*]-(p2:P{idp:124}) )
WHERE *some-predicate-on-path-or-rel*
RETURN path
is not a solution because the shortest good path may be longer than shortest bad paths.
Q1: Can this problem be solved by some Cypher query?
I can solve my problem with the embedded Java Neo4J API:
GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase("db/store/dir/path");
TraversalDescription td = graphDb.traversalDescription()
.breadthFirst()
.evaluator(Evaluators.toDepth(max_depth))
.evaluator(Evaluators.endNodeIs(Evaluation.INCLUDE_AND_PRUNE, Evaluation.EXCLUDE_AND_CONTINUE, endNode))
.evaluator(new DoubleB_PruneEvaluator());
static class DoubleB_PruneEvaluator implements Evaluator {
@Override
public Evaluation evaluate(final Path path) {
Iterator<Relationship> lRels = path.reverseRelationships().iterator();
if (lRels.hasNext() && lRels.next().isType(MyRelTypes.B)) {
if (lRels.hasNext() && lRels.next().isType(MyRelTypes.B))
return Evaluation.EXCLUDE_AND_PRUNE;
}
return Evaluation.INCLUDE_AND_CONTINUE;
}
}
Q2: Is this solution is quite efficient? Or how to improve?
But my application is written on PHP and interacts with Neo4j server via REST protocol.
Q3: How can I run this solution by some REST query?
No intelligent person wouldn't answer me. So I will try myself.
A1: This problem cannot be solved by standard Cypher query. (My Neo4j version 3.1.1)
A2: This solution is not quite efficient for several reasons:
In addition, this solution finds only one path. The other paths of the same length will not be found.
A3: Java coded solutions can be added to a server by extending Neo4j. I solve my problem using user-defined procedures:
my/app/RelType.java:
my/app/DoubleB_PruneEvaluator.java:
my/app/Procedures.java:
Doc: https://neo4j.com/docs/java-reference/3.1/javadocs/index.html?org/neo4j/procedure/Procedure.html
A few words about the compilation and installation plugin:
As a beginner in Java, I decided that utilities Eclipse and Maven is too heavy. I prefer to use simple javac & jar:
Now we can run the Cypher query: