neo4j cypher更新现有节点或创建新节点

时间:2014-08-07 08:34:47

标签: merge neo4j cypher

我有一个图表,大约有900万个节点,以及1200万个关系。对于图中的每个节点,每个相应节点都有一个属性子集,它们通过Label形成节点的唯一标识。该图由各种数据源更新,这些数据源增加图中的现有节点,或者如果节点不存在则创建新节点。我不想在更新期间根据图表中的唯一属性集创建重复项。

例如,我在图表中有人物,他们的唯一性由他们的名字和姓氏决定。以下代码是创建两个不同的人:

CREATE (p:Person{first:"barry",last:"smith",height:187});
CREATE (p:Person{first:"fred",last:"jones",language:"welsh"});

稍后,我从其中一个数据源收到以下数据记录(每行一个):

first: "fred", last: "lake", height: 201
first: "barry", last: "smith", language: "english"
first: "fred", last: "jones", language: "welsh", height: 188
first: "fred", last: "jones", eyes: "brown"
first: "barry", last: "smith"

更新图表后,我想拥有以下节点:

(:Person{first:"fred",last:"jones",language:"welsh",height:"188,eyes:"brown"})
(:Person{first:"barry",last:"smith",language"english",height:187})
(:Person{first:"fred",last"lake",height:201})

我试图制定一个可以进行此类更新的MERGE查询。我想出了以下方法:

  • MERGE开始,使用唯一性属性(示例中的firstlast)来查找或创建初始节点;
  • 然后执行包含传入记录中定义的每个属性的SET

因此,对于上面给出的三个例子记录:

MERGE (p:Person{first:"fred",last:"lake"}) SET p.height = 201;
MERGE (p:Person{first:"barry",last:"smith"}) SET p.language = "english";
MERGE (p:Person{first:"fred",last:"jones"}) SET p.language = "welsh", p.height = 188;
MERGE (p:Person{first:"fred",last:"jones"}) SET p.eyes = "brown";
MERGE (p:Person{first:"barry",last:"smith"});

我已经尝试了这个并且它有效,但我很想知道这是否是最好的方式(最有效...),以确保基于一组属性的节点的唯一性,并且随着时间的推移,允许添加(或不添加)其他信息?

2 个答案:

答案 0 :(得分:16)

只是一种天真的方法:如果您运行MERGE并创建或更新它会怎样?

根据您的记录列表,将每条记录视为地图:

{ first: "fred", last: "lake", height: 201 }
{ first: "barry", last: "smith", language: "english" }
{ first: "fred", last: "jones", language: "welsh", height: 188 }
{ first: "fred", last: "jones", eyes: "brown" }
{ first: "barry", last: "smith" }

然后以参数化方式编写查询:

MERGE (p:Person{ first: { map }.name, last: { map }.last }
ON CREATE SET n = { map }
ON MATCH  SET n += { map }

查询说明:

我在the page linked above的控制台中使用MERGE ON MATCH运行了一些查询,它似乎将现有属性更新为新值。 我运行的查询如下:

MATCH (peter { name: 'Peter' }) RETURN peter
MERGE (peter { name: 'Peter' }) ON MATCH SET peter += { hungry: TRUE , position: 'Entrepreneur' }
MATCH (peter { name: 'Peter' }) RETURN peter
// added two new properties here
MERGE (peter { name: 'Peter' }) ON MATCH SET peter += { hungry: FALSE , position: 'Entrepreneur' }
MATCH (peter { name: 'Peter' }) RETURN peter
// hungry is now false in here

答案 1 :(得分:0)

我会说这是最好的方法。根据您使用的Neo4j接口,您可以编写一个查询来处理所有内容而无需自定义SET命令,但我猜您只是简化了问题并将其覆盖。