2017-06-04 50 views
0

我有一個項目節點,這是POSTED_BY用戶節點。此外,Item可能被零個或多個用戶節點LIKED,零個或多個註釋可能是POSTED_IN Item節點。與COUNT的多個可選匹配似乎不工作

我需要做的是查詢特定的項目節點(給出的ID),和檢索:

  1. 項目節點本身
  2. ,該項目是POSTED_BY
  3. 用戶節點誰喜歡項目節點的用戶數量的計數
  4. 評論次數的計數POSTED_IN項目節點

如果我嘗試查詢只是1-3,現在排除4,我的查詢看起來是這樣的:

MATCH (i:Item {id: 'ByvIzUdbZ'})-[:POSTED_BY]->(u:User) 
OPTIONAL MATCH (u2:User)-[:LIKES]->(i) 
RETURN i, u, COUNT(u2); 

這將返回項目節點,用戶和喜歡準確計數。

現在,以適應第4點,我修改查詢並增加另一個可選的匹配,如下圖所示:

MATCH (i:Item {id: 'ByvIzUdbZ'})-[:POSTED_BY]->(u:User) 
OPTIONAL MATCH (u2:User)-[:LIKES]->(i) 
OPTIONAL MATCH (comment:Comment)-[:POSTED_IN]->(i) 
RETURN i, u, COUNT(u2), COUNT(comment); 

有了這一點,但是,對於用戶(U2)和評論數(評論)是不正確的。他們似乎正在「加起來」。所以,如果喜歡實際上是3,喜歡和評論計數都返回爲6.任何提示我在這裏做錯了嗎?謝謝。

回答

1

您正在看到cartesian products的影響。

如果將由MATCH條款自身生成將N行的數量,但已經存在的行數(比如,從以前MATCH條款)是M,那麼你最終M * N行。

爲避免這種乘法效應(這也影響性能和內存),您可以在適當的子句之後立即執行aggregation。例如,在您的情況下:

MATCH (i:Item {id: 'ByvIzUdbZ'})-[:POSTED_BY]->(u:User) 
OPTIONAL MATCH (u2:User)-[:LIKES]->(i) 
WITH i, u, COUNT(u2) AS u2_count 
OPTIONAL MATCH (comment:Comment)-[:POSTED_IN]->(i) 
RETURN i, u, u2_count, COUNT(comment) AS comment_count; 
0

Cyber​​sam對您爲什麼看到您所看到的內容有很好的解釋。請記住,基數(行數)也會影響查詢中的操作(例如MATCH和OPTIONAL MATCH)的運行次數。

例如,在您的第一次MATCH中,如果10個用戶發佈了相同的項目,那麼您將有10個這樣的項目與10個用戶中的每一個組合。

然後執行OPTIONAL MATCH,儘管你的意思是每個項目只執行一次(你試圖得到每個項目的相似計數),但它會在同一個項目上執行10次,因爲有10行與該項目。這是額外的工作,您可以通過在執行匹配之前嘗試將項目數量設置爲一行來避免這種情況,無論是通過用戶聚合,還是在與用戶匹配之前獲取每個項目所需的數據。

下面是一個示例查詢,它可能會更好一些,爲用戶保存匹配直到結束,每個可選匹配的基數都保持爲1。

MATCH (i:Item {id: 'ByvIzUdbZ'})  // one row 
OPTIONAL MATCH (u2:User)-[:LIKES]->(i) 
WITH i, COUNT(u2) AS u2_count   // back to 1 row 
OPTIONAL MATCH (comment:Comment)-[:POSTED_IN]->(i) 
WITH i, u2_count, COUNT(comment) AS comment_count; // back to one row again 
MATCH (i)-[:POSTED_BY]->(u:User) 
RETURN i, u, u2_count, comment_count