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

Can I create and relate two nodes with the same name but different ids in neo4j

我在 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"

我试过了,但没用。 是我不应该创建具有相同名称的节点还是有解决方法?

下面的怎么样?

首先 运行 创建语句:

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 不是节点的 name,它是此特定查询中标识符的名称。

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

@wassgren 对如何解决您的查询有正确的答案,但我也许可以填写一些关于原因的详细信息,而且太长了,无法在评论中留下。

描述节点或关系时冒号前的字符称为标识符,它只是一个代表 Cypher 查询中的 node/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",您实际上是在说 "find a node, call it 'P', with an ID of both 1 and 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}。如果您的字段应该是整数,请使用整数。