我可以在neo4j中创建和关联两个具有相同名称但不同ID的节点

时间:2015-01-08 14:49:18

标签: neo4j cypher

我在neo4j中创建了两个具有相同名称和标签但具有不同ID的节点:

CREATE (P:names {id:"1"})
CREATE (P:names{id:"2"})

我的问题是我是否可以在这两个节点之间建立关系:

MATCH (P:names),(P:names) 
WHERE P.id = "1" AND P.id = "2" 
CREATE (P)-[r:is_connected_with]->(P) RETURN r"

我尝试但它不起作用。 是不是我不应该创建具有相同名称的节点或有解决方法?

2 个答案:

答案 0 :(得分:3)

以下情况如何?

首先运行create语句:

CREATE (p1:Node {id:"1"}) // note, named p1 here
CREATE (p2:Node {id:"2"})

然后,进行匹配:

MATCH (pFirst:Node {id:"1"}), (pSecond:Node {id:"2"}) // and here we can call it something else
CREATE pFirst-[r:is_connected_with]->(pSecond)
RETURN r

基本上,您匹配两个节点(标签为Node)。在您的匹配中,您可以将其称为p1p2,但如果您愿意,可以更改这些标识符。然后,只需创建它们之间的关系。

您应创建具有相同名称的标识符。另请注意,p1p2不是节点的名称,它是此特定查询中标识符的名称。

编辑:从OP输入后,我创建了small Gist that illustrates some basics regarding Cypher

答案 1 :(得分:3)

@wassgren有关于如何修复查询的正确答案,但我可能会填写一些有关原因的详细信息,并且留下评论的时间太长。

描述节点或关系时冒号前的字符称为标识符,它只是表示Cypher查询中的节点/ rel的变量。 Neo4j有一些您没有遵循的命名约定,因此,它会使您的查询更难以阅读,并且将来您将更难获得帮助。最佳做法是:

  • 标识符以小写字母开头:person代替Person1p代替P
  • 标签是单数且首字母大写:(p1:Name),而非(p1:Names)(p1:names)(p1:name)
  • 关系都是上限,[r:IS_CONNECTED_WITH],而不是[r:is_connected_with],虽然这个一直被打破;-)

回到你的查询,它既不会起作用,也不符合惯例。

无效:

MATCH (P:names),(P:names) 
WHERE P.id = "1" AND P.id = "2" 
CREATE (P)-[r:is_connected_with]->(P) RETURN r

会工作,看起来好多了(!):

MATCH (p1:Name),(p2:Name) 
WHERE p1.id = "1" AND p2.id = "2" 
CREATE (p1)-[r:IS_CONNECTED_WITH]->(p2) RETURN r

但是,您的查询不起作用的原因是,通过编写MATCH (P:names),(P:names) WHERE P.id = "1" AND P.id = "2",您实际上是在说“查找节点,将其称为'P',ID为1和2”。这不是你想要的,显然不会起作用!

如果您尝试创建许多节点,则可以为要创建的每对节点重新运行此查询,并更改每次分配的ID。您也可以在一个查询中创建节点及其关系:

CREATE (p1:Name {id:"1"})-[r:IS_CONNECTED_WITH]->(p2:Name {id:"2"}) RETURN r

在应用程序中,只需在运行查询之前更改要分配给节点的ID。标识符是实例变量,它们在查询完成后消失。

编辑#1!

还有一件事,在应用中设置id属性并将其分配给数据库而不是依赖于Neo4j创建的内部ID 是最佳做法。我建议避免使用顺序ID,而是使用某些东西来创建唯一ID。在Ruby中,许多人使用SecureRandom::uuid来表示这一点,我确信你使用的是任何语言的并行。

编辑#2!

Neo4j支持整数属性。 {id:"1"}!= {id: 1}。如果您的字段应该是整数,请使用整数。