2015-11-24 125 views
1

我想知道如何在neo4j中執行路徑查詢。例如,我有以下所示的路徑的查詢:分析Neo4j路徑查詢

match p=(n)-[r*1..10]->(m) 
where 
    (
    n.URI='http://yago-knowledge.org/resource/Jacob_T._Schwartz' OR 
    n.URI='http://yago-knowledge.org/resource/Anna_Karina' 
) AND 
    filter(x IN r where type(x)=~'.*hasAcademicAdvisor.*') AND 
    filter(y IN r where type(y)=~'.*isCitizenOf.*') AND 
    filter(z IN r where type(z)=~'.*participatedIn.*') AND 
    filter(u IN r where type(u)=~'.*happendedIn.*') AND 
    filter(v IN r where type(v)=~'.*dealsWith.*') 
return p, length(p) order by length(p) desc; 

此查詢是找到與源節點「http://yago-knowledge.org/resource/Jacob_T._Schwartz」或「http://yago-knowledge.org/resource/Anna_Karina」具有一定的關係的曲線圖數據庫路徑。

我對此查詢使用PROFILE命令,下面是我得到的執行計劃。

enter image description here

注意,在第5行第5欄的內容太長,所以我把***而不是把實際的內容。

其實,***表示((((((Property(n,URI(0)) == { AUTOSTRING0} OR Property(n,URI(0)) == { AUTOSTRING1}) AND nonEmpty(FilterFunction(r,x,RelationshipTypeFunction(x) ~= /{ AUTOSTRING2}/))) AND nonEmpty(FilterFunction(r,y,RelationshipTypeFunction(y) ~= /{ AUTOSTRING3}/))) AND nonEmpty(FilterFunction(r,z,RelationshipTypeFunction(z) ~= /{ AUTOSTRING4}/))) AND nonEmpty(FilterFunction(r,u,RelationshipTypeFunction(u) ~= /{ AUTOSTRING5}/))) AND nonEmpty(FilterFunction(r,v,RelationshipTypeFunction(v) ~= /{ AUTOSTRING6}/)))

對不起壞格式。

有人能幫我解釋一下這個計劃嗎?提前致謝!!!

回答

1

我相信當你從文本控制檯看你從底部到頂部閱讀它的計劃。這可以看到,它首先找到每個節點m之間的每個n之間的單個路徑,長度爲1-10(顯然很多)。在找到所有這些路徑之後,它將採取它們並選擇哪些與過濾器保持一致。

如果可以,您應該嘗試將關係條件放在路徑匹配而不是過濾器上,以便Neo4j可以在遍歷時進行過濾,並在不匹配時停止遍歷,這可以爲您節省大量數據庫訪問。我注意到,你們的關係類型匹配是相當寬鬆的,所以我不知道有多難,這將是,但如果你知道所有可能的關係類型,那麼你應該像這樣指定它們:

match p=(n)-[r:hasAcademicAdvisor|isCitizenOf|participatedIn|happendedIn|*1..10]->(m) 

我d有興趣瞭解關於爲什麼使用正則表達式來匹配關係類型的更多信息。我知道有時候人們會爲他們的關係類型(如ID)提供動態值,根據我的經驗,這通常是一種代碼味道。通常你可以改用關係屬性。

其他一些注意事項:您沒有使用標籤,因此爲了找到具有您指定的URI屬性的節點,它首先需要搜索整個數據庫。如果您使用標籤並在:Label(URI)上創建索引或約束,那麼該部分將快得多。

我也將使用IN匹配在這種情況下URI

WHERE n.URI IN ('http://yago-knowledge.org/resource/Jacob_T._Schwartz', 'http://yago-knowledge.org/resource/Anna_Karina') 

最後,您還應該能夠利用正則表達式來使這個簡單的(或許更有效):

filter(x IN r where type(x)=~'.*(hasAcademicAdvisor|isCitizenOf|participatedIn|happendedIn|dealsWith).*') AND 

但是,如果可能的話,那還不如將其放入MATCH那麼有效。

+0

太感謝你了,布萊恩。是的,我有我的理由使用正則表達式來匹配關係類型。實際上,在我的應用場景中,我想要在一組節點之間找到路徑,以便這些路徑包含所有指定的關係。但是,我不關心關係的順序。這是我想出能夠實現我的目標的唯一途徑。另外,我同意你關於添加標籤和使用性能索引。我會嘗試的! – sgao

+0

FWIW,我給出的語法沒有指定特定的順序,只是沿着路徑的所有關係都必須是指定類型之一 –

+0

但是,我需要所有關係都出現在最終路徑中。 – sgao

0
  • 使用標籤,
  • 使用的Neo4j 2.3。X,
  • 使用上的限制:資源(URI)
  • 考慮您的URI值去掉URI前綴,它只是在浪費DB,或與命名空間進口
  • 不使用正則表達式替換針對Rel型匹配,你可以使用明智的REL-類型的
  • 刪除不確定性開始從你們的關係類型

嘗試此查詢

(固定的URI和Rel-類型後)
match p=(n:Resource)-[:hasAcademicAdvisor|:isCitizenOf|:participatedIn|:happendedIn|:dealsWith*1..10]->(m:Resource) 
where n.URI IN ['Jacob_T._Schwartz', 'Anna_Karina'] 
return p, length(p) 
order by length(p) desc; 

有關查詢計劃的詳細信息請參閱的Neo4j廣泛的文檔手冊

還要考慮Neo4j的瀏覽器更加直觀的查詢計劃

+0

非常感謝,Michael。我會嘗試你的建議。 – sgao