2017-04-25 217 views
0

我努力學習Cypher和我有一個trust network的數據,我想查詢誰相信「15最信任的人」的人,所以我寫了這個查詢,QUERY1:爲什麼這兩個Cypher查詢返回不同的結果?

QUERY1: 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 
match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id}) 
return w1.Id as user1, w2.Id as user2 

,我以後想要將最後兩行查詢更改爲:

QUERY2: 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 
match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id})-[:TRUST]->(w3:USER) 
return w1.Id as user1,w2.Id as user2, w3.Id as user3 

並且在分析結果後,我猜測有什麼不對! 所以我硬編碼id到特定的值,例如575,然後count(p)等於1937520,但是,如果我運行硬編碼ID查詢的最後一行,作爲一個獨立的查詢:

QUERY3: 

MATCH r=(u1:USER)-[:TRUST]->(u2:USER {Id: "575"})-[:TRUST]->(u3:USER) 
return count(r) 

count(r)等於到129168!

我檢查了用戶「575」信任207人並且被624人信任,所以QUERY3結果似乎是正確的:207 * 624 = 129168。我的問題是爲什麼?! 我不明白QUERY2有什麼問題,第二個問題是否意味着QUERY1結果也是錯誤的?

EDIT1: 感謝的答案,但我仍然有這個問題,所以我檢查了另一個場景,我已經得到了以下結果: 如果我寫這樣的查詢:

QUERY4: 
MATCH (n) WITH n limit 15 return "1" 

我將在輸出中打印15「1」,所以這意味着QUERY2的最後一部分執行15次,無論我是否對Id進行硬編碼,就像它在for循環中一樣。所以這裏的問題是,我認爲WHIT X LIMIT N doSomeThing將像foreach(x : X)循環執行,如果我使用x,並且不會,如果我不使用x。愚蠢的假設...

回答

1

在QUERY3中,您將u2與單個用戶(用戶575)相匹配。 QUERY 3是正確的。

但是,在QUERY2中,WITH(第3行)與15個不同的u1-u2組合相匹配。 MATCH(第1行)爲每個u1和u2返回一個「行」,這與該模式相匹配。那麼你只返回前15個結果,我猜是15個不同的u1 u2 = user {Id:575}這就是給出1937520個結果,這正好是15 * 129168.

問題在with出現是因爲你沒有聚合(每個u2只得到1行)。你爲每個u2用戶'返回'(使用WITH)一個id變量,所以count(u2)將永遠是1.也許你想寫u1.Id或count(u1)?無論如何,由於LIMIT 15(第4行),使用u2.Id或u1.Id將返回15個結果。 LIMIT 1會做的伎倆,但我們也可以這樣做:

MATCH (u1:User)-[:TRUST]-(u2:User) 
WITH DISTINCT(u2.Id) AS id 
LIMIT 15 

然後是QUERY2的其餘部分(或QUERY1,對於這個問題)。我取消了分數變量,但是如果它意味着計數(u1),它可以被讀取而沒有問題。

+0

你是對的,但如果我改變(W2:用戶{ID:ID})QUERY2的一部分(W2:用戶{ID: 「575」})我得到1937520結果,不這意味着最後一個匹配部分爲USER「575」運行15次,因爲限制15? –

+0

謝謝,我編輯了答案來反映這一點。問題在於WITH上缺少DISTINCT,導致查詢多次返回同一用戶。 – yawmoght

1

此查詢可能會做你想要的。

MATCH (:USER)-[r:TRUST]->(u2:USER) 
WITH u2, COUNT(r) AS score 
ORDER BY score DESC 
LIMIT 15 
MATCH (w1:USER)-[:TRUST]->(u2)-[:TRUST]->(w3:USER) 
RETURN w1.Id AS user1, u2.Id AS user2, w3.Id AS user3; 

它首先找到15個最信任的用戶,然後找到所有這些用戶都在中間的2級信任路徑,最後返回這些路徑的用戶的ID。

另外,第二個MATCH重複使用第一個MATCH已經找到的u2節點,以加速處理第二個MATCH

1

我只是打破查詢2,其餘的應該是有道理的。

QUERY2: 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 
match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id})-[:TRUST]->(w3:USER) 
return w1.Id as user1,w2.Id as user2, w3.Id as user3 

MATCH (u1:USER)-[:TRUST]->(u2:USER) 
with u2.Id as id, COUNT(u2) AS score 
order by score desc 
limit 15 

你基本上創建所有U1信託U2的啓動列表;和COUNT(u2)= u2的#匹配。因此,假設u1相信u2有100個匹配項,COUNT(u2)會爲每一行在該列中放置'100'。 (然後你爲了什麼現在是一個常量,它什麼也不做,並限制15,所以你現在有15 U1信託U2的任意列表。

使剛剛離開

match p=(w1:USER)-[:TRUST]->(w2:USER {Id: id})-[:TRUST]->(w3:USER) 

使匹配用戶w1信任用戶w2的每個路徑p(用於每個用戶的id),並相信用戶w3。

因此,修復第一部分,以獲得'前15個可信用戶,你需要統計傳入信託的數量

MATCH (u1:USER)-[trusts:TRUST]->(u2:USER) 
with u2, COUNT(trusts) AS score 
order by score desc 
limit 15 

所以現在你有15個最值得信賴的用戶,你可以用return u2.id, score來驗證這一點。爲了讓誰相信這些人,你會比只需要問這樣的人......

MATCH (u3:USER)-[:TRUST]->(u2) 

,然後U3會是誰信任來自排名前15位信任的人(U2)一個人的所有用戶。

作爲一個額外的注意,如果您使用的是Neo4j的Web瀏覽器,嘗試配置文件關鍵字您的CYPHER一些洞察到什麼暗號查詢實際執行前掛起。

編輯1:

我們解釋一下查詢4確實MATCH (n) WITH n limit 15 return "1"。正如我相信你一定猜到了,MATCH (n) WITH n limit 15比賽的所有節點,但結果限制到第一15.在返回部分,你說:「對於每一行,返回常量‘1’。」,這給你內部15個不同行,但返回的行不明顯。這是DISTINCT關鍵字的用途。使用RETURN DISTINCT「1」表示「對於每一行,返回常量'1',但過濾結果集只有不同的行。」又如,沒有2列將具有相同的價值。如果你知道會有一些重複的行,但要看到他們反正(也許對於一個重量的參考,或知道他們是從2個獨立的字段)的非明顯的結果是有用的。

+0

謝謝,我從你的答案中學到了很多東西,爲PROFILE關鍵字+1了,但是我的問題是其他問題。我在EDIT1中提到過它。 –

+0

@ M-N不確定查詢4對您的問題實際上意味着什麼,但是我添加了對查詢4做什麼的解釋,以便您可以理解結果。 :3 – Tezra

0

正如我在EDIT1中提到的,這裏的問題是我認爲WHIT X LIMIT N doSomeThing將像foreach(x : X)循環一樣執行,如果我使用x,並且不會,如果我不使用x。愚蠢的假設......

相關問題