cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

What exactly happend when we UNWIND a path and save it as variable

hi all

I need more  clarity of UNWIND key word and also My issue out here is I have query like this:-

profile match p=(v:Vendor)-[*0..30]->(m:MatPlant)-[*0..30]->(d:MatPlant)-[*0..30]->(c:MatPlant)-[*0..30]->(u:Customer)
where u.node_id in ["yxz"] and v.node_id in ["xyz"] and d.node_id in ['abc]
and c.node_id in ['US000'] and m.node_id in ['00A06']
unwind (nodes(p)) as t
with collect(p) as p_list,t
optional match k=(t)-[:MfgMatPlant_To_WorkCenter]->(wc:WorkCenter)
with p_list + collect(DISTINCT k) as result_list
unwind result_list as result
return result
 
In the optional match command I am trying to get workcenter nodes included When Its searching, i know that workcenter  will be connected to only matplant node(m,d,c) and intermediate matplant nodes  in flow but not Vendor and customer how to remove these vendor node from the list 
2 ACCEPTED SOLUTIONS

The 'unwind' clause converts a list of values into rows of values. This will be done row-by-row when you have query results with multiple rows. Further, any variables associated with the row will be appended to each row created by the unwind. The following is an example.

with [1,2,3] as numbers, 'a' as a, 'b' as b
unwind numbers as number
return number, a, b

The result of the unwind is the following. Notice how the values of 'a' and 'b' are  appended to each line generated from unwinding the 'numbers' list. 

Screen Shot 2022-08-01 at 6.04.33 PM.png

The 'unwind' will be done for each result row from a query, thus if you had 10 rows and each had a list of 5 elements, the unwind would result in 50 rows. 

Assume in your query that you have 5 separate paths that result from the match, say p1, p2, ..., p5. Each may have a different number of nodes. The result of your 'unwind nodes(p) as t' line may look something like the following, where I have rows for each node in each path.

Screen Shot 2022-08-01 at 6.14.05 PM.png

The result of your next line 'collect(p) as p_list, t' is to group each row by the value of 't', and collect the paths 'p' that have the same value of 't'. Recall 't' represents the nodes, so the data will be grouped into lines that have the same node and collect all the paths that that node is a part of. Remember there could be nodes common to more than one path. For illustration purposes, assuming you have 'N' distinct nodes across all paths, then you output would look something like the following:

Screen Shot 2022-08-01 at 6.22.32 PM.png

Next, your 'optional match' will be performed for each row (distinctNode) shown in the table above. This will generate zero to 'M' paths for each distance node ('t'). If your data only allows for one potential path, then you can have either zero or one path. 

The final 'with' clause is collecting all these paths for a single distinct node 't' and adding these paths to the p_list list that contains all the paths that the distinct node 't' is a member of. Assuming multiple potential paths 'k', you 'result_list' will look something like the following table:

Screen Shot 2022-08-01 at 6.30.43 PM.png

When you finally 'unwind' result_list, you get a set of rows where each row contains one path from each of the lists in the table above. It looks like you could get duplicate paths 'p', so you should 'return distinct result' instead. 

Is this what you are looking for, a list of all the paths 'p' and 'k', or do you just want all the nodes along all these paths?  If it is the later, you could probably get this more efficiently with an APOC path procedure. 

View solution in original post

Sure, you can remove them list before you unwind or after the unwind. 
1. Deleting from the list:

with [x,y,z,k,l] as list

with [n in list where n<>x or n<>z] as newList

2. delete following unwind

with [x,y,z,k,l] as list

unwind list as s

with s

where s<>x or s<>z

do something on ‘s’

View solution in original post

8 REPLIES 8

ameyasoft
Graph Maven

Try this:

match (v:Vendor)
where v.node_id in ["xyz"]

CALL apoc.path.spanningTree(v, {labelFilter:'MatPlant|Customer', relationshipFilter:'-MfgMatPlant_To_WorkCenter', maxLevel:30}) yield path
with nodes(path) as n1, relationships(path) as r1, length(path) as lvl
unwind n1 as n2
unwind r1 as r2

with labels(n2) as lbl
unwind lbl as lbl1
return distinct lbl1

Check to see if you get WorkCenter node label

No I couldnt able to see any data coming

Run this and post the result as an image:

match (v:Vendor)
where v.node_id in ["xyz"]

CALL apoc.path.spanningTree(v, {labelFilter:'MatPlant|Customer', relationshipFilter:'-MfgMatPlant_To_WorkCenter', maxLevel:6}) yield path
return path

I used the relationship and node names as shown in your post.
Run this query and post the result as image:

call apoc.meta.graph()

Run your query with small change and post the results:

match p=(v:Vendor)-[*0..30]->(m:MatPlant)-[*0..30]->(d:MatPlant)-[*0..30]->(c:MatPlant)-[*0..30]->(u:Customer)
where u.node_id in ["yxz"] and v.node_id in ["xyz"] and d.node_id in ['abc]
and c.node_id in ['US000'] and m.node_id in ['00A06']
unwind (nodes(p)) as t

return distinct labels(t) as lbl

with collect(p) as p_list 

return p_list 

The result is same as return p.

The 'unwind' clause converts a list of values into rows of values. This will be done row-by-row when you have query results with multiple rows. Further, any variables associated with the row will be appended to each row created by the unwind. The following is an example.

with [1,2,3] as numbers, 'a' as a, 'b' as b
unwind numbers as number
return number, a, b

The result of the unwind is the following. Notice how the values of 'a' and 'b' are  appended to each line generated from unwinding the 'numbers' list. 

Screen Shot 2022-08-01 at 6.04.33 PM.png

The 'unwind' will be done for each result row from a query, thus if you had 10 rows and each had a list of 5 elements, the unwind would result in 50 rows. 

Assume in your query that you have 5 separate paths that result from the match, say p1, p2, ..., p5. Each may have a different number of nodes. The result of your 'unwind nodes(p) as t' line may look something like the following, where I have rows for each node in each path.

Screen Shot 2022-08-01 at 6.14.05 PM.png

The result of your next line 'collect(p) as p_list, t' is to group each row by the value of 't', and collect the paths 'p' that have the same value of 't'. Recall 't' represents the nodes, so the data will be grouped into lines that have the same node and collect all the paths that that node is a part of. Remember there could be nodes common to more than one path. For illustration purposes, assuming you have 'N' distinct nodes across all paths, then you output would look something like the following:

Screen Shot 2022-08-01 at 6.22.32 PM.png

Next, your 'optional match' will be performed for each row (distinctNode) shown in the table above. This will generate zero to 'M' paths for each distance node ('t'). If your data only allows for one potential path, then you can have either zero or one path. 

The final 'with' clause is collecting all these paths for a single distinct node 't' and adding these paths to the p_list list that contains all the paths that the distinct node 't' is a member of. Assuming multiple potential paths 'k', you 'result_list' will look something like the following table:

Screen Shot 2022-08-01 at 6.30.43 PM.png

When you finally 'unwind' result_list, you get a set of rows where each row contains one path from each of the lists in the table above. It looks like you could get duplicate paths 'p', so you should 'return distinct result' instead. 

Is this what you are looking for, a list of all the paths 'p' and 'k', or do you just want all the nodes along all these paths?  If it is the later, you could probably get this more efficiently with an APOC path procedure. 

Thanks understood How unwind works.

Consider we have list[x,y,z,k,l] i have unwinded into S variable it so i will get like

x

y

z

k

l

is there any way that i can delete x,z  from s?and get all the details of s

Sure, you can remove them list before you unwind or after the unwind. 
1. Deleting from the list:

with [x,y,z,k,l] as list

with [n in list where n<>x or n<>z] as newList

2. delete following unwind

with [x,y,z,k,l] as list

unwind list as s

with s

where s<>x or s<>z

do something on ‘s’