如何在c#neo4jClient中创建一个唯一的节点(如果已经存在则不重复)?

时间:2013-12-10 17:55:23

标签: c# neo4j neo4jclient

我正在尝试执行以下操作(这在neo4J cypher上很容易。

merge (ee:Person { id: "id1234" })

如何确保下一个创建不会在c#Neo4Jclient中创建另一个节点????

迫切需要这个

client.Cypher.Merge("(user:User {Id: {Id} })")
.onCreate()
.set("user= {newUser}")
.withParams(new { ... } )
.executeWithoutResults();

似乎Merge没有被选中。知道为什么吗?因为即使对象完全相同,它仍然会创建一个新节点。

谢谢, [R

1 个答案:

答案 0 :(得分:7)

您的语法可能不正确。请使用以下语法来防止创建重复的节点。

GraphClient client = GetNeo4jGraphClient();
client.Connect();

client.Cypher
    .Merge("(user:User {Id: {newUser}.Id })")
    .OnCreate()
    .Set("user = {newUser}")
    .WithParams(
                new { 
                    newUser =
                            new { 
                                Id = 1, 
                                Name = "Michael", 
                                Title = "Developer Advocate", 
                                FavoriteDatabase = "Neo4j",
                                Occupation = "Software Developer"
                            }
    })
    .ExecuteWithoutResults();

请注意,我已将Id媒体资源更改为{newUser}.Id以上。

这解决了重复问题,但如果您将此作为GET / CREATE用户的方法使用,则不会反映更新。例如,如果我将newUser.Name属性更改为"Kenny",并且Id属性保持不变,则原始ON CREATE将优先并将节点恢复为其原始状态

要解决这个问题,你需要做两件事之一。

  1. 创建更新方法
  2. 将您的MERGE字符串发送为不带参数的Cypher
  3. 选项1 - 创建更新方法

    创建一个如下所示的其他方法,将我的动态替换为您的User类:

    GraphClient client = GetNeo4jGraphClient();
    client.Connect();
    
    client.Cypher.Match("(user:User {Id: {newUser}.Id })")
        .Set("user = {newUser}")
        .WithParams(
                    new
                    {
                        newUser =
                                new
                                {
                                    Id = 1,
                                    Name = "Kenny",
                                    Title = "Developer Advocate",
                                    FavoriteDatabase = "Neo4j",
                                    Occupation = "Software Developer"
                                }
                    })
        .ExecuteWithoutResults();
    

    选项2 - 将MERGE字符串发送为不带参数的Cypher

    我建议将Cypher直接发送到Neo4j服务器,并在Neo4jClient中绕过LINQ扩展。

    请查看这个经过修改的基于Neo4jClient的CypherQueryCreator.cs文件:

    https://github.com/kbastani/predictive-autocomplete/blob/master/predictive-autocomplete/PredictiveAutocomplete/CypherQueryCreator.cs

    public static List<IGraphNode> MergeUser(User user)
    {
         var sb = new StringBuilder();
         sb.AppendLine("MERGE user:User { Id: '{0}' }");
         sb.AppendLine("RETURN user");
    
         string commandQuery = sb.ToString();
    
         commandQuery = string.Format(commandQuery, user.UserId);
    
         GraphClient graphClient = GetNeo4jGraphClient();
    
         var cypher = new CypherFluentQueryCreator(graphClient, new CypherQueryCreator(commandQuery), new Uri(Configuration.GetDatabaseUri()));
    
         var resulttask = cypher.ExecuteGetCypherResults<GraphNode>();
         var graphNodeResults = resulttask.Result.ToList().Select(gn => (IGraphNode)gn).ToList();
         return graphNodeResults;
    }
    

    您可以在同一个GitHub项目中找到类似的实现:

    https://github.com/kbastani/predictive-autocomplete/blob/master/predictive-autocomplete/PredictiveAutocomplete/Processor.cs

    转到方法“GetRankedNodesForQuery”。

    注意:此实现未利用REST API上建议使用的参数。请查看文档以获取此考虑因素:

    http://docs.neo4j.org/chunked/milestone/rest-api-cypher.html#rest-api-use-parameters

    干杯,

    肯尼