2017-01-18 61 views
1

我可能試圖以最愚蠢的方式解決問題,所以如果有更簡單的方法來解決問題,請糾正。我試圖通過圖來模擬一些條件。在這種情況下,我們有人員和健康計劃。如何確保兩個節點之間的路徑通過中間節點的所有連接?

比方說,要符合健康計劃A的資格,您必須住在某個地方並且是全職的,或者您可以住在另一個地方並且是全職或兼職的。

我對這種建模的方式是在一個人和一個計劃之間的一系列路徑中,計劃之前的最後一個節點是「條件」節點。我認爲這個結構允許AND和OR關係。鏈接到計劃的多個條件表示OR(您可以處於一種狀態,或者您可以處於不同的狀態並且是全職的)。

下面是一個人(黃色節點:「FTai」不詢問名稱)和計劃(綠色節點)之間路徑的圖片。 enter image description here

紅色節點表示條件,並且規則是如果從人到條件通過所有條件的傳入連接都有一條路徑,則此人可以利用此健康計劃。我如何編寫一個查詢,針對某個特定的人收集他們可以訪問的所有計劃?

例如,對於其他人(「Hai」),查詢不應該生成計劃,因爲它們沒有連接到提供給Connection的Full Time節點。

+0

狀態和位置節點是將鏈接到條件節點的唯一節點嗎?或者除了這些之外還有不同種類的條件?而且,從人類節點到條件節點的所有路徑都是沿相同的方向進行的嗎? – InverseFalcon

+0

此外,是不同的條件節點將鏈接到相同的健康計劃,或者是這樣的1:1? – InverseFalcon

+0

好問題。我的目標是構建一個靈活的系統,所以我不認爲狀態和位置節點是連接到狀態節點的唯一節點。目前他們是,但我預計這會隨着我發現其他情況或模擬系統變化而改變。 至於關係的方向,我正在設置,所以路徑都可以在同一個方向,我想。 最後,它不會是1:1。我預計每個「或」情況都有一個條件。多個條件容納OR,並且條件的多個鏈接允許AND。 – Daniel

回答

1

有趣的問題。

如果所存在的關係對於評估條件都是有意義的(例如,否:與夏威夷的ONCE_LIVED_IN關係或可能導致條件錯誤評估爲真的類似關係),並提供關係方向到一個計劃都是單向的,沒有其他外向關係可能會使一條路徑變成一個不相關的子圖,它應該是相當直接的形式來查詢。

下面是在你的描述圖中的創建查詢:

create (p:Person{name:'FTai'}), (p2:Person{name:'Hai'}) 
create (hi:State{name:'Hawaii'}) 
create (con:Condition) 
create (hhc:Plan{name:'Hawaii Healthcare'}) 
create (ft:EmploymentStatus{name:'Full Time'}) 
create (pt:EmploymentStatus{name:'Part Time'}) 
create (con)-[:ALLOWS]->(hhc) 
create (ft)-[:REQUIRED_BY]->(con) 
create (hi)-[:REQUIRED_BY]->(con) 
create (p)-[:HAS_STATUS]->(ft) 
create (p)-[:LIVES_IN]->(hi) 
create (p2)-[:HAS_STATUS]->(pt) 
create (p2)-[:LIVES_IN]->(hi) 

下面是開始於一個查詢:人,直至達到如下傳出關係:條件。從那裏,對於每一個:匹配的條件,我們從這些路徑中收集不同的最後一個關係:條件(應該是:REQUIRED_BY關係),並將其與進入:條件的傳入:REQUIRED_BY關係的數量進行比較。如果關係數量相同,那麼我們已滿足:REQUIRED_BY關係到:Condition中,並且可以返回連接的Plan:Plan。

MATCH (p:Person{name:'FTai'})-[r*..5]->(con:Condition) 
WITH con, COLLECT(DISTINCT LAST(r)) as metRequirements 
WHERE SIZE(metRequirements) = SIZE(()-[:REQUIRED_BY]->(con)) 
MATCH (con)-[:ALLOWS]->(plan:Plan) 
RETURN DISTINCT plan 

編輯

我的創作查詢不包括:DEFINED_AS狀態和就業狀況之間的關係,以及這種關係的存在會導致我公司提供的不當匹配查詢(所以海會錯誤地履行條件)。

圍繞這種障礙有幾種方法。你可以做白名單或黑名單。對於白名單,您需要提供每個有效的關係以在可變長度關係中遍歷。

如果您的查詢不應該遍歷關係類型,那麼黑名單可能會更容易。下面是查詢的更新版本,將工作即使:DEFINED_AS關係到位:

// you can add to the blacklist as needed, and change to a parameter 
WITH ['DEFINED_AS'] as blacklist 
MATCH (p:Person{name:'Hai'})-[r*..5]->(con:Condition) 
WHERE NONE(rel in r WHERE TYPE(rel) in blacklist) 
WITH con, COLLECT(DISTINCT LAST(r)) as metRequirements 
WHERE SIZE(metRequirements) = SIZE(()-[:REQUIRED_BY]->(con)) 
MATCH (con)-[:ALLOWS]->(plan:Plan) 
RETURN DISTINCT plan 
+0

謝謝,我會試試看。它似乎成功地搔癢了。我也有興趣知道,根據你的經驗,你認爲這是一個很好的方法去建模這個。我的意思是,「最好」,「明智」,「易於管理」等任意組合。如果您有任何批評或其他方法,我會很樂意聽到他們的意見。 - 謝謝 – Daniel

+0

我試了一下,但同樣的查詢也允許訪問圖中的其他人(「海」)。我仍然在努力,但我認爲這是因爲國家和EmployementStatus(這是另一個記錄保存項目的一部分)之間的單獨關係允許遍歷從Hai,到HI,到全時,然後由此遍歷到條件。我大概可以限制它所傳播的關係類型,或者我可以使用最短路徑來排除其他路徑。 – Daniel

+0

似乎對我很好。隨着模型的發展,我要注意的事情是新的外向關係,並確保它們最終不會創造出不符合條件的路徑。如果你必須建立這種查詢不需要遵循的關係,那麼你需要明確地包含你想要在你的可變長度關係中遵循的所有傳出路徑類型,這是一種隨着模型的變化而不斷更新的痛苦。 – InverseFalcon

0

也許我不明白您的查詢的有關像這樣的複雜性,但如何:

match (state:State)-[:REQUIRED_BY]->(and:Condition)<-[:REQUIRED_BY]-(status:EmploymentStatus) 
with state,status,and 
match (status)<-[:HAS_STATUS]-(person:Person)-[:LIVES_IN]->(state) 
with person, and 
match (and)-[:ALLOWS]->(plan:Plan) 
return person, plan 
+0

這適用於這個特定的示例。但是怎麼樣:條件只有:國家要求,但不是:EmploymentStatus要求,反之亦然?如果該模型除了增加了新的節點和要求類型:State和EmploymentStatus?示例模型中的複雜性並不多,但是要找到一種可以隨着模型本身變得更加複雜而工作的方法。 – InverseFalcon

相關問題