使用Cypher在Neo4j中创建一个简单的八叉树结构

时间:2016-11-25 18:13:46

标签: neo4j cypher octree

我想使用Cypher在Neo4j中创建一个八叉树结构。我想创建类似于下图的内容:

http://sqlfiddle.com/#!9/d86a7a/15

关于如何实现这一点的任何想法,而无需“手动”创建每个节点和关系?

3 个答案:

答案 0 :(得分:1)

如果您事先知道树的高度,可以使用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)

这导致以下树:

enter image description here

说明:对于k级的树,我们将branches个变量复制k-1次,然后展开每个列表。这会产生笛卡尔积,从而产生叶节点。对于k级的(全)二叉树,这导致2 ^(k-1)个叶节点。 (这也适用于具有8 ^(k-1)级别的八叉树。)

我们将级别的数量与下划线组合在一起,为每个级别创建唯一的变量名称。可以这样查询ID:

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一开始可能看起来很棘手,但有good explanations。)

如果要添加其他级别,请按以下方式更新查询:

  • 从分支中定义一个新变量,例如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)

结果:

enter image description here

答案 1 :(得分:1)

您可以通过创建根目录在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)}));

答案 2 :(得分:0)

我不确定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实例并执行这些语句 如果您不确定如何操作,可以打印出cypher语句,然后将它们粘贴到neo shell或浏览器中 这是运行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,

如果您正在寻找

,请告诉我