Получить дерево с Neo4j
Учитывая лес деревьев на REST-сервере Neo4j, я пытаюсь вернуть одно дерево с заданной корневой вершиной.
Поскольку каждое дерево достаточно велико, мне необходим дедуплицированный список всех вершин и ребер, чтобы можно было восстановить полное дерево на стороне клиента.
Я пробовал несколько комбинаций вокруг MATCH (r:root)-[*]->()
но они возвращают любой путь, начиная с корня, таким образом, с большим количеством дубликатов:
MATCH p = (r:root)-[*]->(x)
RETURN nodes(p) AS Vertices, rels(p) AS Edges";
это возвращает каждый путь следующим образом, повторяя каждый узел каждый раз:
a->b
a->b->c
a->b->c->d
так далее...
Вместо этого мне нужен результат, имеющий
{
Vertices: [a, b, c, d],
Edges: [[a, b], [b, c], [c, d]]
}
Я использую Node.js с Seraph, если это уместно, но я не строго привязан к этой библиотеке.
1 ответ
Итак, во-первых, вы можете добавить WHERE
предложение, чтобы убедиться, что ваш путь всегда заканчивается листом:
MATCH p = (r:root)-[*]->(x)
WHERE NOT(x-->())
RETURN nodes(p) AS Vertices, rels(p) AS Edges";
Во-вторых, если вы хотите получить все узлы и отношения за один раз, вам может потребоваться выполнить два запроса:
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);
Обновление (Майкл)
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
Обновление 2 (Майкл)
Я нашел еще более компактный способ
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
Если вы также хотите включить корневой узел, используйте *0..