2

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.

PEER
  • 243
  • 3
  • 11

1 Answers1

11

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..

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
Brian Underwood
  • 10,746
  • 1
  • 22
  • 34
  • You can also combine the two queries with a union, and you only need the second one because it also gives you all nodes :) – Michael Hunger Jun 19 '15 at 21:20
  • 1
    There are some errors in the query, WHERE NOT(x-->()) leads to extraneous input >. UNWIND nodes(p) AS Vertex leads to mismatched inputs unwind, nodes and AS. What shall be the correct query? – harshvardhan Jun 24 '18 at 10:09