Bidirectional recursion in neo4j - neo4j

Cannot find answer online for this. I want to do a recursive query upstream and downstream on protein interaction map. If user enters a protein (protein 'C') and depth N=2, I want to return 2 upstream and 2 downstream proteins in the interaction map and the regulation. However if its upstream then protein 'b' on right side of MATCH needs to come first in the return table and if its downstream direction then protein 'a' on left side of match needs to come first in return table. How can I do this?
For instance this is the bidirection but half of the rows are the wrong order in columns 1 and 3.
MATCH p = (a:Protein { name:'C' })<-[:REGULATES*1..2]->(b:Protein)
WITH *, relationships(p) as r
RETURN nodes(p)[length(p)-1].name AS Protein1, r[length(p)-1] as Regulates, b.name AS Protein2
I can only get what I want with two calls and switching order or RETURN columns.
MATCH p = (a:Protein { name:'C' })-[:REGULATES*1..2]->(b:Protein)
WITH *, relationships(p) as r
RETURN nodes(p)[length(p)-1].name AS Protein1, r[length(p)-1] as Regulates, length(p), b.name AS Protein2
MATCH p = (a:Protein { name:'C' })<-[:REGULATES*1..2]-(b:Protein)
WITH *, relationships(p) as r
RETURN b.name AS Protein1, r[length(p)-1] as Regulates, nodes(p)[length(p)-1].name AS Protein2

Figured it out using functions startNode and endNode. The last() and head() functions are also handy.
MATCH p = (n:Protein { name:'C' })<-[:REGULATES*1..3]->(b:Protein)
WITH *, relationships(p) as rs
RETURN startNode(last(rs)).name as Protein1, last(rs).direction as Regulates, endNode(last(rs)).name as Protein2, length(p)

Related

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.

Neo4j - Cypher - Build object where Property is dynamic, like Type(r)

From my searchings I did not find a way to set the property of an object dynamically, only by defining it hardcoded (Like below the "Detail" property)
Here is my sample:
Neo4j Graph or via Neo4j Console
MATCH(p:Person)-[r]->(m:Movie)
WITH { Person: p.name,
Detail: collect(r.roles)
} AS Result
RETURN Result
My target (not working yet):
MATCH(p:Person)-[r]->(m:Movie)
WITH { Person: p.name,
CASTED_FOR: // --> Only values(r.roles) for relationship "CASTED_FOR" needed here
ACTED_IN: // --> Only values(r.roles) for relationship "ACTED_IN" needed here
} AS Result
RETURN Result
I know I could make e.g. [r:CASTED_FOR] or WHERE Type(r) = "CASTED_FOR", but I don't like to have multiple WITH and MATCH queries.
Thank you
This query uses Cypher's list comprehension construct to do what you want:
MATCH (p:Person)-[r]->(:Movie)
WITH p, COLLECT(r) AS rs
RETURN {
Person: p.name,
CASTED_FOR: [x IN rs WHERE TYPE(x) = 'CASTED_FOR' | x.roles],
ACTED_IN: [x IN rs WHERE TYPE(x) = 'ACTED_IN' | x.roles]
} AS Result

How to avoid duplications return distinct nodes and the relation ship using neo4j

I would like to return for a given node-id related nodes and their relationships props
For example:
-> defines a bi direction relationship with property timestamp
1234->777
777->1234
1234->999
999->1234
1234->888
888->1234
1234,777,888,999 are node-ids
When I execute this:
final PreparedStatement ps = conn.prepareStatement("start a = node(1234) match (a)-[k:nearby*]->(b) where a<>b return DISTINCT b, k");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Map result = (Map<String, Object>) rs.getObject("b");
System.out.println(result.toString());
}
} catch (SQLException e) {
e.printStackTrace();
logger.error("Error returning userId=" + userIdInput, e);
}
return null;
}
I get:
{userId=777}
{userId=999}
{userId=888}
{userId=888}
{userId=999}
{userId=999}
{userId=777}
{userId=888}
{userId=888}
{userId=777}
{userId=888}
{userId=777}
{userId=999}
{userId=999}
{userId=777}
How I do get distinct results only (777,888,999)
How to retrieve the relationship props of 1234 to the dest node? I expect to get the timestamp prop which defined on each relationship
Thank you,
ray.
I'm not sure what language you're using so I'll focus on the Cypher. Firstly I would replace the START query with a MATCH with a WHERE on ID(a):
MATCH (a)-[k:nearby*]->(b)
WHERE ID(a) = 1234 AND a<>b
RETURN DISTINCT b, k
Secondly I'm pretty sure you don't need the a<>b because Cypher paths won't loop back on the same nodes:
MATCH (a)-[k:nearby*]->(b)
WHERE ID(a) = 1234
RETURN DISTINCT b, k
Lastly, and to your question, I suspect the reason that you're getting duplicates is because you have multiple relationships. If so you can return the result node and an array of the relationships like so:
MATCH (a)-[k:nearby*]->(b)
WHERE ID(a) = 1234
RETURN collect(b), k
That should return you node/relationship objects (with properties on both). Depending on your language/library you might get Maps or you might get objects wrapping the data
If your library doesn't return the start/end nodes for relationships for you, you can do something like this:
MATCH (a)-[k:nearby*]->(b)
WHERE ID(a) = 1234
RETURN collect({rel: b, startnode: startnode(b), endnode: endnode(b)}), k
Hopefully that helps!
You get non distinct results, because you return both b and k
If you only want to get distinct b's use:
MATCH (a)-[k:nearby*]->(b)
WHERE ID(a) = 1234 AND a<>b
RETURN DISTINCT b
You should also use parameters!
MATCH (a)-[k:nearby*]->(b)
WHERE ID(a) = {1} AND a<>b
RETURN DISTINCT b
ps.setInt(1,1234);

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

Cypher query produces incomplete results (neo4j-1.9-SNAPSHOT)

I have run into the problem when executing a cypher query against a database "neo4j-1.9-SNAPSHOT" on Windows 7.
The database can be downloaded from the topic in Google Groups.
When I run the fist 2 queries in the web admin console, I do not get node with id ="45" as the first node in the path in the result list.
1) start a = node:my_nodes(label='2826'), b = node:my_nodes(label='2826')
match a-[r1]-b
with a, b, r1
match b-[r2]-c
where c.label = 2826 and r1.label = r2.label and id(r1) <> id(r2)
return id(a), id(b), id(c), id(r1), id(r2);
2) START n0=node:my_nodes(label='2826'), n1=node:my_nodes(label='2826'),
n2=node:my_nodes(label='2826')
MATCH n0-[r0]-n1-[r1]-n2
where r0.label = r1.label and id(r0)<>id(r1)
RETURN id(n0), id(n1), id(n2), id(r0), id(r1);
However, when I run the 3rd query, node with id="45" should definitely be in the result list of the first two queries. Moreover, when checking the database it seems to be the case.
3) start a = node(45), b = node:my_nodes(label='2826')
match a-[r1]-b
with a, b, r1
match b-[r2]-c
where a.label = 2826 and c.label = 2826 and r1.label = r2.label and id(r1) <> id(r2)
return id(a), a.label, id(b), id(c), id(r1), id(r2);
On running the cypher query:
start a = node:my_nodes(label='2826')
return id(a);
node with id="45" is in the index.
Any ideas what can be wrong with the first 2 queries?

Resources