簡體   English   中英

兩個節點之間所有路徑的密碼

[英]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或更高版本, p1p2 就不會包含相同的關系

您實際上可以在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.

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