Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
01-15-2020 07:43 AM
Hi,
I'm working on a project that stores our customers relationships in Neo4j. Our model looks like this: (Client) - [PARENT_OF] - (Client). Each Client can have up to 3 different labels assigned.
I made a query that at first glance should work but it's not returning the nodes from the path as a List.
Here is my query "MATCH p = (n:Client)-[r:PARENT_OF*]->(t:Client) WHERE n.code="MYCODE" RETURN nodes(p) as nodes , labels(n) as labels"
In the docs I read that the nodes() function takes a path as parameter and then outputs the nodes from the path as a list. When I execute the query from the browser it returns each node from nodes as an array containing the parent node and its child.
Nodes | Labels
[ ["Label1", "Label2"]
{node1},{node2}
],
[ ["Label1", "Label2"]
{node1},{node3}
],
[ ["Label1", "Label2"]
{node2},{node4}
]
In my backend (Java + Spring) while debugging I get the labels correctly but it isnt mapping the Nodes as they aren't a single Entity but an array as I said.
Below I attached an image from the browser output when I run the query. How can I make it so there's only one node instead of 2?
Thanks
Solved! Go to Solution.
01-16-2020 05:32 AM
Hi @marcos.stival,
Welcome to the community!
What you're looking for is a way to flatten your list of lists, and then unwind (or pivot them).
MATCH p = (n:Client)-[r:PARENT_OF*]->(t:Client)
WHERE n.Code="MYCODE"
// nodes(p) is an array of arrays. the reduce is similar to a flat function.
WITH reduce(output = [], n IN nodes(p) | output + n ) as nodeCollection
// here we take the single row of the flattened array and pivot it to rows.
UNWIND nodeCollection as client
// once we have each client in it's own row, then we call labels
// Also don't forget the distinct!
// Remember the arrays simply flatten out each path, 2 of your nodes show up in multiple paths.
RETURN distinct client, labels(client)
I hope that was informative while also helping answer the question.
If you have any other follow on questions, let me know
-Mike
01-15-2020 10:33 AM
Hi,
It's not still clear what you are trying to do and what is the expected output. You get 3 rows in the output because there are 3 paths. nodes
returns all nodes in a path incuding the first and the last nodes. If you don't need the first one, you can use the tail
function. For example, tail([1,2,3])
returns [2,3]
. So just pass the nodes(p)
to the tail
function and you will get all nodes but the first one.
Sorry if I am not answering your question. I did my best given the level of details I found in the question.
01-16-2020 03:27 AM
Hi Shan, thanks for you reply.
The expected output is a list of the nodes from the path.
I have a path that looks like this :
I want the output from my cypher query to return a list of those nodes with each node's label (most nodes usually have 2 labels)
For the path from the image it should return a list with 7 nodes. Instead when I run the query I get the OP image result which is an array containing the parent node and a child.
This is the response I need:
[
{
"node": {nodedata},
"labels" : ["label1","label2"]
},
{
"node": {nodedata},
"labels" : ["label1","label2"]
},
{
"node": {nodedata},
"labels" : ["label1","label2"]
}
]
This is the response I got:
[
{
"nodes": [{node1},{node2}]
"labels": ["label1","label2"]
},
{
"nodes": [{node1},{node2}]
"labels": ["label1","label2"]
},
{
"nodes": [{node1},{node2}]
"labels": ["label1","label2"]
},
{
"nodes": [{node1},{node2}]
"labels": ["label1","label2"]
}
]
01-16-2020 05:32 AM
Hi @marcos.stival,
Welcome to the community!
What you're looking for is a way to flatten your list of lists, and then unwind (or pivot them).
MATCH p = (n:Client)-[r:PARENT_OF*]->(t:Client)
WHERE n.Code="MYCODE"
// nodes(p) is an array of arrays. the reduce is similar to a flat function.
WITH reduce(output = [], n IN nodes(p) | output + n ) as nodeCollection
// here we take the single row of the flattened array and pivot it to rows.
UNWIND nodeCollection as client
// once we have each client in it's own row, then we call labels
// Also don't forget the distinct!
// Remember the arrays simply flatten out each path, 2 of your nodes show up in multiple paths.
RETURN distinct client, labels(client)
I hope that was informative while also helping answer the question.
If you have any other follow on questions, let me know
-Mike
01-16-2020 05:46 AM
Oh my god Mike, thanks for your reply it works like a charm!
I have yet to understand how flat functions works and the syntax for the reduce function too but for the sake of the query I think I get it.
Thanks again.
Have a very nice day!
01-16-2020 06:22 AM
Happy to help.
for using the reduce to flatten,
the code reduce(output = [ ], n in nodes(p) | output +n)
is translated to
output = [ ]
=> the output starts off as an empty array .n in nodes(p)
=> for each element n in the collection nodes(p)ouput + n
=> for each n do this to transform from n to output.@mark.needham also wrote a good explanation of how to use reduce to flatten data here
Neo4j: Cypher - Flatten a collection
-Mike
All the sessions of the conference are now available online