2017-12-02 169 views
0

我有節點的分層結構,它們都具有一個自定義的分配排序屬性(數字)限制查詢。這裏有一個簡單的Cypher查詢重現:的Neo4j - 基於節點的排名

merge (p {my_id: 1})-[:HAS_CHILD]->(c1 { my_id: 11, sort: 100}) 
merge (p)-[:HAS_CHILD]->(c2 { my_id: 12, sort: 200 }) 
merge (p)-[:HAS_CHILD]->(c3 { my_id: 13, sort: 300 }) 
merge (c1)-[:HAS_CHILD]->(cc1 { my_id: 111 }) 
merge (c2)-[:HAS_CHILD]->(cc2 { my_id: 121 }) 
merge (c3)-[:HAS_CHILD]->(cc3 { my_id: 131 }); 

我掙扎的問題是,我常常需要根據相對於一些父節點的子節點上排名的決定,與regads到這種標識。因此,例如,節點c1相對於節點p具有1級(因爲它具有最小sort屬性),c2具有等級2,並且c3具有等級3(最大sort)。

那種決定我需要根據這些信息:顯示孩子只有前2個cX節點。這裏就是我想:

graph

cc1cc2都存在,但cc3是不是因爲c3(其父)不是第一或p的第二個孩子。下面是一個啞巴查詢:

match (p {my_id: 1 })-->(c) 
optional match (c)-->(cc) where c.sort <= 200 
return p, c, cc 

問題是,這些sort屬性自定義設置和進口的,所以我不知道哪個值將舉行兒童數2.

的方式我目前的解決方案是在導入過程中的排名吧,因爲我使用的是Oracle,這是很簡單 - 我只需要使用rank窗口功能。但對我來說似乎很尷尬,我覺得可以有更優雅的解決方案。我試了下查詢和它的作品,但它看起來奇怪,它在更大的圖形非常慢:

match (p {my_id: 1 })-->(c) 
optional match (c)-->(cc) 
where size([ (p)-->(c1) where c1.sort < c.sort |c1]) < 2 
return p, c, cc 

下面是這個查詢的計劃和最昂貴的部分其實是在size表達:

query plan

回答

2

您看到的速度很慢很可能是因爲您沒有在查詢中執行索引查找,所以它會執行所有節點掃描並訪問圖中每個節點的my_id屬性以查找帶有id的節點1(你的p節點)。

您需要在節點上的標籤上添加標籤,並在查詢中使用這些標籤(至少對你的p節點),並創建一個索引(或在這種情況下,很可能是唯一約束)爲my_id所以這查找變得快速。

可以確認發生了什麼事情,這樣會在查詢的個人資料(如果可以添加輪廓計劃你的描述,具有擴展的計劃,這將有助於確定進一步優化的所有元素)。

至於您的查詢,這樣的事情應該工作(我使用的是:節點標籤爲您的實際標號的替身)

match (p:Node {my_id: 1 })-->(c) 
with p, c 
order by c.sort asc 
with p, collect(c) as children // children are in order 
unwind children[..2] as child // one row for each of the first 2 children 
optional match (child)-->(cc) // only matched for the first 2 children 
return p, children, collect(cc) as grandchildren 

請注意,這只是返回的節點,而不是路徑或關係。爲什麼你要在圖形視圖的結果曲線圖的原因是,在瀏覽器的設置選項卡(在左下角菜單中的齒輪圖標),你必須Connect result nodes底部檢查。

+0

非常感謝您的擴大答覆,我已經將剖析計劃添加到我的問題。實際上,實際的DB需要索引和標籤,正如您在計劃中看到的那樣,而計劃中最昂貴的部分實際上就是具有大小的子句。話雖如此,你的查詢是非常高效的,所以我會說這是訣竅!再次感謝! –