2017-03-29 80 views
1

我正在尋找一種有效的方式來做Neo4j中的injective匹配。如果你不確定我的意思,我只想在比賽中每個返回的節點都是唯一的(例如具有唯一ID)的情況下返回匹配,並且路徑同樣適用。Neo4j中的內射匹配

An injective function

使用維基百科(上圖),域,X,匹配的是在圖案中的節點和路徑,並且所述共域,Y的圖,是數據庫的內部圖形。上圖是從X點到Y中的同一元素(因此模式中沒有2個節點與圖中的同一個節點相匹配,同樣適用於邊),因此沒有2個箭頭,而默認的Neo4J匹配是非-injective並允許模式中的2個節點與Graph中的同一節點進行匹配(您可以看到非內射匹配的示例,如上圖中指向D中Y的箭頭從X中的1和2開始) 。傳統圖論將調用匹配來自域X的多個項目到共域Y「合併」中的相同項目,但是我可以理解,在這種情況下該術語可能會令人困惑。

我可以通過指定匹配的節點是不同的模擬這種特定查詢:

match (a), (b) where not id(a) = id(b) return a, b 

但我想這樣做在一般意義上,而不必是這樣明確的在每個查詢。因此,對於這個例子,我想返回匹配,其中(a)和(b)是獨特的節點,但我想用一些常規行爲來做到這一點,而不是基於ID指定唯一性。

當我查詢時,似乎路徑已經保證是唯一的,但是如果有人能確認那會很好。

+0

不知道爲什麼人們downvoting這 –

+0

我想一個原因是,您使用的是一些術語中的Neo4j已經使用並意味着不同的事情。例如,對於熟悉Neo4j術語「合併」的人來說,「在哪裏匹配的節點和路徑未合併」相當混亂(在Neo4j中,MERGE是創建或匹配圖元素,如果它存在,MATCH如果不是,則創建)。你能用不同的術語來描述這個需求嗎? – InverseFalcon

+0

@InverseFalcon一個公平的評論,我能想到的唯一的術語是,匹配的節點和路徑是唯一的(獨特會起作用,但很明顯用於查詢中的不同目的)。 –

回答

1

如果您只是想確保您匹配的變量的節點不相同,您可以安裝APOC Procedures並使用collection helper functions中的一些,特別是apoc.coll.containsDuplicates()

使用示例可能看起來像:

MATCH p1=(a)-[r]->(b), (c) 
WHERE NOT apoc.coll.containsDuplicates([a, b, c]) 
RETURN a, b, c, p1 
+0

試圖給它一個去,但我努力正確安裝APOC(我的neo4j.conf缺少-.-)。一旦我測試過,我會回來看看,但它確實看起來是正確的:) –

+0

你不應該爲了使用APOC而弄亂conf文件,只需將jar放入plugins文件夾並重新啓動neo4j即可。最棘手的部分是根據你的Neo4j版本下載正確的APOC版本,應該有一個版本矩陣來幫助。 – InverseFalcon

+0

啊,我的工作!問題是我根本沒有弄清conf文件,所以Neo4j根本沒有指向我的插件目錄。 這似乎工作完美,但我會保持我的答案作爲遺產(以防止APOC支持停止或其他)。 作爲一個說明,我認爲它可能更有效地集中於身份證。不是apoc.coll.containsDuplicates([id(a),id(b),id(c)]),但我真的不確定。 –

1

我不確定你想要什麼,但我可以升級你的查詢來提高效率。

Match (a),(b) where id(a) < id(b) 
Return a,b 

如果你想返回不同的節點或關係,密碼器有一個distinct函數。例如:

Match (a)-->(b) 
Return distinct(a) 

P.總是使用節點標籤,因爲它加快了查詢的執行速度

+0

所以匹配(a),(b)返回不同的(a)不同的(b)將確保a和b匹配單獨的節點? 如果是這樣,這正是我正在尋找 –

+0

沒有不幸的不是。它只需要一個列表並從中刪除重複項。你想使用的是我寫的第一個查詢...你能更具體什麼是用例 –

+0

不幸的是不是真的;我試圖建立一個非常普遍的模型,現在想要建立一般意義上的內射匹配。 如果你不確定我的意思是內射匹配:http://www.mathsisfun.com/sets/injective-surjective-bijective.html 如果我有一組節點(v1,v2,... vn)和邊(e1,e2,... em)我想找到沒有合併兩個節點或邊的那組節點和邊的所有有效匹配。我可以生成一個where子句,就像你爲每一對描述的那樣,但是隨着我想要匹配的節點/邊緣的增加,會發生二次聯盟 –

0

編輯:@InverseFalcon使用APOC插件給出了更好的解決方案,但是如果因任何原因無法使用APOC或APOC支持停止,則可以手動檢查ID的唯一性如此處所述。

路徑在設計上是獨一無二的,所以通過簡單地確保節點是唯一的,可以實現內在匹配。從this answer獲取靈感,顯然你不能包裝一個查詢來實現這一點,但在WHERE子句中的一個簡短的ALL語句至少簡化了ID檢查。

如果你想匹配的模式被描述:

MATCH p1=(a)-[r]->(b), (c) 
RETURN a, b, c, p1 

這是一個非常簡單的模式(任何3級從第一到第二任何關係的節點),那麼你可以保證的唯一性通過檢查每個節點的反對其他ID的三個節點:

MATCH p1=(a)-[r]->(b), (c) 
WHERE ALL(n in [a, b, c] where 
      1=length(filter(m in [a, b, c] where id(m)=id(n)))) 
RETURN a, b, c, p1 

這是通過在該組節點檢查每個節點,我們希望是唯一的([A,b,C]),並針對每個比較其ID該集合中的其他節點ID,確保只有一個匹配的ID(本身)i在集合中。這是「where 1 = length()」部分的原因。

因此,通常使用這個思想,返回的節點保證是唯一的,返回的模式路徑保證是獨一無二的(通過Neo4j的設計)使匹配過程成爲內射。

這不是一個理想的解決方案,因爲語句必須從查詢中自定義編寫,但它的至少一個WHERE條件與節點數成線性增長,而不是爲每對節點創建一個條件的條件隨節點數增加一個階乘。

+0

將標記爲答案,除非出現更好的答案 –

+0

這看起來像你試圖找到一定大小的節點的所有組合,而不重複。那接近嗎? – InverseFalcon

+0

在這個特定的例子中是的,但更一般的我只想返回沒有合併節點或路徑的匹配,並確保ID中沒有重複保證這一點。這應該適用於一般情況下的匹配,即將ALL中任何任意模式的所有節點放在ALL子句中。 –