关联ForEach中的现有节点

时间:2014-06-03 19:40:23

标签: foreach neo4j cypher neo4jclient

我有一套PlayStation网络游戏和一组游戏文本本地化(游戏标题,游戏描述等)。我想将每个游戏与相应的区域设置相关联(" en"," fr"," de"例如),但我不确定正确的方法或者这是否正确使用Cypher的FOREACH条款。我使用Neo4jClient添加/更新游戏并添加/更新各自的区域设置。这是我到目前为止的代码:

client.Cypher
    .ForEach("(game in {PSNGames} | MERGE (g:PSNGame {NPCOMMID : game.NPCOMMID}) SET g = game)")
    .WithParams(new
    {
        PSNGames = games.ToList()
    })
    .ExecuteWithoutResults();

client.Cypher
    .ForEach("(localized in {PSNGamesLocalized} | MERGE (l:PSNGameLocalized {NPCOMMID : localized.NPCOMMID}) SET l = localized)")
    .WithParams(new
    {
        PSNGamesLocalized = localizedGames.ToList()
    })
    .ExecuteWithoutResults();

我的想法是做另一个ForEach电话和MERGE关系:

MATCH (g:PSNGame) WITH COLLECT(g) AS games 
FOREACH (game IN games | MERGE game-[:LOCALE]->(l:PSNGameLocalized {NPCOMMID : game.NPCOMMID}))

但是,这会创建新的PSNGameLocalized标签,节点和属性:

Added 93 labels, created 93 nodes, set 93 properties, created 93 relationships, returned 0 rows in 326 ms

我一直在手动创建每个节点并添加/更新每个关系,这被证明非常慢。我喜欢批量交易的想法,以加快数据导入。如何在利用FOREACH

的同时添加/更新关系

1 个答案:

答案 0 :(得分:2)

在考虑解决问题之后,我想出了以下内容:

client.Cypher
    .Match("(p:PSNProfile {PSNId : {profile}.PSNId})")
    .ForEach(@"(game in {PSNGames} | 
                MERGE p-[:PLAYS {LastPlayed : game.LastUpdated}]->(g:PSNGame {NPCOMMID : game.NPCOMMID})-[:LOCALE]->(l:PSNGameLocalized {NPCOMMID : game.NPCOMMID}) 
                SET g = game, 
                    l = { NPCOMMID : game.NPCOMMID, 
                         TitleName : game.TitleName, 
                       TitleDetail : game.TitleDetail, 
                            Locale : {locale} 
                        })")
    .WithParams(new
    {
        PSNGames = games.ToList(),
        locale = locale,
        profile = profile
    })
    .ExecuteWithoutResults();

这背后的关键是让Cypher处理foreach循环。我不再需要在C#端进行foreach循环。通过传递参数,我可以利用MERGE命令动态创建/更新节点和关系。这种方法比我之前的方法快几个级别。我希望这可以帮助其他有类似问题的人。