Lets say I have points a, b, c, d and a->b->c->d is related with next. Below is merge command for it.
merge (a:point{id:'a'})-[:next]-(b:point{id:'b'})-[:next]-(c:point{id:'c'})-[:next]-(d:point{id:'d'}) return a, b, c, d
Neo4j image of the merge
What I am looking for is a way to get all the points between a and d. Using below query I get the relationships, but how can I get list that contains b, c?
match p=(start:point)-[:next*]-(end:point)
with *, relationships(p) as r
where start.id ='a' and end.id = 'd'
return start, r, end
You can do
RETURN nodes(p)[1..-1]
to get the nodes except the first and last one.
Related
Node A is connected to Node E through different nodes B (B can be repeating), C and D etc as given below.
(A)--(C)--(D)--(E)
(A)--(B)--(C)--(D)--(E)
(A)--(B)--(B)--(C)--(D)--(E)
(A)--(B)--(B)--(B)--(C)--(D)--(E)
There could be up to 7 B nodes between A and C or no B node at all (like the first case above).
Question: How to get all the E1, E2, E3, E4 connected to A1 with a single query and return properties from all A, B, C, D and E nodes? I could not return the properties using the hops.
MATCH (A {Id:30})-[*1..6]-(E) RETURN DISTINCT A.Name, E.Name;
But we want to return B.Name (If there are multiple B nodes in the middle their names too), C.Name and D.Name too. Happy to skip hopping completely if required. Help please? Thanks in advance.
Try this
// in case there is always A,C and E, you can look for
// paths with length 3 to 6
MATCH path=(A)-[*3..6]-(E)
// return the name of each node in the same order
RETURN [n IN nodes(path) | n.name] AS nodeNames
Assuming A through E are node labels, this query should get all paths that match your pattern (with 0 to 7 B nodes between the A and C nodes), and return distinct lists of node Name values:
MATCH p=(:A)-[*..8]-(:C)--(:D)--(:E)
WHERE ALL(n IN NODES(p)[1..-3] WHERE 'B' IN LABELS(n))
RETURN DISTINCT [m IN NODES(p) | m.Name] AS names
In general, the query would be more efficient if you could also specify the relationship types and their directionality.
Suppose I have Red, Blue and Green nodes (R, B, G) and the relationships might look like this:
As you can see, R points to B and G also points to B. I want to match all R nodes where all the B nodes they point to are also related to a specific G node. How would I do this?
You can set this up on your own database by running something like this:
CREATE
(R1:Test_R),
(B1:Test_B),
(G:Test_G),
(R2:Test_R),
(B2:Test_B),
(R1)-[:TEST_LINK]->(B1),
(R1)-[:TEST_LINK]->(B2),
(R2)-[:TEST_LINK]->(B1),
(G)-[:TEST_LINK]->(B1)
RETURN
R1, R2, B1, B2, G
You can then query them by running something like this:
MATCH
(R:Test_R)-[:TEST_LINK]->(B:Test_B)
OPTIONAL MATCH
(B)<-[:TEST_LINK]-(G:Test_G)
RETURN
R,B,G
You can do it using a query something like the following:
MATCH
(R:Test_R)-[:TEST_LINK]->(B:Test_B)
WITH
{R: R, B: COLLECT(B) } AS d
MATCH
(G:Test_G)
WHERE
ID(G) = 5770 // Match our specific G node
AND ALL(b IN d.B WHERE (b)<-[:TEST_LINK]-(G) )
RETURN d.R
The ALL function will return true if all items in the list return true for the predicate specified:
ALL(<variable> IN <list> WHERE <predicate)
I'm trying to find all relations between node a and node b, and the relations could be multi-directions. For example,
a <- c -> b or a -> d -> b where c and d are nodes.
I've tried MATCH (a:PERSON {name: 'WD'})-[r*..3]-(b:PERSON{name: 'EK'}) RETURN r, a, b, but I got two isolated nodes, because the relation between a and b is: a <- c -> b.
Any help would be appreciated.
You can return the path if you need all the relationships and nodes in between.
Following query will
You can modify your query to return full paths instead of just nodes a and b as following:
MATCH paths=(a:PERSON {name: 'WD'})-[r*..3]-(b:PERSON{name: 'EK'})
RETURN paths
This will return paths of length up to 3, change it as you need.
I have a path that returns a number of, well, paths. nodes(path) looks like:
[a, b, c, d],
[a, b, e],
[a, f]
What I want is to get all the nodes. So converting that path to
a
b
c
d
e
f
would be great. I would like to continue using the nodes in further cypher statements so leaving them in a collection doesn't work for me.
Any ideas?
EDIT 1
MATCH(t:THING1 {id:"t1"})-[:AFFECTS]->(x:SOME_NODE), (t)-[:CHANGES]->(SOME_NODE)
MATCH p=shortestpath((s)-[MY_RELATION*0..4]->(x))
WITH collect(nodes(p)) as nodes
WITH REDUCE(output = [], r IN nodes | output + r) AS flat
This produces a collection of nodes. Now to convert it into rows and dedup it...
You could just unwind the collections of nodes from the paths and then return the distinct ones.
MATCH(t:THING1 {id:"t1"})-[:AFFECTS]->(x:SOME_NODE), (t)-[:CHANGES]->(SOME_NODE)
MATCH p=shortestpath((s)-[MY_RELATION*0..4]->(x))
UNWIND nodes(p) as n
RETURN DISTINCT n
Consider a Cypher query in the following form:
MATCH a-->b,a-->c,a-->d WHERE [some conditions on a, b, c and d] RETURN id(a),id(b),id(c),id(d)
The query above, probably as expected, will return all the combinations of candidate nodes for a, b, c, and d. So, for instance, if there are three candidates for b and four candidates for c, the total number of rows returned by the query will be 3 x 4 = 12. How can it be adjusted so the different matching nodes for each alias (a to d) is returned only once?
The following query is not a valid one, but should clarify what I have in mind:
MATCH a-->b,a-->c,a-->d WHERE [some conditions on a, b, c and d] RETURN distinct id(a), distinct id(b), distinct id(c), distinct id(d)
You can use distinct aggregation.
MATCH a-->b,a-->c,a-->d
WHERE [some conditions on a, b, c and d]
RETURN collect(distinct id(a)) as ids_a,collect(distinct id(b)) as ids_b,
collect(distinct id(c)) as ids_c,collect(distinct id(d)) as ids_d;