查詢建立
本章節將說明使用 SDN 抽象層時,建立查詢的技術細節。由於我們不會討論所有可能的案例,而是著重於其背後的通用概念,因此會有一些簡化。
儲存
除了 find/load
操作之外,save
操作是在處理資料時最常用的操作之一。一般而言,save 操作呼叫會對資料庫發出多個陳述式,以確保產生的圖形模型與給定的 Java 模型相符。
-
將建立一個 union 陳述式,如果找不到節點的識別符,則建立一個節點;如果節點本身存在,則更新節點的屬性。
(
OPTIONAL MATCH (hlp:Person) WHERE id(hlp) = $__id__ WITH hlp WHERE hlp IS NULL CREATE (n:Person) SET n = $__properties__ RETURN id(n) UNION MATCH (n) WHERE id(n) = $__id__ SET n = $__properties__ RETURN id(n)
) -
如果實體不是新的,則網域模型中第一個找到的類型的所有關係都將從資料庫中移除。
(
MATCH (startNode)-[rel:Has]→(:Hobby) WHERE id(startNode) = $fromId DELETE rel
) -
相關實體的建立方式將與根實體相同。
(
OPTIONAL MATCH (hlp:Hobby) WHERE id(hlp) = $__id__ WITH hlp WHERE hlp IS NULL CREATE (n:Hobby) SET n = $__properties__ RETURN id(n) UNION MATCH (n) WHERE id(n) = $__id__ SET n = $__properties__ RETURN id(n)
) -
關係本身將被建立
(
MATCH (startNode) WHERE id(startNode) = $fromId MATCH (endNode) WHERE id(endNode) = 631 MERGE (startNode)-[:Has]→(endNode)
) -
如果相關實體也與其他實體有關係,則將啟動與 2. 相同的程序。
-
對於根實體上定義的下一個關係,從 2. 開始,但將第一個替換為下一個。
如您所見,SDN 盡力使您的圖形模型與 Java 世界保持同步。這也是我們強烈建議您不要載入、操作和儲存子圖的原因之一,因為這可能會導致關係從資料庫中移除。 |
多個實體
save
操作被重載,具備接受相同類型多個實体的功能。如果您使用產生的 ID 值或使用樂觀鎖定,則每個實體都將產生一個單獨的 CREATE
呼叫。
在其他情況下,SDN 將建立一個包含實體資訊的參數列表,並將其與 MERGE
呼叫一起提供。
UNWIND $__entities__ AS entity MERGE (n:Person {customId: entity.$__id__}) SET n = entity.__properties__ RETURN collect(n.customId) AS $__ids__
參數看起來像這樣
:params {__entities__: [{__id__: 'aa', __properties__: {name: "PersonName", theId: "aa"}}, {__id__ 'bb', __properties__: {name: "AnotherPersonName", theId: "bb"}}]}
載入
load
文件不僅會向您展示查詢的 MATCH 部分的外觀,還會展示資料如何回傳。
最簡單的載入操作類型是 findById
呼叫。它將比對所有具有您查詢類型標籤的節點,並對 ID 值進行篩選。
MATCH (n:Person) WHERE id(n) = 1364
如果提供了自訂 ID,SDN 將使用您定義為 ID 的屬性。
MATCH (n:Person) WHERE n.customId = 'anId'
要回傳的資料被定義為地圖投影。
RETURN n{.first_name, .personNumber, __internalNeo4jId__: id(n), __nodeLabels__: labels(n)}
如您所見,其中有兩個特殊欄位:__internalNeo4jId__
和 __nodeLabels__
。當涉及到將資料對應到 Java 物件時,這兩者都至關重要。__internalNeo4jId__
的值可以是 id(n)
或提供的自訂 ID,但在對應過程中,必須存在一個已知的欄位來引用。__nodeLabels__
確保可以找到並對應此節點上的所有已定義標籤。當使用繼承並且您查詢的不是具體類別,或者定義的關係僅定義了超類型時,這是必要的。
談到關係:如果您在實體中定義了關係,它們將作為模式理解添加到回傳的地圖中。上面的回傳部分將如下所示
RETURN n{.first_name, …, Person_Has_Hobby: [(n)-[:Has]→(n_hobbies:Hobby)|n_hobbies{__internalNeo4jId__: id(n_hobbies), .name, nodeLabels: labels(n_hobbies)}]}
SDN 使用的地圖投影和模式理解確保僅查詢您已定義的屬性和關係。
在您有自我參照節點或建立可能導致回傳資料中出現循環的架構的情況下,SDN 會退回到級聯/資料驅動的查詢建立。從尋找特定節點並考慮條件的初始查詢開始,它會逐步瀏覽產生的節點,並且如果它們的關係也被對應,則會即時建立更多查詢。此查詢建立和執行迴圈將持續到沒有查詢找到新關係或節點為止。建立的方式可以視為與儲存/更新過程類似。