Neo4J create从.net客户端到webclient有不同的结果

时间:2014-05-08 22:02:39

标签: c# neo4j cypher

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

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;

这在cypher中产生类似的东西:

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

提供的完整项目

2 个答案:

答案 0 :(得分:2)

您使用的是哪个版本的.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,其中图形识别用户节点,因此它被创建(希望听起来不太明显)。

让我们知道它是怎么回事。

答案 1 :(得分:1)

所以这是关于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;
                           });

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

但是,我觉得这不是一个干净的实现,并且有一种更好的方法来编写这个查询。我会在另一个问题上提出这个问题。