如何将唯一数据添加到Neo4j图形数据库中。

6

我正在逐步向我的Neo4j数据库添加数据,但我卡在如何覆盖或更新现有数据以及检查数据是否已经存在于其中。

基本上,我有一组电影及其对应的ID,例如:

[
  {id: 'gameofthrones', genre: 'fantasy', release: '2017'},
  {id: 'inception', genre: 'scifi', release: '2010'},
  ...
]

我可以按照以下方式添加电影:
CREATE 
(m1:Movie {id: 'gameofthrones', genre: 'fantasy', release: '2017'}), 
(m2:Movie {id: 'inception', genre: 'scifi', release: '2010'}) 

然而,当我运行脚本两次时,它会创建4个节点而不是保持在两个节点。所以我的问题是,如何确保它检查节点id是否已经存在,如果存在则覆盖它而不是创建一个新节点?我尝试过(但只有属性被添加)。
// data
attributes['id']         = 'gameofthrones';
attributes['genre']     = 'fantasy';
...

// query
MERGE ( s:Movie {attributes}.id)
ON CREATE SET ( s:Movie {attributes} )

我在 NodeJS 中称之为:

executeQuery(queryStr, {"attributes": attributes})

// cypher (nodejs)
function executeQuery(queryStr, params) {
    var qq = Q.defer();
    db.cypher({
        query: queryStr,
        params: params,
    }, function (error, results) {
        if (error) {
            qq.reject(error);
        } else {
            if (results.length != 0) {
                qq.resolve(true);
            } else {
                qq.resolve(false);
            }
        };
    });
    return qq.promise;
};

你如何在 apoc.load.json 中载入数据?--使用最新的 apoc.load.json 示例进行更新 - Tomaž Bratanič
哦,我只是把数据作为一个对象。 - WJA
2个回答

4

你必须将查询更改为这样

MERGE ( s:Movie {attributes}.id)
ON CREATE SET s += {attributes}
ON MATCH SET s += {attributes} // optional

这段代码应该能够正常工作,但你最好使用apoc.map.clean()函数来避免重复设置id,这样可以避免一些问题。

MERGE ( s:Movie {attributes}.id)
ON CREATE SET s += apoc.map.clean({attributes},['id'],[])

最好将属性与ID分开,这样就不会被覆盖,从而触发另一个索引更新。 - Michael Hunger

3
您可以使用以下MERGE语句来实现这一点。
MERGE (m1:Movie {id: 'gameofthrones'})
ON CREATE SET m1.genre = 'fantasy', m1.release = '2017'

MERGE (m2:Movie {id: 'inception'})
ON CREATE SET m2.genre: 'scifi', m2.release = '2010' 

理想情况下,您应该使用参数而不是字面字符串来创建查询。如果您使用apoc.load.json,则可以实现此目的。
with "file:///home/sample.json" as url // can be also http://url/sample.json
CALL apoc.load.json(url) yield value
UNWIND value as item
MERGE (m1:Movie {id: item.id})
ON CREATE SET m1.genre = item.genre, m1.release = item.release

使用Apoc函数的动态属性示例:

with "file:///home/sample.json" as url // can be also http://url/sample.json
CALL apoc.load.json(url) yield value
UNWIND value as item
MERGE (m1:Movie {id: item.id})
ON CREATE SET m1 += apoc.map.clean(item,['id'],[])

如果您没有安装apoc插件:

with "file:///home/sample.json" as url // can be also http://url/sample.json
CALL apoc.load.json(url) yield value
UNWIND value as item
MERGE (m1:Movie {id: item.id})
ON CREATE SET m1 += item

请注意,id属性将首先被合并,然后使用ON CREATE SET进行更新,如果要避免多次写入单个属性,请使用apoc和上述查询语句实现。


谢谢。所以我尝试了带参数的方法,但是没能成功。我更新了我的问题。 - WJA
事实是,属性的数量会动态变化。我不想每次都在字符串中设置属性。 - WJA
添加了一个具有动态属性的示例。 - Tomaž Bratanič
我不明白你这样检索数据的目的。我已经有以对象形式(预加载)存在的数据了。为什么我还需要将其作为JSON再次获取呢? - WJA
如果您已经有一个对象,可以跳过apoc.load.json,只需执行以下操作:with my_object as value UNWIND value as item MERGE (m1:Movie {id: item.id}) ON CREATE SET m1 += item - Tomaž Bratanič

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接