neo4j: finding path and removing duplicates - neo4j

If I have a linked series of nodes: A<--B-->C-->D
match (n)-[r]-(m) return n,r,m will give me [A,B],[B,A],[B,C],[C,B],[C,D],[D,C].
What if I want to return only one of each pair: [A,B], [B,C], [C,D]?
How do I discard the 'duplicates' that come from ignoring the path direction? The nature of this data is such that path directions are fluid and unpredictable. I can get the answer in code with the duplicated results but I'm wondering if there is a way to get neo4j to do the work in advance.

Use the direction arrow:
match (n)-[r]->(m) return n,r,m
if you want to have undirected paths, the pair will be returned twice
you can limit that by imposing order.
match (n)-[r]->(m) where id(n) < id(m) return n,r,m

Related

In neo4j how to return specific nodes or relationship with cypher?

You are given two arrays one for some labels and another for some relationships and you are asked to return the nodes and their relationships which are found only in the arrays you where given. I tried different approach to it but I couldn't get a better cipher to return the graph with respect to both arrays
MATCH (n)-[r]-(m) where n in ["username"] and r in ["knows"] return n,r
The code above, I know its completely wrong but it kinda shows the idea, share your thoughts 😁
This should work:
MATCH (n)-[r]-(m)
WHERE ANY(l IN labels(n) WHERE l IN ['username','label2'])
AND type(r) IN ['knows','relType2']
RETURN n,r,m

In Neo4J return root nodes when having two types of relationships

I have a one direction tree as described as:
Node_C [is_a_method_of] Node_A
Node_D [is_related_to] Node_B
Node_C [is_related_to] Node_D
Node_A and Node_B are root nodes because they are not related or are a method of other nodes. How can I return them?
I saw in another post:
MATCH (n)
WHERE NOT (n)--()
RETURN n;
But that returns orphan nodes.
You would probably want to add some relationship type and direction to your query:
MATCH (n)
WHERE NOT (n)-[:is_a_method_of]->() AND NOT (n)-[:is_related_to]->()
RETURN n;
You haven't really specified the direction of relationships in your graph, so this is only my assumption. You could adapt this query to work on your graph schema if my assumptions are wrong.

How to avoid specific paths in allShortestPath function?

The graph is supposed to represent a system similar to github, with commits (commit1, commit2, commit3 and commit4), documents (d1, d2) and changes on those documents (green nodes).
I am trying to use CYPHER to get all the documents values at a specific commit. In other words, I am trying to find the shortest path between the specific commit and each of the documents on my graph, but avoiding some paths.
Imagine if I am on commit4, d1 should be equal to foo2 and d2 should be equal to spain. This could be solved with the following CYPHER query:
MATCH (c:Commit {id: 'commit4'})-[:FOLLOWS|CHANGED*]->(:Value)<-[:EQUALS]-(d:Document), p = allShortestPaths((c)-[*]-(d))
RETURN p
This would give the following response:
Now, imagine that I want to be get the values on commit3. The request should not return any changes from the commit4. However, if I use the allShortestPaths function the way I do, it will go through commit4 since it is actually the shortest path to d1 and return the exact same response than if my starting node was commit4.
MATCH (c:Commit {id: 'commit3'})-[:FOLLOWS|CHANGED*]->(:Value)<-[:EQUALS]-(d:Document), p = allShortestPaths((c)-[*]-(d))
RETURN p
How could I avoid the allShortestPath function to go through a [:FOLLOWS]->(c) relationship and solve my problem?
From what you explained, I understand that you don't want to traverse the FOLLOWS edge in the opposite direction of the edge. To do so you can use cypher projection in algo.shortestPath:
MATCH (start:Commit {name:'commit4'})
MATCH (end:Document)
CALL algo.shortestPath.stream(start, end, null,{
nodeQuery:'MATCH (n) RETURN id(n) AS id',
relationshipQuery:'MATCH (n)-[r:FOLLOWS|CHANGED]->(p) RETURN id(n) AS source, id(p) AS target UNION MATCH (n)-[r:EQUALS]-(p) RETURN id(n) AS source, id(p) AS target',
graph:'cypher'})
YIELD nodeId, cost
WITH end as document, algo.asNode(nodeId) AS value WHERE "Value" in labels(value)
return document, value
Replace "commit4" with any other commit name.

Cypher query to find the longest path using neo4j 3.1.0 version

Can anybody send the Cypher query to find LONGEST PATH between two nodes using neo4j 3.1.0 version.
The graph algorithm to find the longest path is not implemented.
Here is a Cypher query that gets all paths and sorts them by size:
// get the nodes
MATCH (a:Node), (b:Node)
WHERE ID(a) = 14 AND ID(b) = 7
WITH a,b
// match all paths
MATCH p=(a)-[*]-(b)
// return the longest
RETURN p, length(p) ORDER BY length(p) DESC LIMIT 1
However, without any restrictions on the query, this might not work on large graphs. Finding the longest path in an undirected graph is expensive: https://en.wikipedia.org/wiki/Longest_path_problem
And without restrictions on the query (direction and relationship type) the query will look for all undirected paths.
You should restrict your path query or try two solve your problem without the longest path.
If you are looking for the longest path between nodes where each node in the chain has the same relationship to the next then see Achieving longestPath Using Cypher which shows:
MATCH p=(parent:Entity)-[:HAS_CHILD*1..10]->(child:Person)
WHERE size((child)-[:HAS_CHILD]->()) = 0
RETURN child;
However I am using:
MATCH (parent:Entity)-[:HAS_CHILD*1..10]->(child:Person)
WHERE NOT (child)-[r:HAS_CHILD]->()
RETURN child;
If anyone can comment on performance or any other aspect please do!
I also discovered an undocumented feature which will return the child when it is also the parent (as in only one node):
MATCH (parent:Entity)-[:HAS_CHILD*0..]->(child:Person)
WHERE NOT (child)-[r:HAS_CHILD]->()
RETURN child;

Find paths covering all nodes in neo4j

How do we find out paths in neo4j which will cover all the selected set of nodes.
This will be used for solving a tsp of sorts. to find path which covers all the given set of cities, later will sort on the basis of total distance covered by the path.
You can find all paths between two nodes like this.
match p=(:startNode)-->(:endNode)
return p;
or you can try like
match p=(:startNode)-->(:endNode)
return nodes(p) as node, relationships(p) as rels
You can get all paths like this
match p = ()-->()
return p
limit 100 // Apply limit according to nodes

Resources