Get nodes BETWEEN two nodes - neo4j

How can I get the nodes on a path of variable length between two nodes, exclusive, in Neo4j?
Example
N1 -RELATIONSHIP-> N2 -RELATIONSHIP-> N3 -RELATIONSHIP-> N4
I'd like to get N2 and N3
I do not know the length of the path beforehand, I only know the starting node

Match p= (n1)-[r:RELATIONSHIP*]->(n4) return filter(x IN nodes(p)
WHERE x<>n1 AND x<>n4) AS pathNodes
try this

You can get all the nodes with in the path like this
MATCH p=(n1)-->(b)-->(n4)
RETURN filter(x IN nodes(p)
WHERE id(x) <> id(n1) AND id(x) <>id(n4)) AS allNodes
Here is the reference doc http://neo4j.com/docs/stable/query-functions-collection.html

Related

Cypher Connect nodes in a path returned by gds.alpha.kShortestPaths.stream

I run gds.alpha.kShortestPaths.stream using Neo4j 4.0.2. The algorithm yields a path.
The path has the nodes connected with NEXT relationship. I need to find the actual relationships in the Graph that connect the nodes in the path. I came up with a kludgy query that is based on my knowing how long the path is:
...
YIELD path
with nodes(path) as nodes with nodes[0] as n0, nodes[1] as n1, nodes[2] as n2, nodes[3] as n3
match (n0)-[r1]-(n1)
match (n1)-[r2]-(n2)
match (n2)-[r3]-(n3)
return n0, n1, n2, n3, r1, r2, r3
Obviously this solution is inadequate and the only reason I posted it here is to illustrate what I need to do for a path of any length.
Thank you
You can do this programmatically with:
YIELD index, path
WITH index, nodes(path) as nodes
WITH index, nodes, size(nodes) as number_of_nodes
UNWIND range(0,number_of_nodes - 2) as start
WITH index, nodes[start] as start_node, nodes[start + 1] as end_node
MATCH (start_node)-[r:NEXT]->(end_node)
RETURN index, start_node,r, end_node

neo4j. Matching nodes, but I need to return edges if there

Think to a Cypher query like this:
MATCH (n)
WHERE <complex condition>
RETURN n
But I need to return also possible edges between those nodes. Is it possible?
MATCH (n)
WHERE <complex condition>
WITH COLLECT(n) AS nodes
MATCH (n)-[r]-(m)
WHERE (n IN nodes) AND (m in nodes)
AND id(n)>id(m)
RETURN n,r,m

cypher multiple match is very slow

I want to match some node which don't satisfy the condition, but it's very slow. How to optimize it? There are about 70000 nodes in the database.
match (n:A)--(p:B)--(q:C)
with collect(n) as nc
match m where not m in nc
return count(m)
There is no need to first get all the nodes that match an initial pattern. It is enough to go through all the nodes and check them:
MATCH (m) WHERE NOT (m)--(:B)--(:C)
RETURN count(m)
Or if the condition on the label 'A' is important:
MATCH (m)
OPTIONAL MATCH p = (m)--(:B)--(:C)
WITH m WHERE (p IS NULL) OR (NOT p IS NULL AND NOT 'A' IN LABELS(m))
RETURN count(m)

How to achieve the following in Cypher query?

I tried the following query # http://goo.gl/Ou2GZG
START s=node(1), t=node(4)
MATCH p=s-[*]-pt--t
WHERE SINGLE (n1 IN nodes(p)
WHERE id(n1)=id(t))
WITH DISTINCT pt AS pts, t
MATCH p=t-[*]-pfn
WHERE NONE (n IN nodes(p)
WHERE id(n)=3 OR id(n)=7)
RETURN DISTINCT pfn AS pf
but I don't want to hard code 3 and 7 in the penultimate line where 3 and 7 are the nodes contained in (pts). I tried the following but I am getting "Unclosed parenthesis" error
START s=node(1), t=node(4)
MATCH p=s-[*]-pt--t
WHERE SINGLE (n1 IN nodes(p)
WHERE id(n1)=id(t))
WITH DISTINCT pt AS pts, t
MATCH p=t-[*]-pfn FOREACH(pt in pts :
WHERE NONE (n IN nodes(p)
WHERE id(n)=id(pt)))
RETURN DISTINCT pfn AS pf
I think you can use the ALL predicate to ensures that for each node n in the path p there doesn't exist a node in pt that has the same id as the node n,
START s=node(1), t=node(4)
MATCH p=s-[*]-pt--t
WHERE SINGLE (n1 IN nodes(p)
WHERE id(n1)=id(t))
WITH DISTINCT collect(id(pt)) AS pts, t
MATCH p=t-[*]-pfn
WHERE ALL (n IN nodes(p)
WHERE NONE (pt IN pts
WHERE id(n)= pt))
RETURN DISTINCT pfn AS pf

Cypher query to check node connectivity

I'm new to neo4j and would really appreciate your help for this.
I have following graph created in neo4j.
n1----n2----n3----n4---n5
n1,n2,n3,n4,n5 all are nodes
--- : relationship_type_1 (REL)
Now given any set of nodes (in any order), I want to check whether these nodes are connected or not.
E.g. Given n1, n2, n3 ==> Connected.
Given n1, n3, n2, n4, n5 ==> Connected.
How should I formulate my cypher query to check connectivity?
Following query is working even if I change the order,
MATCH p=_1--_2--_3
WHERE _1.name?="Node1" and ALL (n in nodes(p)
WHERE n.name IN ["Node1", "Node2", "Node4"])
RETURN nodes(p);
on http://console.neo4j.org/?id=xl8pnl
but if I provide start nodes instead of using _1,_2 and change the order then it's not returning me the path. :(
http://console.neo4j.org/?id=xl8pnl
for following query,
START p1=node(6),p2=node(5),p3=node(4) MATCH p=p1--p2--p3
WHERE p1.name?="Node1" AND ALL (n IN nodes(p) WHERE n.name IN ['Node1' ,'Node3', 'Node2' , 'Node4'])
RETURN nodes(p)
it doesn't return the path as nodes are connected in node(6)-node(5)-node(4) order.
You need to list the different patterns that constitute the "connectedness" to you for instant by listing them explicitly like
console.neo4j.org/r/2w3poz
START p1=node(0),p2=node(4),p3=node(5)
RETURN
CASE
WHEN p1--p2--p3 OR p2--p1--p3 OR p1--p3--p2 OR p3--p2--p1 OR p3--p1--p2
THEN 'Connected'
ELSE 'Not connected'
END
Case 1:
2 paths found
MATCH p=_1--_2--_3--_4
WHERE _1.name?="Node1" and
ALL (n in nodes(p)
WHERE n.name IN ["Node1", "Node2", "Node3", "Node4"])
RETURN nodes(p);
Check it out here:
http://console.neo4j.org/?id=nn9yl6
in this case order dosen't matter
Case 2
(no path found)
Use node 1,2,4
MATCH p=_1--_2--_3
WHERE _1.name?="Node1" and ALL (n in nodes(p)
WHERE n.name IN ["Node1", "Node2", "Node4"])
RETURN nodes(p);
Check it out here:
http://console.neo4j.org/?id=xl8pnl

Resources