2016-10-02 93 views
0

我試圖使用以下查詢來計算兩個計數之間的差異。CYPHER - 不同的COUNTs返回相同的結果

MATCH (user: User {username : 'bar' }) 
MATCH (user)-[upvote : UPVOTED]->(:Post) 
MATCH (user)-[downvote : DOWNVOTED]->(:Post) 
RETURN COUNT(upvote) - COUNT(downvote) 

它總是返回0,因爲兩個計數都是相同的值。我已經爲每個計數單獨運行了查詢,它們確實不同(3和1),但是一起查詢返回了無情的結果。

[UPDATE]

古怪,當我運行此查詢

MATCH (user : User {username : 'bar' }) 
MATCH (user)-[upvote : UPVOTED]->(:Post) 
MATCH (user)-[downvote : DOWNVOTED]->(:Post) 
RETURN COUNT(downvote) 

它返回3,而預期輸出爲1。這是因爲如果較大MATCH被支配結果

有沒有想法?謝謝

+0

您是否在添加COUNT之前試圖查看該查詢的結果?你知道它實際上是匹配嗎?這可能會讓你知道爲什麼。 – jonrsharpe

+0

我已經單獨測試了這些匹配,它返回一個列表; upvotes 3件,downvotes 1件。如果我將這兩個匹配的查詢一起運行,它將返回兩個列表,每個列表中包含3個項目。我無法確認這些返回項目的內容,因爲這些關係沒有任何屬性。 –

+0

他們每個人的數量是多少? 4? – jonrsharpe

回答

3

Neo4j在執行MATCH和OPTIONAL MATCHES時建立行。它們將取決於以前查詢的結果數量。

例如,假設用戶已經upvoted 3,但downvoted 1.

在你的匹配upvotes結束,行數被建造爲3,每個用戶,每個upvoted關係。

但在匹配downvotes結束,行數被建造爲3每一行都有:用戶的upvotes之一,單downvote:

user, up1, down1 
user, up2, down1 
user, up3, down1 

的計數ups應該是準確的,但是下降的數量也會是3。

請注意,這也是一個性能問題:您爲用戶獲取downvotes的查詢不會像您所期望的那樣爲單個用戶運行一次,而是針對每個用戶運行一次(僅此一次恰好是每行中的相同用戶)。

如果你有2個downvotes,而不是一個,那麼就不會有建立6列(3×2,每個給予好評與每一個可能的downvote配對):

user, up1, down1 
user, up1, down2 
user, up2, down1 
user, up2, down2 
user, up3, down1 
user, up3, down2 

如果你沒有DISTINCT UPS的計數並在查詢結束時顯示DISTINCT,您應該得到正確的數字,但更好的方法是注意背對背匹配(第一次匹配結果不止一行),並像這樣計算計數:

MATCH (user : User {username : 'bar' }) 
MATCH (user)-[upvote : UPVOTED]->(:Post) 
WITH user, COUNT(upvote) as upvotes 
MATCH (user)-[downvote : DOWNVOTED]->(:Post) 
RETURN upvotes, COUNT(downvote) as downvotes 

這個原理的工作原理是,在WITH後中間,你只有1個建立的行:用戶,與upvote計數。當我們匹配的downvotes,建立行會隨着給予好評的用戶,每個downvote關係數:

user, 3 as upvotes, down1 
:downvotes X 1,當您運行COUNT函數這將讓你一個準確的數數

如果你有兩個downvotes而不是一個,它會是:

user, 3 as upvotes, down1 
user, 3 as upvotes, down2 

等等。

一般來說,如果可以的話,在背靠背的MATCHES或OPTIONAL MATCHES之間運行聚合(計數,收集等),而不是在最後(除非你知道你在做什麼,背對背匹配對你的情況是正確的)。可視化neo4j如何建立你的行,這會告訴你可能會出錯。