2017-05-23 69 views
2
通過多路徑地址的節點列表

考慮以下Cyphers:選擇在Cypher支架

MATCH (n{name: "John"})-[:Colleague]-(m) RETURN m; 

此查詢查找的John(s)Colleague(s)。現在,另一個問題:

MATCH (n{name: "John"})-[:Friend]-()-[:Colleague]-(m) RETURN m; 

這一個發現的John(s)'Friend(s)Colleague(s)。現在是最後一個:

MATCH (n{name: "John"})-[:Colleague]-()-[:Friend]-(m) RETURN m; 

最後,人們發現的John(s)'Colleague(s)Friend(s)。我在找的是一個Cypher查詢,它查找給定查詢找到的所有節點的聯合。

請注意,這只是一個例子。我在這裏實際問到的是如何使用多條路徑找到一組節點?例如:

MATCH (n{name: "John"}) 
    -[:Colleague]-/
    -[:Friend]-()-[:Colleague]-/
    -[:Colleague]-()-[:Friend]- 
    (m) RETURN m; 
+0

在查詢語言中,UNION結合了多個查詢的結果(加法),而JOIN採用多個查詢(還原)的交集。如果我理解你是對的,你想加入,對吧? – Tezra

+0

@Tezra我在找UNION;所有節點都可以從n節點開始,並採用任何給定的路徑。 – Mehran

回答

1

您可以在多個匹配中重複使用變量來引用同一個節點(JOIN模式)。實施例

MATCH (n{name: "John"})-[:Colleague]-(m) 
MATCH (n)-[:Friend]-()-[:Colleague]-(m) 
MATCH (n)-[:Colleague]-()-[:Friend]-(m) 
RETURN m; 

這裏,「約翰」匹配一次,並用作每個匹配的開始,和m是加入每個匹配的有趣的節點。如果有多個「John」實例,則此查詢將分別處理所有這些實例。如果所有的「約翰」都應該被視爲同一個人,那麼就不要重複使用n。

如果你想UNION代替JOIN,你可以收集他們這樣

MATCH (n{name: "John"}) 
OPTIONAL MATCH (n)-[:Colleague]-(c) 
OPTIONAL MATCH (c)-[:Friend]-(fc) 
OPTIONAL MATCH (n)-[:Friend]-()-[:Colleague]-(fc) 
WITH c+collect(fc)+collect(cf) AS nodez 
UNWIND nodez AS m 
RETURN DISTINCT m; 
+0

我真的很喜歡你的第一個解決方案,如果工作!但是到目前爲止,當測試它時,'(m)'沒有加入。你確定如果你重用節點變量,它們可以連接在一起嗎? – Mehran

+0

是的。你可以用一個更簡單的模式來測試它。 'CREATE(a:TEST {id:1}) - [:HAS] - >(b:TEST {id:2}) - [:HAS] - >(c:TEST {id:3})CREATE(d: TEST {id:4}) - [:HAS] - >(b)CREATE(d) - [:HAS] - >(z:TEST {id:5})RETURN *' 然後 'MATCH(a: TEST {id:1}) - [:HAS] - >(b)MATCH(d:TEST {id:4}) - [:HAS] - >(b)RETURN *' (http://console.neo4j .org/r/a5qwio) – Tezra

+0

@Mehran第一個版本是,如果你只想要滿足所有3(AKA JOIN)的節點。如果你想要所有滿足任何模式的節點,你必須使用UNION或COLLECT()。 – Tezra

2

那麼簡單地使用UNION呢?試試看:

MATCH (n{name: "John"})-[:Colleague]-(m) 
RETURN m as node 

UNION 

MATCH (n{name: "John"})-[:Friend]-()-[:Colleague]-(m) 
RETURN m as node 

UNION 

MATCH (n{name: "John"})-[:Colleague]-()-[:Friend]-(m) 
RETURN m as node 
+0

這很棒,但如果我不想在這裏完成我的查詢呢?我的意思是我試圖嵌入這個更大的查詢,但它似乎UNION不能成爲一個更大的查詢的內部組成部分。是對的嗎?如果你能告訴我如何找到具有類型關係的節點,這將是非常好的:與找到的(m)s同胞。我不是說爲每個子查詢添加' - [:兄弟] - >(o)'。我正在尋找一種方法來包含這個後期的一部分,與聚合的(m)的結果相關聯。 – Mehran

+0

我相信UNION是不可能的。爲了實現這個目標,使用@Tezra方法在[先前的回答](https://stackoverflow.com/a/44139032/6835358)(改編)中顯示:'MATCH(n {name:「John」}) - [ (m) WITH n,collect(m)as z MATCH(n) - [:朋友] - () - [:同事] - (m) WITH n,z + collect(m)as z (m) MATCH(n) - [:同事] - () - [:朋友] - (m) WITH z + collect(m)AS m UNWIND m AS節點 MATCH(node) - [:Sibling] - > s) RETURN node,s'這會給你和UNION相同的結果,你可以繼續查詢。 –

3

在這種特殊情況下,可以使用多個關係類型可變長度的關係。但是,爲了防止不好的路徑(同事的同事,朋友的朋友,以及朋友),我們必須進行一些額外的篩選以確保路徑中至少有一個同事關係。

MATCH (n{name: "John"})-[r:Colleague|Friend*1..2]-(m) 
WHERE 'Colleague' in [rel in r | type(rel)] 
RETURN m; 

另外,我強烈建議您使用節點上的標籤,並在標籤/名稱組合使用一個索引,使您查找到您的約翰節點,而不必在檢查每一個節點快,你的圖。

這個查詢不會像查詢執行UNION那樣高效,但只有索引查找和只有兩次遍歷,沒有太多關係,它應該可以正常工作。

+0

儘管您的解決方案絕對有效並且工作正常(我甚至可能會將其用於解決我手邊的問題)。但有沒有辦法實現任意路徑?像UNION一樣,但同時它可以成爲更大查詢的一部分。在我看來,UNION只能是查詢的最外層,沒有任何東西可以包裝它。 – Mehran

+0

我爲這個添加了一個單獨的答案。 – InverseFalcon

1

爲處理UNION查詢添加單獨的答案,同時保留處理聯合結果的能力。

我們實際上有一個關於post-UNION processing的知識庫文章,有幾種不同的方法。

通過APOC程序,您可以在apoc.cypher.run()內執行UNION,並獲取返回的聯合結果並繼續對其進行操作。

+0

對於那些沒有APOC的人,你可以使用collect()像聯合體(https://neo4j.com/blog/cypher-union-query-using-collect-clause/) – Tezra

1

這個簡單的查詢應該工作:

MATCH p=({name: "John"})-[:Friend*0..1]-()-[:Colleague]-()-[:Friend*0..1]-(m) 
WHERE LENGTH(p) <= 2 
RETURN m; 

它採用了可變長度模式*0..1使Friend關係可選。 WHERE子句篩選出長度超過2個關係的路徑。