簡體   English   中英

如何編寫查詢以比較不同路徑上的節點和邊?

[英]How do I write queries to compare nodes and edges on different paths?

我們是Neo4j的新手(很興奮!),我正在嘗試將Cypher應用到我們的問題中。 我們有一個與路徑匹配的查詢,但需要刪除涉及從相同節點或邊緣起源的任何其他路徑上遍歷的任何節點或邊緣的路徑。 這是一個測試用例:

CREATE (a1:A {name: 'a1'})-[ab1:AB {name: 'ab1'}]->(b1:B {name: 'b1'}),
       (a1)-[ab2:AB {name: 'ab2'}]->(b2:B {name: 'b2'}),
       (a2:A {name: 'a2'})-[ab3:AB {name: 'ab3'}]->(b1),
       (a2)-[ab5:AB {name: 'ab5'}]->(b3:B {name: 'b3'}),
       (a3:A {name: 'a3'})-[ab4:AB {name: 'ab4'}]->(b2),
       (a3)-[ab6:AB {name: 'ab6'}]->(b3),
       (a4:A {name: 'a4'})-[ab7:AB {name: 'ab7'}]->(b3);

格式化以提高可讀性:

a1-[ab1]->b1
a1-[ab2]->b2
a2-[ab3]->b1
a2-[ab5]->b3
a3-[ab4]->b2
a3-[ab6]->b3
a4-[ab7]->b3

我們想找到以下路徑:[A,AB,B,AB,A,AB,B,AB,A](四個步驟)。 (注意:我們不在乎邊緣方向性。)這是我的第一次嘗試(我們的術語:i_id ='initial'和t_id ='terminal')。

MATCH p = (i_id:A)-[ab1:AB]-(b1:B)-[ab2:AB]-(a1:A)-[ab3:AB]-(b2:B)-[ab4:AB]-(t_id:A)
RETURN i_id.name, ab1.name, b1.name, ab2.name, a1.name, ab3.name, b2.name, ab4.name, t_id.name
ORDER BY i_id.name;

鑒於Cypher的“ 唯一性”功能,結果是合理的:

+-------------------------------------------------------------------------------------------------+
| i_id.name | ab1.name | b1.name | ab2.name | a1.name | ab3.name | b2.name | ab4.name | t_id.name |
+-------------------------------------------------------------------------------------------------+
| "a1"      | "ab1"    | "b1"    | "ab3"    | "a2"    | "ab5"    | "b3"    | "ab6"    | "a3"      |
| "a1"      | "ab1"    | "b1"    | "ab3"    | "a2"    | "ab5"    | "b3"    | "ab7"    | "a4"      |
| "a1"      | "ab2"    | "b2"    | "ab4"    | "a3"    | "ab6"    | "b3"    | "ab5"    | "a2"      |
| "a1"      | "ab2"    | "b2"    | "ab4"    | "a3"    | "ab6"    | "b3"    | "ab7"    | "a4"      |
| "a2"      | "ab3"    | "b1"    | "ab1"    | "a1"    | "ab2"    | "b2"    | "ab4"    | "a3"      |
| "a2"      | "ab5"    | "b3"    | "ab6"    | "a3"    | "ab4"    | "b2"    | "ab2"    | "a1"      |
| "a3"      | "ab4"    | "b2"    | "ab2"    | "a1"    | "ab1"    | "b1"    | "ab3"    | "a2"      |
| "a3"      | "ab6"    | "b3"    | "ab5"    | "a2"    | "ab3"    | "b1"    | "ab1"    | "a1"      |
| "a4"      | "ab7"    | "b3"    | "ab5"    | "a2"    | "ab3"    | "b1"    | "ab1"    | "a1"      |
| "a4"      | "ab7"    | "b3"    | "ab6"    | "a3"    | "ab4"    | "b2"    | "ab2"    | "a1"      |
+-------------------------------------------------------------------------------------------------+

但是,我們需要其他過濾。 考慮在哪里i_id.name ='a2':

+-------------------------------------------------------------------------------------------------+
| i_id.name | ab1.name | b1.name | ab2.name | a1.name | ab3.name | b2.name | ab4.name | t_id.name |
+-------------------------------------------------------------------------------------------------+
| "a2"      | "ab3"    | "b1"    | "ab1"    | "a1"    | "ab2"    | "b2"    | "ab4"    | "a3"      |
| "a2"      | "ab5"    | "b3"    | "ab6"    | "a3"    | "ab4"    | "b2"    | "ab2"    | "a1"      |
+-------------------------------------------------------------------------------------------------+

注意第一個路徑如何包含ab4.name =“ ab4”,在第二個路徑中也可以找到ab3.name。 相反,在第二條路徑上以“ ab4.name”找到“ ab2”,在第一條路徑上以“ ab3.name”找到。 在我們的應用程序中,我們希望這兩個“取消”,以便查詢不返回與a2相匹配的內容。

所以最后,我的問題是:您將如何在Cypher中進行此操作? 只要可以快速執行多個查詢就可以了:-)我對Cypher是全新的,但是我認為可能有用的一些事情是(稻草抓緊,這里:-)

  • 將路徑作為集合進行比較(類似WHERE ab4.name NOT IN ...?)
  • 為項目添加標簽/添加屬性指示它們所在的i_id和路徑?
  • 每次?
  • 放松?
  • 通過...分組?

我們想在Cypher中做更多的事情,但是如果答案是“您做不到”,那么我們將上面的候選結果存入內存並完成處理。 非常感謝!

因此,我根據您的第二個建議制定了一個解決方案,即向關系添加屬性以指示它們是否在兩個或多個路徑上。

首先,在每個AB關系上創建一個traversed屬性並將其設置為0

MATCH ()-[ab:AB]-()
SET ab.traversed = 0

現在,我將使用a2作為示例的起始節點。 此查詢查找從a2到另一個標簽A節點的所有路徑,該節點的長度為四步。 每個關系的traversed屬性設置為在路徑上遇到該關系的次數。

MATCH p = (a2:A {name:'a2'})-[:AB*4]-(:A)
UNWIND RELATIONSHIPS(p) AS r
WITH r, COUNT(*) AS times_traversed
SET r.traversed = times_traversed
RETURN r.name, r.traversed
ORDER BY r.name

我們得到以下輸出:

在此處輸入圖片說明

正如您在示例中所解釋的, ab2ab4都在兩條路徑上,因此它們的traversed屬性為2

通過在每個關系上設置這些屬性,可以將路徑過濾為僅其traversed屬性之和等於路徑長度(在您的情況下為4)的路徑。

MATCH p = (a2:A {name:'a2'})-[:AB*4]-(:A)
WHERE REDUCE(traversal = 0, r IN RELATIONSHIPS(p) | traversal + r.traversed) = LENGTH(p)
RETURN p

這不會返回任何路徑,因為兩個路徑的traversed屬性之和均為6 ,而不是必需的4

但是,就像我說的那樣,這太過優雅了,也許有更好的方法可以做到這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM