我正试图建立一种将一个人与城市联系起来的关系->状态->国家,而不重新创建城市/州/国家节点和关系(如果它们已经存在的话(-所以我的图中只有一个美国节点,例如
我从一个人开始
CREATE (p:Person {name:'Omar', Id: 'a'})
RETURN p
那么我想将其转换为带有apoc的apoc.do.case
语句或者如果找不到节点或与现有节点匹配,则使用创建新节点的唯一约束将其转换为一个合并语句
// first case where the city/state/country all exist
MATCH (locality:Locality{name:"San Diego"})-[:SITUATED_IN]->(adminArea:AdministrativeArea { name: 'California' })-[:SITUATED_IN]->(country:Country { name: 'USA' })
MERGE (p)-[:SITUATED_IN]->(locality)-[:SITUATED_IN]->(adminArea)-[:SITUATED_IN]->(country)
return p
// second case where only state/country exist
MATCH (adminArea:AdministrativeArea { name: 'California' })-[:SITUATED_IN]->(country:Country { name: 'USA' })
MERGE (p)-[:SITUATED_IN]->(locality:Locality{name:"San Diego"})-[:SITUATED_IN]->(adminArea)-[:SITUATED_IN]->(country)
return p
// third case where only country exists
MATCH (country:Country { name: 'USA' })
MERGE (p)-[:SITUATED_IN]->(locality:Locality{name:"San Diego"})-[:SITUATED_IN]->(adminArea:AdministrativeArea { name: 'California' })-[:SITUATED_IN]->(country)
return p
// last case where none of city/state/country exist, so I have to create all nodes + relations
MERGE (p)-[:SITUATED_IN]->(locality:Locality{name:"San Diego"})-[:SITUATED_IN]->(adminArea:AdministrativeArea { name: 'California' })-[:SITUATED_IN]->(country:Country { name: 'USA' })
return p
这里的关键是我只想得到一个(加利福尼亚州(->(美国(。我不想要那些节点&获取重复的关系
- 使用
MATCH
的查询永远不会指定您想要的Person
。像p
这样的变量名只在查询的生命周期内存在(有时甚至没有那么长(。因此,p
在MATCH
查询中未绑定,并且可能导致MERGE
子句创建空节点。您需要将MATCH (p:Person {Id: 'a'})
添加到这些查询的开头(假设所有人都有唯一的Id值( - 每个查询都不应该负责确保所有需要的位置都存在并正确连接——这对每个查询来说都太复杂了,而且开销太大了。相反,您应该在需要之前分别创建适当的位置和位置间关系。如果事实上,创建一个位置以创建与其相关联的所有关系应该是每个查询的责任
- 如果模式中的每一个东西都已经存在,
MERGE
将不会创建指定的模式,因此为了避免重复,MERGE模式最多应该有一个可能不存在的东西。因此,一个MERGE
模式最多应该有1个关系,如果它有一个关系,那么2个端节点应该已经绑定(例如,通过MATCH
子句(
一旦Locality
节点和位置间关系存在,就可以添加这样的人:
MATCH (locality:Locality {name: "San Diego"})
MERGE (p:Person {Id: 'a'}) // create person if needed, specifying a unique identifier
ON CREATE SET p.name = 'Omar'; // set other properties as needed
MERGE (p)-[:SITUATED_IN]->(locality) // create relationship if necessary
以上注意事项应该有助于设计用于创建Locality
节点和位置间关系的代码。
最后,我使用的解决方案要简单得多,它是一系列合并。
match (person:Person {Id: 'Omar'}) // that should be present in the graph
merge (country:Country {name: 'USA'})
merge (state:State {name: 'California'})-[:SITUATED_IN]->(country)
merge (city:City {name: 'Los Angeles'})-[:SITUATED_IN]->(state)
merge (person)-[:SITUATED_IN]->(city)
return person;