2014-12-01 55 views
0

我正在按传出关系的数量排序一个大型数据库。我有一个工作Cypher查询如下:问题利用OrderBy与Neo4jClient

optional match (n)-[r]->(m) 
return n, Count(r) as c 
order by c DESC limit 1; 

Cypher查询正在按预期工作。但是,当我正在调试并逐步完成Cypher - > Neo4jClient转换时,我似乎无法找到问题的根源。

public ReturnPayload[] getByConnections() 
    { 
     var query = client.Cypher 
      .OptionalMatch("(p)-[r]->(m)") 
      .Return((p, r, m, c) => new 
      { 
       p = p.As<Person>(), 
       pid = (int)p.Id(), 
       e = r.As<RelationshipInstance<Object>>(), 
       m = m.As<Metadata>(), 
       c = r.Count() 
      }).OrderByDescending("c").Limit(1); 

     var res = query.Results; 
     var payload = new List<ReturnPayload>(); 
     foreach (var el in res) 
     { 
      var t = new ReturnPayload(); 
      t.e = el.e; 
      t.m = el.m; 
      t.pid = el.pid; 
      t.p = el.p; 
      payload.Add(t); 
     } 

     return payload.ToArray<ReturnPayload>(); 
    } 

我怀疑问题的一部分,可能是我没有利用CollectAs<T>(),因此它指的“1”的计数每每个人。不幸的是,我试图使用CollectAs<T>()CollectAsDisctinct<T>(),我的结果JSON体系结构只是将每个单独的元素封装在一个数组中,而不是将相同的元素聚合到一个数组中。

FOREACH循环有助于从匿名类型转换为我的相对标准的<ReturnPayload>,它不使用参数中的c对象。

您的时间表示感谢,谢谢。

调试好的查询测试:

OPTIONAL MATCH (p)-[r]->(m) 
RETURN p AS p, id(p) AS pid, r AS e, m AS m, count(r) AS c 
ORDER BY c DESC 
LIMIT {p0} 

而我的 '功能' 的Cypher查询:

optional match (n)-[r]->(m) 
return n, Count(r) as c 
order by c DESC limit 1; 
+0

您可以根据https://github.com/Readify/Neo4jClient/wiki/cypher#debugging提取调试查询文本,并与您的预期/正在运行的查询进行比较吗? – 2014-12-01 21:26:47

+0

@TathamOddie:我的不好。编辑到最初的帖子的底部。 – Kyle 2014-12-01 21:36:29

+0

@ThamhamOddie:在Cypher窗口中运行调试查询会导致数据不正确(逻辑上没有代码错误)。所以Cypher查询是有效的,但我的Cypher构造不是。 – Kyle 2014-12-01 21:50:13

回答

1

所以,你已经确定你自己,你正在运行的两个不同的查询。这是问题:您的C#与您期望的Cypher不匹配。

为了使C#匹配工作Cypher支架,将其更改为这样:

var query = client.Cypher 
     .OptionalMatch("(n)-[r]->(m)") 
     .Return((n, r) => new 
     { 
      n = n.As<Person>(), 
      c = r.Count() 
     }) 
     .OrderByDescending("c") 
     .Limit(1); 

那现在应该产生相同的查询,因此相同的输出你从工作Cypher支架期待。

在一个纯粹的风格笔记,还可以简化您的foreach查询到更多的功能等同的:

var payload = query 
    .Results 
    .Select(r => new ReturnPayload { 
     n = r.n, 
     c = r.c 
    }) 
    .ToArray(); 
return payload; 

然而,当我仔细看,您的查询,它看起来像你只是想为计数为了获得前1名,然后你扔掉它。

考虑使用WITH子句:

optional match (n)-[r]->(m) 
with n as n, count(r) as c 
order by c desc 
limit 1 
return n 

您可以映射回C#中使用类似的语法:

var query = client.Cypher 
    .OptionalMatch("(n)-[r]->(m)") 
    .With((n, r) => new 
    { 
     n = n.As<Person>(), 
     c = r.Count() 
    }) 
    .OrderByDescending("c") 
    .Limit(1) 
    .Return(n => new ReturnPayload  // <-- Introduce the type here too 
    { 
     n = n.As<Person>() 
    }); 

然后,你不需要来查询数据,只是把它带着另一个foreach循环。 (您会注意到我在Return调用中也引入了DTO类型,因此您不必将其从匿名类型中翻译出来。)

(声明:我只是输入了所有这些C#直接回答;我没有仔细检查汇编,所以我的签名可能会稍微偏离。)

希望帮助!

+0

谢谢你的回应!我唯一剩下的问题是:为什么两个Cypher查询的结果如此明显不同?据我所知,'功能'查询只有更多的变量通过返回。为什么在订购时似乎会导致这种意外的行为? – Kyle 2014-12-02 14:07:23