Создание простой структуры октодерева в Neo4j с использованием Cypher
3 ответа
Вы можете сделать это в Cypher, создав рут:
CREATE (root:Root:Leaf);
затем повторяем запрос, добавляя уровень столько раз, сколько вам нужно (в какой-то момент транзакция станет слишком большой):
MATCH (n:Leaf)
REMOVE n:Leaf
FOREACH (i IN range(0, 7) |
CREATE (n)-[:CONTAINS]->(:Node:Leaf {value: coalesce(n.value, "") + toString(i)}));
Вы можете использовать Cypher для создания дерева, если вы знаете его высоту заранее. Для простоты я сгенерировал бинарные деревья (с коэффициентом ветвления 2).
WITH 0 as root, range(1,2) AS branches
WITH root as root, branches AS l1s, branches AS l2s
UNWIND l1s AS l1
UNWIND l2s AS l2
MERGE (n0:TreeNode {name: root})
MERGE (n1:TreeNode {name: l1})
MERGE (n2:TreeNode {name: l1+"_"+l2})
MERGE (n0)-[:X]->(n1)
MERGE (n1)-[:X]->(n2)
Это приводит к следующему дереву:
Пояснение: для дерева k уровней мы копируем branches
Переменные k-1 раз, и раскрутите каждый список. Это создает декартово произведение, следовательно, производит листовые узлы. Для (полных) бинарных деревьев k уровней это приводит к 2^(k-1) листовым узлам. (Это также работает для октодеревьев, которые будут иметь 8^(k-1) уровней.)
Мы объединяем номера уровней с подчеркиванием, чтобы создать уникальные имена переменных для каждого уровня. Идентификаторы могут быть запрошены так:
WITH 0 as root, range(1,2) AS branches
WITH root as root, branches AS l1s, branches AS l2s
UNWIND l1s AS l1
UNWIND l2s AS l2
RETURN root, l1, l1+"_"+l2
Это приводит к:
╒════╤═══╤═════════╕
│root│l1 │l1+"_"+l2│
╞════╪═══╪═════════╡
│0 │1 │1_1 │
├────┼───┼─────────┤
│0 │1 │1_2 │
├────┼───┼─────────┤
│0 │2 │2_1 │
├────┼───┼─────────┤
│0 │2 │2_2 │
└────┴───┴─────────┘
Теперь все, что нам нужно сделать, это создать узлы и отношения, обращая внимание на то, что узлы / ребра создаются только один раз. Это обеспечивается с помощью MERGE
, (MERGE
может показаться хитрым на первый взгляд, но есть хорошие объяснения.)
Если вы хотите добавить дополнительные уровни, обновите запрос следующим образом:
- определить новую переменную из веток, например
l3s
- раскрутить новую переменную, например
l3
- создать дополнительные узлы для нового уровня с добавленным именем переменной, например
MERGE (n3:TreeNode {name: l1+"_"+l2+"_"+l3})
- создать новые ребра с предыдущего уровня, например
MERGE (n2)-[:X]->(n3)
Конечно, вы также можете использовать числа для узлов. Вместо добавления подчеркивания вам нужно сгенерировать новый числовой идентификатор для каждого узла.
WITH range(1,2) AS branches
WITH branches AS l1s, branches AS l2s
UNWIND l1s AS l1
UNWIND l2s AS l2
MERGE (n0:TreeNode {number: 0})
MERGE (n1:TreeNode {number: l1})
MERGE (n2:TreeNode {number: 2*l1+l2})
MERGE (n0)-[:X]->(n1)
MERGE (n1)-[:X]->(n2)
Результат:
Я не уверен, что это может сделать только Cypher, но вы можете использовать язык программирования и подключиться к neo4j для создания узлов и связей.
В PHP например:
function create_children($parent){
print "\n$parent: ";
for ($i=0; $i<=7;$i++) {
$node_id = (int) "$parent"."$i";
$children[] = $node_id;
print "$node_id,";
// create children nodes
// CREATE (child:node) SET node_id = $node_id
//create relationship here
// MATCH (parent:node) where node_id = $parent
// CREATE (parent)-[r:parent_of]->(child)
}
return $children;
}
function create_tree ($root, $depth) {
if ($depth ==0) return;
else{
$children = create_children($root);
$depth--;
foreach ($children as $child) {
create_tree($child, $depth);
}
}
}
// MAIN
// CREATE (parent:node) SET node_id=0;
create_tree(0,3);
Конечно, там, где находятся операторы cypher, вам нужно подключиться к вашему экземпляру neo4j и выполнить эти операторы.
Если вы не уверены, как это сделать, вы можете просто распечатать операторы шифров, а затем вставить их в нео-оболочку или браузер.
вот результат бега create_tree(0,2)
Выходные данные показывают родителя, сопровождаемого его восемью детьми
0: 00,01,02,03,04,05,06,07,
00: 00,01,02,03,04,05,06,07,
01: 10,11,12,13,14,15,16,17,
02: 20,21,22,23,24,25,26,27,
03: 30,31,32,33,34,35,36,37,
04: 40,41,42,43,44,45,46,47,
05: 50,51,52,53,54,55,56,57,
06: 60,61,62,63,64,65,66,67,
07: 70,71,72,73,74,75,76,77,
дайте мне знать, если это то, что вы искали