从CSV加载以创建二叉树

时间:2016-12-24 17:51:30

标签: csv neo4j

我需要在Neo4j中创建一个二叉树。我开始创建两个CSV,一个用于顶点,一个用于边缘,然后我启动了两个查询来创建整个树。

我以为我只用一个查询就可以创建整个树。 我从哪里开始的CSV是这样的:

"parent","child_1","child_1_attr1","child_1_attr2","edge_1_attr1","edge_1_attr2","child_2","child_2_attr1","child_2_attr2","edge_2_attr1","edge_2_attr2"
"vertex_1","vertex_2","2","5","4","1","vertex_3","5","3","2","2"
"vertex_2","vertex_4","3","5","2","3","vertex_5","4","4","4","3"
"vertex_3","vertex_6","2","1","2","4","vertex_7","2","2","5","5"
"vertex_4","vertex_8","4","4","4","5","vertex_9","2","3","2","5"
"vertex_5","vertex_10","1","1","3","3","vertex_11","1","3","2","3"
"vertex_6","vertex_12","3","1","1","1","vertex_13","1","2","5","1"
"vertex_7","vertex_14","4","2","2","1","vertex_15","2","5","4","3"

然后我尝试了这个查询:

LOAD CSV WITH HEADERS FROM 'file:///Prova1.csv' AS line
Match (p:Vertex {name: line.parent})
Create (c1:Vertex {name: line.child_1, attr1: line.child_1_attr1, attr2: line.child_1_attr2})
Create (c2:Vertex {name: line.child_2, attr1: line.child_2_attr1, attr2: line.child_2_attr2})
Create (p)<-[:EDGE {attr1: line.edge_1_attr1, attr2: line.edge_1_attr2}]-(c1)
Create (p)<-[:EDGE {attr1: line.edge_2_attr1, attr2: line.edge_2_attr2}]-(c2)

在此查询之前,我手动创建第一个顶点,然后运行此查询,但我得到的唯一结果是创建顶点1,2和3。 它应该匹配父(总是已经创建),然后创建两个孩子,然后它应该将这两个孩子连接到他的父亲。

谁能帮帮我?

3 个答案:

答案 0 :(得分:1)

您的执行视图可能是,对于每一行/每行,执行所有Cypher代码,然后对下一行/行重复此操作直到完成,这是不正确的。

相反,每个Cypher操作都将对所有行执行,然后下一个Cypher操作将对所有行执行等。

这意味着您的MATCH操作:

Match (p:Vertex {name: line.parent})

同时在CSV中的所有行上执行,然后才会进行下一个操作(您的CREATE,对所有行执行操作),依此类推。

由于您声明手动创建了第一个顶点,该顶点是唯一一个将匹配的顶点,因此CRECH语句尚未执行,因此MATCH中的所有其他行都将失败,因此这些节点不会不存在。这意味着只会创建两个顶点,即那个完全匹配的节点的子节点。

导入CSV数据以首先创建所有节点,然后使用单独的CSV处理来匹配已创建的节点并创建相关关系通常是一种很好的做法。

但是,如果你想在一个目标中创建所有内容,你可能希望在各个地方使用MERGE,但如果你不完全理解MERGE的行为,这也很棘手(这就像尝试匹配,如果没有找到匹配,则为CREATE)或者不完全理解Cypher的执行方式(如本例所示)。

您还希望根据唯一节点值而不是所有属性进行合并,并设置其余属性。在相关标签/属性上具有唯一约束或索引(以适用者为准)以加快执行速度也特别有用,尤其是随着图形大小的增加。

此查询可能有效。

LOAD CSV WITH HEADERS FROM 'file:///Prova1.csv' AS line
MERGE (p:Vertex {name: line.parent})
MERGE (c1:Vertex {name: line.child_1})
SET c1.attr1 = line.child_1_attr1, c1.attr2 = line.child_1_attr2
MERGE (c2:Vertex {name: line.child_2})
SET c2.attr1 = line.child_2_attr1, c2.attr2 = line.child_2_attr2
Create (p)<-[:EDGE {attr1: line.edge_1_attr1, attr2: line.edge_1_attr2}]-(c1)
Create (p)<-[:EDGE {attr1: line.edge_2_attr1, attr2: line.edge_2_attr2}]-(c2)

这个工作的原因是,当您为所有父节点完成第一个MERGE时,将在图中创建所有父节点(或者更确切地说,将成为父节点)。

因此,当我们为您的子节点达到MERGE时,这将匹配图中已创建的大多数节点...此时将创建的唯一新节点将是叶节点,这些节点不会是由您的第一个MERGE创建,因为他们不会成为任何其他节点的父级,并且不会显示在CSV的父列中。

答案 1 :(得分:0)

由于某种原因,导入查询无效,因为您首先匹配父项,然后创建节点和关系。我以这种方式修改了查询,它现在正在运行:

LOAD CSV WITH HEADERS FROM 'file:///test.csv' AS line
CREATE (c1:Vertex {name: line.child_1, attr1: line.child_1_attr1, attr2: line.child_1_attr2}), 
       (c2:Vertex {name: line.child_2, attr1: line.child_2_attr1, attr2: line.child_2_attr2}) WITH c1,c2, line
MATCH (p:Vertex {name:line.parent}) CREATE (p)<-[:EDGE {attr1: line.edge_1_attr1, attr2: line.edge_1_attr2}]-(c1), 
      (p)<-[:EDGE {attr1: line.edge_2_attr1, attr2: line.edge_2_attr2}]-(c2)

因此,如果您首先创建节点然后匹配父节点并创建关系,则查询正在运行。结果如下:

enter image description here

我会调查你的查询,找出它无法正常工作的原因,因为我真的不明白为什么它不起作用。

答案 2 :(得分:0)

foreach (num in range(1,15) |
merge (parent:Node {number: num})
merge (left:Node {number: num + num})
merge (right:Node {number: num + num + 1})
merge (left)<-[:LEFT]-(parent)-[:RIGHT]->(right)
)

说明: 这创建了具有31个节点的完美二叉树结构。然后,您可以在CSV中包含相同的数字,以查找并向每个相应编号的节点添加属性。

在二叉树中,如果在第一个(根或最顶层节点)上包含值为1的数字属性,则将每个后续节点的数值增加1(从左到右;从上到下),然后你得到一个方便的数学关系,每个节点的左边孩子都有一个父亲的数字+数字的数值,而右边的孩子是数字+数字+ 1.