Создание простой структуры октодерева в Neo4j с использованием Cypher

Я хотел бы создать структуру октодерева в Neo4j, используя Cypher. Я хотел бы создать что-то похожее на иллюстрацию ниже:

октри

Любые идеи о том, как это можно реализовать без необходимости создавать каждый узел и связь «вручную»?


person edwpea    schedule 25.11.2016    source источник


Ответы (3)


Вы можете использовать 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)

Конечно, вы также можете использовать числа для узлов. Вместо добавления символов подчеркивания вам нужно сгенерировать новый числовой «id» для каждого узла.

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)

Результат:

введите здесь описание изображения

person Gabor Szarnyas    schedule 25.11.2016

Вы можете сделать это в 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)}));
person Frank Pavageau    schedule 25.11.2016

Я не уверен, что только шифр может это сделать, но вы можете использовать язык программирования и подключиться к 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);

Конечно, там, где находятся операторы шифрования, вам нужно подключиться к экземпляру neo4j и выполнить эти операторы.
Если вы не знаете, как это сделать, вы можете просто распечатать операторы шифрования, а затем вставить их в оболочку neo или browser
вот результат выполнения 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,

дайте мне знать, если это то, что вы искали

person Albert s    schedule 25.11.2016