Neo4J创建从.net客户端到web客户端有不同的结果

本文关键字:客户端 结果 创建 net Neo4J web | 更新日期: 2023-09-27 18:02:32

我在我的人工社交应用程序中有一个"喜欢"的方法。它看起来像这样:(在我发送查询文本之前将其拆分以查看查询文本)(使用executewithoutresults)

var client = new GraphClient(new Uri("http://localhost:7474/db/data"));
client.Connect();
var q = client.Cypher.Start(new {n = string.Format("node({0})", nodeId)})
      .Match("(u:User)")
      .Where((User u) => u.ProviderUserKey == id)
      .Create("(n)-[:Liked_By]->(u)");
var res = q.Return(u => u.As<UserInfo>()).Results;

生成如下代码:

START n=node(31)
MATCH (u:User)
WHERE (u.ProviderUserKey = 9)
CREATE (n)-[:Liked_By]->(u)

当我从web控制台执行它时,它给了我在节点(n)和用户节点(u)之间创建关系的预期行为。然而,当我从。net执行它时,它为用户创建了一个新节点,并为我开始的任何节点创建了一个新关系。

我是新手,所以我希望这是非常明显的!我如何编写这个查询,以便它只创建节点(可以是任何时间)与用户节点之间的关系?

完整的项目可在https://github.com/fauxtrot/angular-ts-proto

Neo4J创建从.net客户端到web客户端有不同的结果

您使用的是什么版本的。net客户端?

考虑到上面的Cypher正在使用标签,看起来你正在使用一个相当新的Cypher/Neo4j版本,例如Cypher 2和Neo4j 2.x。

如果您正在使用Cypher 2(并且。net客户端支持它),看看当您将查询更新为如下内容时会发生什么:

MATCH (u:User {ProviderUserKey: 9}), (n {id: 31})
CREATE (n)-[:Liked_By]->(u)

…并将其转换为。net客户端使用的内容(在这一点上,我还没有对。net Neo4j客户端做过很多工作)。

老实说,如果你只想生成一次关系,考虑使用MERGE而不是CREATE(同样,如果你正在使用Cypher 2)。

对我来说,这听起来像是。net语句没有在图形识别用户节点的地方生成Cypher,所以它正在被创建(希望这听起来不太明显)。

这是关于Merge关键字实际作用的一个教训。在之前的查询中,我合并了我认为是两个查询,以便在查询项目之后获得该项目的点赞。Merge语句正在创建一个具有相似关系的新用户节点。

我确实重写了上面提到的查询,看起来像这样:

client.Cypher
  .Start(new { n = string.Format("node({0})", nodeId) })
  .Match("(u:User {ProviderUserKey : {id}})")
  .WithParam("id", id)
  .Create("(n)-[:Liked_By]->(u)").ExecuteWithoutResults();

,它具有只创建关系的预期效果。感谢@BtySgtMajor让我走上了正确的道路(通过提到这段关系)。

对于那些在家里玩的人来说,这里是令人不快的查询:

  var result = client.Cypher.Start(new { s = string.Format("node({0})", id) })
               .Match("(u:User)<-[mb:Created_By]-(c:Comment)-[o:On_Item]->(s:Session)")
               .Merge("(c)-[lb:Liked_By]->(lbu:User)")  //bad line here
               .Return((u, mb, c, s, o, lbu) => 
                     new { Comment = c.As<Comment>(), MadeByUser = u.Node<UserInfo>(),                  CommentNodeId = c.Id(), LikedByUsers = lbu.CollectAs<UserInfo>() })
                           .Results.Select(x =>
                           {
                               x.Comment.MadeBy = x.MadeByUser.Data;
                               x.Comment.MadeBy.NodeId = (int)x.MadeByUser.Reference.Id;
                               x.Comment.MadeBy.ProviderUserKey = x.MadeByUser.Reference.Id;
                               x.Comment.Id = (int)x.CommentNodeId;
                               x.Comment.LikedBy = x.LikedByUsers.Select(ui => new UserInfo { Username = ui.Data.Username, ProviderUserKey = ui.Reference.Id, NodeId = (int)ui.Reference.Id }).ToList();
                               return x.Comment;
                           });

我将合并更改为OptionalMatch,它不再创建错误的用户节点!

然而,我觉得这不是一个干净的实现,有一个更好的方式来编写这个查询。我会在另一个问题中提出这个问题。