![](/img/trans.png)
[英]How do I load nodes and edges from different files in neo4j using cypher efficiently?
[英]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是全新的,但是我認為可能有用的一些事情是(稻草抓緊,這里:-)
我們想在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
我們得到以下輸出:
正如您在示例中所解釋的, ab2
和ab4
都在兩條路徑上,因此它們的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.