查詢建立

本章介紹在使用 SDN 抽象層時查詢的技術建立。會有一些簡化,因為我們不討論所有可能的情況,而是堅持其背後的總體思想。

儲存

除了 find/load 操作之外,save 操作是在處理資料時最常用的操作之一。儲存操作呼叫通常會向資料庫發出多個語句,以確保生成的圖模型與給定的 Java 模型匹配。

  1. 將建立一個 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))

  2. 如果實體不是新的,則領域模型中找到的第一個型別的關係都將從資料庫中移除。

    (MATCH (startNode)-[rel:Has]→(:Hobby) WHERE id(startNode) = $fromId DELETE rel)

  3. 相關實體將以與根實體相同的方式建立。

    (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))

  4. 關係本身將被建立

    (MATCH (startNode) WHERE id(startNode) = $fromId MATCH (endNode) WHERE id(endNode) = 631 MERGE (startNode)-[:Has]→(endNode))

  5. 如果相關實體還與其他實體存在關係,則將開始與第 2 點相同的過程。

  6. 對於根實體上定義的下一個關係,從第 2 點開始,但將 first 替換為 next

正如您所見,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 會回退到級聯/資料驅動的查詢建立方式。從查詢特定節點並考慮條件的初始查詢開始,它遍歷結果節點,如果它們的關係也被對映,則會動態建立進一步的查詢。這個查詢建立和執行迴圈將一直持續到沒有查詢找到新的關係或節點為止。這種建立方式可以類比於儲存/更新過程。