count the number of nodes after shortest path neo4j - neo4j

MATCH (FooB:Actor { name: 'Foob' }),(AnnaH:Actor { name: 'Anna Hathaway' }), p = shortestPath((Foob)-[act:ACTED_IN*]-(AnnaH))
RETURN p
So this returns a graph p that is the shortest path from actors Foob to Anna Hathaway. How do I now count all nodes in p with a label of "chocolate"?

This should do it
RETURN SIZE([n IN nodes(p) WHERE n:chocolate]) AS count

Use nodes function in conjunction with UNWIND:
MATCH (FooB:Actor { name: 'Foob' }),(AnnaH:Actor { name: 'Anna Hathaway' }), p = shortestPath((Foob)-[act:ACTED_IN*]-(AnnaH))
UNWIND nodes(p) AS n
WITH n AS n
WHERE n.chocolate
RETURN COUNT(*)

Related

Shortest Path using Neo4j, with relationships of Start and End Node

I'm fairly new to Neo4j. I'm trying to get the shortest path for default movie database.
However, along with it I also need the start and end node(of type Person) to display there first level relation to any other node and if any person node on the path have a relation to the start and end node via some other node. Its better to explain with below pictures.
Normal shortestpath will look, something like this.
MATCH (p1:Person { name: 'Kevin Bacon' }),(p2:Person { name: 'Meg Ryan' }),
p = shortestPath((p1)-[*..15]-(p2))
return p
However my desired output is this one.
I tried below cypher. However i cannot understand, how to do it. I'm getting below result, which is incorrect.
MATCH (p1:Person { name: 'Kevin Bacon' }),(p2:Person { name: 'Meg Ryan' }),
p = shortestPath((p1)-[*..15]-(p2))
MATCH (p1:Person)-[r]-(b) // here i need foreach node on path for type person, get there relationships? However can't do that
return p,p1,r,b
Appreciate any help. Thanks.
You can get all the movies in the start and end nodes of shortest path. Then add the movies with the path.
MATCH p = shortestPath((p1:Person { name: 'Kevin Bacon' })-[*..15]-(p2:Person { name: 'Meg Ryan' }))
WITH p1, p2, p
MATCH (p1)-[:ACTED_IN]->(m1)
MATCH (p2)-[:ACTED_IN]->(m2)
RETURN p, m1, m2
Thanks for the reply Jose. It's close. I don''t want to restrict the relation just to "ACTED_IN" with (Movie). I just did a small modification.
MATCH p = shortestPath((p1:Person { name: 'Kevin Bacon' })-[*..15]-
(p2:Person { name: 'Meg Ryan' }))
UNWIND nodes(p) as n
MATCH (n)-[*]->(q)
RETURN n, q
However, i don't need the nodes highlighted in the box as they are not related to Meg and Kevin. Not sure how to exclude them.

To get all nodes and path from edge to root using neo4j

I want to get all nodes information with paths from edge to root node.Using one of the edge property.
This is the three layer node structure.
MATCH (g:GrandChild{name:"C"})<-[:childToGrandChild]-(c:Child)<-[p:Parent*0..]-(c:Child) RETURN c,g,p
This will return only B,C nodes with relationship like this
cypher used
CREATE (p: Parent{name : '1'} ) RETURN p
MATCH (p:Parent) WHERE p.name = '1' CREATE (c: Child{name : '2'} )<-[:parentToChild]-(p) RETURN p
MATCH (c:Child) WHERE c.name = '3' CREATE (g: GrandChild {name : '2'} )<-[:childToGrandChild]-(c) RETURN c
Please help..
You have missed parentTochild relationship which will be like,
MATCH (g:GrandChild{name:"C"})<-[:childToGrandChild]-(c:Child)<-[parentToChild*0..]-(p:Parent)
RETURN c,g,p
Try this :
MATCH (g:GrandChild{name:"C"})<-[:childToGrandChild]-(c:Child)
MATCH (c)<-[p:Parent*0..]-(c2:Child)
RETURN c,c2,g,p

Neo4j cypher return Path with a specific format

I have a cypher query to return the shortest Path between two nodes.
I am using Java JdbcTemplate.
MATCH (nodeA),(nodeB), p = shortestPath((nodeA)-[*..15]-(nodeB)) " //
+ "WHERE ID(nodeA) = {1} and ID(nodeB) = {2} RETURN nodes(p) as nodes " //
+ ",relationships(p) as edges
My problem is that I have a Util method that do the mapping of the jdbctempate result. It only works when my cypher returns nodes suchs as :
RETURN { id : id(node), labels : labels(node), data: node } as node
Is there a way to make my initial cypher return the result in that format?
NODES returns a list of nodes, so you can use UNWIND to unpack the list into a set of rows. So in your example...
MATCH (nodeA),(nodeB), p = shortestPath((nodeA)-[*..15]-(nodeB))
WHERE ID(nodeA) = {1} AND ID(nodeB) = {2}
UNWIND nodes(p) as n
RETURN { id : id(n), labels : labels(n), data: n} as node, relationships(p) as edges
You can use WITH + COLLECT to fold the nodes back into a list, and then perform the same operation on relationships if you need.

How to check if node globally exists and set condition on it in Cypher?

I'm struggling with problem of creating query in Cypher.
Let's use this graph as an example:
MERGE(a:Person {name:'Alice', age:38, eyes:'brown'})
MERGE(c:Person {name:'Charlie', age:53, eyes:'green'})
MERGE(d:Person {name:'Daniel', age:54, eyes:'brown'})
MERGE(b:Person {name:'Bob', age:25, eyes:'blue'})
MERGE(a)-[:KNOWS]->(c)
MERGE(a)-[:KNOWS]->(b)
MERGE(c)-[:KNOWS]->(d)
MERGE(b)-[:KNOWS]->(d)
I would like to have query that returns me nodes with name = 'Alice' only if there aren't any nodes with name = 'Bob'. So if there is Bob I would like to see no results.
Here is what I've tried:
1) With exists()
MATCH p =(n)-[*1..3]->(b)
WHERE n.name = 'Alice' AND NOT EXISTS ((n {name: 'Bob'})-[*1..3]->(b))
RETURN p
But it returns all nodes and relationships.
2) With none()
MATCH p =(n)-[*1..3]->(b)
WHERE n.name = 'Alice' AND NONE (x IN nodes(p) WHERE x.name = 'Bob')
RETURN p
This returned all nodes, without Bob...
3) with any()
MATCH p =(n)-[*1..3]->(b)
WHERE n.name = 'Alice' AND NOT ANY (x IN nodes(p) WHERE x.name = 'Bob')
RETURN p
But this gave me the same result as above.
I'm running out of ideas how to return Alice only if Bob is not present.
What I would expect from query is to return Alice when I delete Bob, but when such node exists - nothing.
Any help is appreciated:)
Thanks!
You should try this query :
MATCH (n:Person {name:'Alice'})
WHERE NOT (n)-[:KNOWS*..3]-(:Person {name:'Bob'})
RETURN n

Shortest path through a node

How to get the shtortest path between two nodes, where the path is going through a specific node. This is what I've got so far:
MATCH (a:User { username:"User1" }),(b:User { username:"User2" }),(c:User { username:"User3" }),
p = allShortestPaths((a)-[*]-(b))
RETURN p
I want a result in which the path goes through User3 (c).
You can find each leg separately:
MATCH (a:User {username:"User1"}),(b:User {username:"User2"}),(c:User {username:"User3"}),
p = allShortestPaths((a)-[*]-(c)), q = allShortestPaths((c)-[*]-(b))
RETURN p, q
Be aware, though, that if you have very long paths, or cycles, this query can take a long time or never finish. You should consider putting an upper bound on the path lengths, e.g.:
MATCH (a:User {username:"User1"}),(b:User {username:"User2"}),(c:User {username:"User3"}),
p = allShortestPaths((a)-[*..10]-(c)), q = allShortestPaths((c)-[*..10]-(b))
RETURN p, q

Resources