2014-12-01 36 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