讀圖資料庫實戰筆記04_路徑與圖變異

来源:https://www.cnblogs.com/lying7/archive/2023/10/31/17799113.html
-Advertisement-
Play Games

1. Groovy 1.1. Java編程語言的一個超集 1.2. Gremlin Console的一個特性是能和Groovy配合使用 1.2.1. Gremlin Console會自動地迭代結果 1.3. 從技術上說,Gremlin Console就是Groovy互動式解釋器(read-eval- ...


1. Groovy

1.1. Java編程語言的一個超集

1.2. Gremlin Console的一個特性是能和Groovy配合使用

1.2.1. Gremlin Console會自動地迭代結果

1.3. 從技術上說,Gremlin Console就是Groovy互動式解釋器(read-eval-print loop,REPL)

1.3.1. 既可以作為一個獨立的程式運行,也可以很容易地在其他程式中作為整體程式的一部分使用

2. 變異(mutation)

2.1. 簡單地被理解為通過添加、修改或刪除頂點、邊和/或屬性來改變圖

2.2. 變異遍歷或變異過程是在某種程度上改變圖的內容或結構的操作

3. 添加頂點

3.1. INSERT INTO person (first_name) VALUES ('Dave');

3.2. 在圖中添加頂點相當於在關係資料庫中添加實體

3.3. 過程

3.3.1. 給定一個遍歷源g

3.3.2. 添加一個新的頂點,類型是person

3.3.3. 在該頂點上添加一個屬性,鍵是first_name,值是Dave

3.4. groovy

g.addV('person').property('first_name', 'Dave')
==>v[13]

3.4.1. 只需要為每一個addV()操作增加一個單一頂點

3.4.2. addV(label)

3.4.2.1. 在圖中增加一個類型為label的頂點並返回這個新增頂點的引用

3.4.3. property(key, value)

3.4.3.1. 在頂點或邊上增加一個屬性

3.4.3.2. 該屬性包含指定的key和value

3.4.3.3. 返回對進入該操作的頂點或邊的引用

3.4.4. v[13]

3.4.4.1. 頂點的唯一的識別碼

3.4.4.2. 這個ID值是根據資料庫的當前狀態內部生成的

3.4.4.2.1. 頂點的ID值應該被視為圖資料庫引擎的內部信息
3.4.4.2.2. 對資料庫引擎等工具的內部信息,你應該保持足夠的警惕
3.4.4.2.3. 為了應用程式的需要而在應用代碼中使用它們則是極其危險的

3.4.4.3. Gremlin Server,在頂點上使用簡單整數(32位),在邊上使用長整數(64位)

3.4.4.4. 其他圖資料庫引擎可能會使用UUID或GUID

3.4.4.5. 雖然可以在代碼中運用這些值,但最佳實踐是不去使用它們

3.5. g.V().addV('person')

3.5.1. V()操作不僅代表圖中的所有頂點,也會返回所有頂點

3.5.1.1. 下一個操作將在上一步操作輸出的每個元素上執行

3.5.2. 圖中的每一個現有頂點都會被添加一個person頂點

3.5.3. 在某些情況下,這可能是我們想要的結果

4. 添加邊

4.1. 在關係資料庫世界里,實體間的連接是通過外鍵隱式實現的

4.2. 在圖的世界里,這些連接需要通過邊來顯式添加

4.3. 在添加邊時,需要為它指定入頂點和出頂點

4.4. SELECT * FROM table1 WHERE id = (SELECT id1 FROM table2);

4.5. 過程

4.5.1. 給定一個遍歷源g

4.5.2. 添加一條標簽為friends的邊

4.5.3. 分配邊的出頂點是鍵為first_name、值為Ted的頂點

4.5.4. 分配邊的入頂點是鍵為first_name、值為Hank的頂點

4.6. groovy

g.addE('friends').
  from(
    V().has('person', 'first_name', 'Ted')
  ).
  to(
    V().has('person', 'first_name', 'Hank')
  )
==>e[15][4-friends->6]

4.6.1. addE(label)

4.6.1.1. 添加一條標簽為label的邊

4.6.2. from(vertex)

4.6.2.1. 指定邊從哪個頂點開始的調節器

4.6.3. to(vertex)

4.6.3.1. 指定邊在哪個頂點結束的調節器

4.6.4. 操作調節器不能單獨使用

4.6.5. 調節器來源於TinkerPop,但提供開始頂點和結束頂點的細節則是通用需求

5. 刪除頂點

5.1. DELETE FROM person WHERE person_id = 13;

5.2. 過程

5.2.1. 給定一個遍歷源g

5.2.2. 找到一個ID為13的頂點

5.2.3. 刪除這個頂點

5.3. g.V(13).drop()

5.3.1. V(id)

5.3.1.1. 返回id指定的頂點

5.3.1.2. 這個id是由Gremlin Server(其選擇的資料庫)分配和維護的內部ID

5.3.2. drop()

5.3.2.1. 刪除任何經過它的頂點、邊或屬性

5.3.2.2. 沒有任何返回結果

5.3.2.2.1. 發揮作用之後,它不會向客戶端返回任何消息

6. 刪除邊

6.1. 方式1

6.1.1. 如果刪除開始頂點或結束頂點,那麼任何與該頂點關聯的邊也會被刪除,這是圖資料庫版本的引用完整性體現

6.2. 方式2

6.2.1. 顯式地刪除它們,留下開始頂點和結束頂點

6.3. 過程

6.3.1. 給定一個遍歷源g

6.3.2. 找到一條ID為15的邊

6.3.3. 刪除這條邊

6.4. g.E(15).drop()

6.4.1. 在TinkerPop中,g.E()的預設實現需要一個類型為Long而不是int的參數,在Java中要留意這一點

6.4.2. 幾乎和刪除頂點的語句一模一樣

6.4.2.1. 這種相似的語法也昭示了頂點和邊在圖資料庫中同等重要

7. 修改圖

7.1. UPDATE person SET first_name = 'Dave' WHERE first_name = 'Dav';

7.2. 過程

7.2.1. 給定一個遍歷源g

7.2.2. 找到一個鍵為first_name、值為Dav的頂點

7.2.3. 修改該頂點的屬性,將其值改為Dave

7.3. groovy

g.V().has('person', 'first_name', 'Dav').
      property('first_name', 'Dave')
==>v[18]

8. 腳本變異

8.1. groovy

g.V().drop().iterate()
dave = g.addV('person').property('first_name', 'Dave').next()
josh = g.addV('person').property('first_name', 'Josh').next()
ted = g.addV('person').property('first_name', 'Ted').next()
hank = g.addV('person').property('first_name', 'Hank').next()
g.addE('friends').from(dave).to(ted).next()
g.addE('friends').from(dave).to(josh).next()
g.addE('friends').from(dave).to(hank).next()
g.addE('friends').from(josh).to(hank).next()
g.addE('friends').from(ted).to(josh).next()

8.2. Gremlin代碼的第一行是g.V().drop().iterate(),用來清除圖中的所有數據

8.3. iterate()操作和next()操作類似,都會觸發遍歷

8.4. iterate()操作不會返回結果,而next()操作會返回遍歷的結果

8.5. 由於drop()操作不返回值,因此這裡使用iterate()操作比next()操作更合適

8.6. dave = g.addV('person').property('first_name', 'Dave').next()

8.6.1. 要在添加邊之前把相應的頂點創建好

8.6.2. 過程

8.6.2.1. 給定一個遍歷源g

8.6.2.2. 添加一個含有標簽person的新頂點

8.6.2.3. 為這個頂點添加一個鍵為first_name、值為Dave的屬性

8.6.2.4. 執行這些操作,返回迭代中的第一個(下一個)項作為結果

8.6.3. 聲明保存遍歷結果的變數dave

8.6.3.1. 變數是圖世界中另一種差別的源頭

8.6.3.1.1. Cypher,不支持這種跨請求的查詢
8.6.3.1.2. 甚至在支持TinkerPop的圖資料庫間的支持程度都不一樣
8.6.3.1.3. 不管是Azure的CosmosDB還是Amazon Nepture,都沒有這個功能
8.6.3.1.4. JanusGraph和DataStax Enterprise Graph則完全支持
8.6.3.1.5. 如果查詢語言和資料庫支持變數的話,我們推薦使用它們
8.6.3.1.6. 變數可以極大地簡化某些操作
8.6.3.1.6.1. 把添加頂點和邊的操作串聯在一起

8.6.3.2. 當要把結果賦值給一個變數時,則不得不包含終端操作

8.6.3.3. 否則,整個迭代集會被分配到變數中,而不只是迭代集里的那些結果

8.6.3.4. 這不是一個冪等的操作

8.6.4. next()

8.6.4.1. 一個終端操作,它從上一個操作獲得迭代遍歷源,迭代一次,然後返回迭代中的第一個或下一個項

8.6.4.2. 類似於iterate()的終端操作

8.6.4.3. 可以把它想成一個強制遍歷迴圈的操作

8.7. g.addE('friends').from(dave).to(ted)

8.7.1. 給定一個遍歷源g

8.7.2. 增加一條標簽為friends的邊

8.7.3. 出頂點指向dave變數

8.7.4. 入頂點指向ted變數

9. 鏈式變異

9.1. 在圖資料庫中,變異可以鏈接在一起,以同時執行多個變更

9.2. groovy

g.addE('friends').from(dave).to(josh).
  addE('friends').from(dave).to(hank).
  addE('friends').from(josh).to(hank).
  addE('friends').from(ted).to(josh).iterate()

9.3. 要在一個語句中包含複雜的操作,鏈接操作是Gremlin中的基本策略

9.3.1. 每一個操作從上一個操作的輸出獲取數據,併在處理後將該數據交給下一個操作

9.3.2. 對於熟悉函數式編程的朋友來說,這一切都似曾相識

9.4. 圖遍歷中的變異操作允許把多個變異操作鏈接成一個操作,而SQL做不到這一點

10. 路徑(path)

10.1. 在遍歷中從開始頂點訪問到結束頂點之間的所有頂點和邊的列表

10.2. 不僅告訴我們兩個頂點是連接的,而且展示了它們之間的所有中間元素

10.3. 路徑描述了從開始頂點到結束頂點的一系列遍歷操作

10.4. 路徑代表一系列連接兩個元素的頂點和邊

10.5. 意味著我們不僅能發現兩個頂點是相互連接的,而且能確定如何從起點到達終點

10.6. groovy

g.V().has('person', 'first_name', 'Ted').
  until(has('person', 'first_name', 'Denise')).
  repeat(
    both('friends')
  ).path()

10.6.1. path()

10.6.1.1. 當遍歷執行時,返回指定遍歷器訪問頂點(某些時候還有邊)的歷史

10.6.1.2. 在Gremlin中使用path()操作會增加伺服器的資源消耗,因為每個遍歷器都需要維護自己訪問的所有歷史記錄

10.6.1.3. 只在需要所有路徑數據時使用path()

10.7. groovy

Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold
     of 30000 ms or evaluation was otherwise cancelled directly for request
     [g.V().has('person', 'first_name', 'Ted').
  until(has('person', 'first_name', 'Denise')).
  repeat(
    both('friends')
  ).path()]
Type ':help' or ':h' for help.

10.7.1. 遍歷超時了

10.7.2. 圖中生成了一個環

10.7.2.1. 環是圖論中的一個概念,指的是圖中頂點和邊的路徑包含一個或多個能到達自己的頂點

10.7.2.2. 環指的是含有重覆頂點的路徑,通常會在圖遍歷過程中引起長時間運行的迴圈與尋路查詢

10.7.3. :clear命令清除緩存並重新啟動遍歷

11. 簡單路徑

11.1. 不會在任何一個頂點上重覆的路徑

11.2. 在簡單路徑中只會得到非環的結果

11.2.1. 簡單路徑就是圖中不含重覆頂點的路徑

11.3. 每個遍歷器會維護它訪問的所有項的歷史

11.3.1. 當碰到一個曾經訪問過的項時,它就知道這個元素在環中,並把它剔除

11.3.2. 只有那些不含環的遍歷器會繼續完成遍歷工作

11.4. groovy

g.V().has('person', 'first_name', 'Ted').
  until(has('person', 'first_name', 'Denise')).
  repeat(
    both('friends').simplePath()
  ).path()
==>path[v[4], v[0], v[15], v[19]]
==>path[v[4], v[0], v[13], v[19]]
==>path[v[4], v[2], v[0], v[15], v[19]]
==>path[v[4], v[2], v[0], v[13], v[19]]
==>path[v[4], v[0], v[15], v[17], v[19]]
==>path[v[4], v[0], v[15], v[13], v[19]]
==>path[v[4], v[0], v[13], v[15], v[19]]
==>path[v[4], v[2], v[6], v[0], v[15], v[19]]
==>path[v[4], v[2], v[6], v[0], v[13], v[19]]
==>path[v[4], v[2], v[0], v[15], v[17], v[19]]
==>path[v[4], v[2], v[0], v[15], v[13], v[19]]
==>path[v[4], v[2], v[0], v[13], v[15], v[19]]
==>path[v[4], v[0], v[13], v[15], v[17], v[19]]
==>path[v[4], v[2], v[6], v[0], v[15], v[17], v[19]]
==>path[v[4], v[2], v[6], v[0], v[15], v[13], v[19]]
==>path[v[4], v[2], v[6], v[0], v[13], v[15], v[19]]
==>path[v[4], v[2], v[0], v[13], v[15], v[17], v[19]]
==>path[v[4], v[2], v[6], v[0], v[13], v[15], v[17], v[19]]

11.4.1. simplePath()

11.4.1.1. 篩選掉遍歷中被重覆訪問的頂點

11.4.1.2. 如果把simplePath()放在遍歷末尾,它就在迴圈邏輯之外了,遍歷器會被困在環里,無法離開

11.4.1.3. 就像在Java里創建一個for迴圈,但把計數器變數放在for迴圈之外

12. 遍歷和篩選邊

12.1. 從頂點走到邊,再從邊走到頂點。必須顯式遍歷到邊,並顯式從邊離開

12.2. 邊可以直接被遍歷和篩選,不需要遍歷到相鄰的頂點

12.3. InE(label)

12.3.1. 從當前頂點遍歷到相鄰的入邊

12.4. outE(label)

12.4.1. 從當前頂點遍歷到相鄰的出邊

12.5. bothE(label)

12.5.1. 從當前頂點遍歷到相鄰邊,不考慮方向

12.6. 如果指定了標簽,只遍歷到符合篩選條件的邊

12.7. 每個E操作都從一個頂點開始,遍歷到一條邊,然後停留在這條邊上

12.7.1. 這些操作都結束於邊,而不是相鄰的頂點

12.8. inV()

12.8.1. 從當前邊遍歷到入頂點

12.8.2. 通常和outE()操作搭配使用

12.8.2.1. 組合來完成到相鄰頂點的遍歷

12.9. outV()

12.9.1. 從當前邊遍歷到出頂點

12.9.2. 通常和inE()操作搭配使用

12.9.2.1. 組合來完成到相鄰頂點的遍歷

12.10. otherV()

12.10.1. 遍歷到不是出頂點的那個頂點(如另一個頂點)

12.10.2. 通常和bothE()操作搭配使用

12.10.2.1. 輕鬆地帶到“另一個頂點”上,不是遍歷出發的那個頂點

12.11. bothV()

12.11.1. 從當前邊遍歷到兩個相鄰的頂點

12.11.2. 極少用到

12.12. groovy

g.V().has('person','first_name','Dave').
  bothE('works_with').otherV().values('first_name')
==>Ted
==>Josh
==>Hank
==>Kelly
==>Denise

12.13. groovy

g.V().has('person', 'first_name','Dave').
  both('works_with').values('first_name')
==>Ted
==>Josh
==>Hank
==>Kelly
==>Denise

12.14. groovy

g.V().has('person', 'first_name', 'Ted').
  until(has('person', 'first_name', 'Denise')).
  repeat(
    bothE('works_with').otherV().simplePath()
  ).path()
==>path[v[4], e[29][0-works_with->4], v[0], e[33][0-works_with->19], v[19]]
==>path[v[4], e[29][0-works_with->4], v[0], e[32][0-works_with->13], v[13],
     e[34][19-works_with->13], v[19]]
==>path[v[4], e[30][2-works_with->4], v[2], e[28][0-works_with->2], v[0],
     e[33][0-works_with->19], v[19]]
==>path[v[4], e[30][2-works_with->4], v[2], e[28][0-works_with->2], v[0],
     e[[32][0-works_with->13], v[13], e[34][19-works_with->13], v[19]]

12.14.1. bothE().otherV()遍歷模式來顯式地遍歷到邊上

12.14.2. 在路徑結果中包括邊

12.14.3. 航空交通路線

12.14.3.1. 頂點代表機場,邊代表機場間的航班

13. 通過屬性篩選邊

13.1. 基於時間的篩選

13.2. 基於權重的篩選

13.3. groovy

g.V().has('person','first_name','Dave').
  bothE('works_with').has('end_year',lte(2018)).
  otherV().
  values('first_name')
==>Josh
==>Ted
==>Hank

13.3.1. 可以基於邊的屬性進行篩選

13.3.2. 使用一些斷言操作,如代表“小於或等於”的lte()

13.3.3. 對於比單值匹配更複雜的操作,斷言操作是非常好用的管理工具

14. 邊的計數

14.1. g.V().bothE().count()

14.2. g.V().both().count()

14.2.1. 通過both()操作來計數通常代價更高昂

15. 反規範化(denormalization)

15.1. 把經常訪問的頂點屬性複製到相鄰的邊上

15.2. 它對於某些以讀為主的活動類型特別有幫助

15.3. 會帶來維護同一個屬性值的兩份副本的開銷

15.4. 維護數據的多個副本就是反規範化,不管使用關係資料庫還是圖資料庫,反規範化都會帶來這種額外的開銷


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前面一些文章,老周簡單介紹了在Qt 中使用列表模型的方法。很明顯,使用 Item Model 在許多時候還是挺麻煩的——要先建模型,再放數據,最後才構建視圖。為了簡化這些騷操作,Qt 提供了幾個便捷類。今天咱們逐個看看。 一、QListWidget 這廝對應的 List View,用來顯示簡單的列表 ...
  • 1. equels和==的區別 equals方法用於比較對象的內容是否相等,可以根據自定義的邏輯來定義相等的條件,而==操作符用於比較對象的引用是否相等,即它們是否指向同一塊記憶體地址。equals方法是一個 實例方法,可以被所有的Java對象調用,而==操作符可以用於比較對象的引用或基本數據類型的值 ...
  • 什麼是模塊? 將模塊視為代碼庫。模塊是一個包含一組函數的文件,您想要在應用程式中包含這些函數。 創建一個模塊 要創建一個模塊,只需將要包含在其中的代碼保存在擴展名為 .py 的文件中: 示例:將以下代碼保存在名為 mymodule.py 的文件中: def greeting(name): print ...
  • docker部署是主流的部署方式,極大的方便了開發部署環境,保持了環境的統一,也是實現自動化部署的前提。 1 項目的目錄結構 package: 點擊打包,生成 xxx-SNAPSHOT.jar target目錄: 打包生成目錄,生成的jar存放位置 Dockerfile: 跟項目根目錄同級 2 創建 ...
  • RSA演算法是一種非對稱加密演算法,由三位數學家`Rivest`、`Shamir`和`Adleman`共同發明,以他們三人的名字首字母命名。RSA演算法的安全性基於大數分解問題,即對於一個非常大的合數,將其分解為兩個質數的乘積是非常困難的。RSA演算法是一種常用的非對稱加密演算法,與對稱加密演算法不同,RSA算... ...
  • 可能有幾種原因導致這種情況。以下是一些常見的問題和可能的解決方法: 證書驗證問題: 當你使用mitmproxy抓包時,它通常會生成自簽名的SSL證書,以便進行中間人攻擊檢查。但在Python中使用requests庫時,預設情況下,它會驗證SSL證書的有效性。你需要禁用SSL驗證,以便使用mitmpr ...
  • 背景 由於我個人電腦是2020款m1,16G,256G。一方面,平時除了運行多個瀏覽器,還有coding 編輯器等等,記憶體確實很緊張。其次呢,m1 是ARM的架構,所以構建的鏡像是無法在X86的機器上運行的。所以我嘗試將docker引擎和client分開。 第一步:下載二進位docker 客戶端文件 ...
  • Tabby是一個開源免費軟體,支持Windows、macOS和Linux系統。它提供了一個高度可定製的終端界面,可以通過多種方式添加、切換和關閉終端標簽頁。能與 Linux 伺服器輕鬆傳輸文件,支持多種主題,界面炫酷,插件豐富。它還支持通過插件擴展其功能,例如增強的滾動條、批量複製和粘貼等功能。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...