[英]Cypher for all paths between two nodes
我有一個包含數百萬個節點和關系的圖。 我需要獲取兩個節點之間的所有路徑。 就我而言,關系路徑中的所有節點都必須具有相同的標簽
我的查詢是這樣的;
match (n:Label) match (m:Label) where n.NAME='foo' and m.NAME='foo2'
match p=(n)-[r*..20]-(m) where all(x in nodes(p) where (x:Label))
with p
return p, EXTRACT(x IN nodes(p) | x.NAME), EXTRACT(r IN relationships(p) | type(r))
標簽為“ Label”的節點數約為20,但是此查詢遍歷所有圖形以查找兩個節點之間的所有可能路徑,然后嘗試使用“ where all”子句來減少路徑。 然后它崩潰了我的數據庫。
我需要獲取所有標簽名稱為“ Label”的節點及其關系,然后查詢子圖之間的路徑以降低成本。
有許多路徑擴展器 APOC程序應該會有所幫助,因為許多程序允許您在生成路徑時指定標簽過濾器。
例如:
MATCH (n:Label {NAME: 'foo'})
WITH COLLECT(n) AS ns1
MATCH (m:Label {NAME: 'foo2'})
WITH ns1 + COLLECT(m) AS startNodes
CALL apoc.path.expandConfig(
startNodes,
{labelFilter: '+Label', minLevel: 1, maxLevel: 20}
) YIELD path
RETURN
path,
[x IN nodes(path) | x.NAME] AS names,
[r IN relationships(path) | TYPE(r)] AS types;
試圖在數百萬個節點的圖中查找所有可能的路徑(即使長度不超過20),也可能導致內存溢出。
您可以做的是將其分解為較小的部分。 該查詢不會那么優雅,但應該可以。
例如,如果我們一次執行的路徑長度為5,則兩段查詢將如下所示:
MATCH p1 = (n1:Label)-[r1*..5]-(n2:Label), p2 = (n2:Label)-[r2*..5]-(n3:Label)
WHERE all(x1 in nodes(p1) WHERE (x1:Label))
AND all(x2 in nodes(p2) WHERE (x2:Label))
RETURN r1, r2
此查詢的費用計划如下所示:
+-----------------------+----------------------+---------------------+
| Operator | Variables | Other |
+-----------------------+----------------------+---------------------+
| +ProduceResults | r1 | r1 |
| | +----------------------+---------------------+
| +Filter | n1, n2, n3, r1, r2 | [see below] |
| | +----------------------+---------------------+
| +VarLengthExpand(All) | n1, r1 -- n2, n3, r2 | (n2)-[r1:*..5]-(n1) |
| | +----------------------+---------------------+
| +Filter | n2, n3, r2 | n3:Label |
| | +----------------------+---------------------+
| +VarLengthExpand(All) | n3, r2 -- n2 | (n2)-[r2:*..5]-(n3) |
| | +----------------------+---------------------+
| +NodeByLabelScan | n2 | :Label |
+-----------------------+----------------------+---------------------+
因此,您可以看到,在第一個擴展之后,過濾器會過濾掉所有不以:Label
開頭和結尾的路徑,然后才進行第二個擴展。
只要您的Neo版本是2.2或更高版本, p1
和p2
就不會包含相同的關系 。
您實際上可以在ProduceResults
運算符(第二行)前面的過濾器中看到此過濾完成:
all(x1 in NodesFunction(ProjectedPath(Set(r1, n1),)) where x1:Label)
AND none(r1 in r1 where any(r2 in r2 where r1 == r2))
AND n1:Label
現在您還應該看到,我們只檢查最后一個過濾器上路徑中的所有節點。 因此,這樣的路徑:(a:Label)-(b:Blah)-(c:Label)仍會經過第一段,並且僅在結果生成之前被過濾。
因此,您可以通過檢查所有段節點是否具有:Label
來進一步優化,然后手動檢查與過去的關系相似的關系。 僅顯示第二階段:
WITH n2, r1
MATCH p2 = (n2:Label)-[r2*..5]-(n3:Label)
WHERE all(x2 in nodes(p2) WHERE (x2:Label))
AND none(r1 in r1 where any(r2 in r2 where r1 == r2))
我忘記提及了,但是請記住,這樣的查詢是以惰性方式執行的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.