我可以在 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
)。在您的比赛中,您称它们为 p1
和 p2
,但您可以根据需要更改这些标识符。然后,简单地创建它们之间的关系。
您应该不创建具有相同名称的标识符。另请注意 p1
和 p2
不是节点的 name,它是此特定查询中标识符的名称。
编辑: 从 OP 输入后,我创建了一个 small Gist that illustrates some basics regarding Cypher.
@wassgren 对如何解决您的查询有正确的答案,但我也许可以填写一些关于原因的详细信息,而且太长了,无法在评论中留下。
描述节点或关系时冒号前的字符称为标识符,它只是一个代表 Cypher 查询中的 node/rel 的变量。 Neo4j 有一些您没有遵循的命名约定,因此,它使您的查询更难阅读,并且您将来更难获得帮助。最佳做法是:
- 标识符以小写开头:
person
而不是 Person1
,p
而不是 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}
。如果您的字段应该是整数,请使用整数。
我在 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
)。在您的比赛中,您称它们为 p1
和 p2
,但您可以根据需要更改这些标识符。然后,简单地创建它们之间的关系。
您应该不创建具有相同名称的标识符。另请注意 p1
和 p2
不是节点的 name,它是此特定查询中标识符的名称。
编辑: 从 OP 输入后,我创建了一个 small Gist that illustrates some basics regarding Cypher.
@wassgren 对如何解决您的查询有正确的答案,但我也许可以填写一些关于原因的详细信息,而且太长了,无法在评论中留下。
描述节点或关系时冒号前的字符称为标识符,它只是一个代表 Cypher 查询中的 node/rel 的变量。 Neo4j 有一些您没有遵循的命名约定,因此,它使您的查询更难阅读,并且您将来更难获得帮助。最佳做法是:
- 标识符以小写开头:
person
而不是Person1
,p
而不是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}
。如果您的字段应该是整数,请使用整数。