问题
Given a forest of trees in a Neo4j REST server, I`m trying to return a single tree given the root vertex.
Being each tree quite large, I need a de-duplicated list of all vertices and edges in order to be able to reconstruct the full tree on the client side.
I tried multiple combinations around MATCH (r:root)-[*]->()
but they return any path starting from the root, thus with lots of duplicates:
MATCH p = (r:root)-[*]->(x)
RETURN nodes(p) AS Vertices, rels(p) AS Edges";
this returns each and every path as follows, repeating each node every time:
a->b
a->b->c
a->b->c->d
etc...
Instead, I need a result having
{
Vertices: [a, b, c, d],
Edges: [[a, b], [b, c], [c, d]]
}
I'm using Node.js with Seraph, if relevant, but I`m not strictly bound to that library.
回答1:
So first off, you might want to add a WHERE
clause to make sure that your path is always ending with a leaf:
MATCH p = (r:root)-[*]->(x)
WHERE NOT(x-->())
RETURN nodes(p) AS Vertices, rels(p) AS Edges";
So secondly, if you want to get all of the nodes and relationships in one go, you may need to execute two queries:
MATCH p = (r:root)-[*]->(x)
WHERE NOT(x-->())
UNWIND nodes(p) AS Vertex
RETURN DISTINCT Vertex;
MATCH p = (r:root)-[*]->(x)
WHERE NOT(x-->())
UNWIND rels(p) AS Edge
RETURN DISTINCT startNode(Edge), endNode(Edge);
Update (Michael)
MATCH p = (r:root)-[*]->(x)
WHERE NOT(x-->())
UNWIND nodes(p) AS Vertex
WITH collect(DISTINCT Vertex) as nodes, p
UNWIND rels(p) AS Edge
RETURN nodes, collect(distinct Edge) as rels
Update2 (Michael)
I found an even more compact way
MATCH p = (:root)-[r*]->(x)
RETURN collect(DISTINCT id(x)) as nodes, [r in collect(distinct last(r)) | [id(startNode(r)),id(endNode(r))]] as rels
If you also want to include the root node, use *0..
来源:https://stackoverflow.com/questions/30940411/fetch-a-tree-with-neo4j