1. Gremlin Server只將數據存儲在記憶體中 1.1. 如果停止Gremlin Server,將丟失資料庫里的所有數據 2. 概念 2.1. 遍歷(動詞) 2.1.1. 當在圖資料庫中導航時,從頂點到邊或從邊到頂點的移動過程 2.1.2. 類似於在關係資料庫中的查詢行為 2.2. 遍歷(名 ...
1. Gremlin Server只將數據存儲在記憶體中
1.1. 如果停止Gremlin Server,將丟失資料庫里的所有數據
2. 概念
2.1. 遍歷(動詞)
2.1.1. 當在圖資料庫中導航時,從頂點到邊或從邊到頂點的移動過程
2.1.2. 類似於在關係資料庫中的查詢行為
2.2. 遍歷(名詞)
2.2.1. 要在圖資料庫中執行的一個或多個操作
2.2.1.1. 要麼返回數據,要麼進行更改
2.2.2. 在關係資料庫中與之對應的是實際的SQL查詢
2.3. 遍歷源(traversal source)
2.3.1. TinkerPop特有的概念
2.3.2. 表示遍歷圖操作的起點或基點
2.3.3. 通常用變數g表示,並且需要位於任何遍歷的開頭
2.3.4. 從遍歷源開始遍歷,通過每個分支發送一個遍歷器來遍歷圖
2.4. 遍歷器(traverser)
2.4.1. 與遍歷執行特定分支相關聯的計算過程
2.4.2. 遍歷器維護相關圖當前分支移動的所有元數據
2.4.2.1. 當前對象、迴圈信息、歷史路徑數據等
2.4.3. 唯一遍歷器表示通過數據的每個分支
2.4.4. 可以被刪除,也可以帶著結果返回
3. 遍歷圖的過程
3.1. 找到起始頂點,確定要遍歷的邊,遍歷該邊,最後到達目標頂點完成遍歷
3.2. 遍歷圖需要我們瞭解圖的結構,我們任何時間在圖中的位置,以及每個位置的相鄰邊、相鄰頂點和可用屬性
3.3. 遍歷圖資料庫的重點是從一個元素遍歷到另一個元素
3.3.1. 在清楚地陳述業務問題並徹底理解用例之後,應該會發現我們的邏輯模型和已識別出的相關模式元素有助於編寫遍歷
3.4. 通過多個並行進程遍歷圖
3.4.1. 每個並行進程都稱為遍歷器
3.5. 遍歷是一系列操作
3.5.1. 遍歷的每個操作都是從一個位置開始,並且(幾乎總是)在不同的位置結束
3.5.2. 每個操作都從上一個操作結束的位置繼續
3.6. 遍歷需要知道我們在圖中的位置
3.6.1. 在關係資料庫中,SQL查詢能夠在查詢的任意點連接任意兩個表
3.6.2. 在圖中,則只能使用圖中當前位置旁邊的邊或頂點
3.6.3. 為了有效地在整個圖中導航,必須跟蹤我們在圖數據模型結構中的位置
3.6.3.1. 最難掌握的技能
3.7. 邊的方向很重要
3.7.1. 邊的有向性是圖資料庫的一個關鍵能力,對於篩選或決定要遍歷哪些邊非常有用
3.7.2. 關係的這種方向性與關係資料庫中不同,後者中的所有關係都是雙向的
3.7.3. 在圖資料庫中,不僅要決定邊的方向,還要確定我們希望如何遍歷該邊
3.7.3.1. 只遍歷入邊、出邊,還是同時遍歷兩者
3.8. 遍歷並不包含歷史記錄
3.8.1. 在圖資料庫中,從遍歷返回的唯一值是結束頂點
4. 使用Gremlin編寫遍歷
4.1. TinkerPop允許在Gremlin代碼中使用任何模式,因此本身完全避免了模式定義的問題
4.2. 所有圖查詢語言都普遍需要理解篩選及邊的方向性才能在圖中移動
4.3. 一旦從關係資料庫轉移到圖資料庫里這種根據當前位置來考慮遍歷的思考方式,我們就養成了利用數據中關係的必備思維習慣
4.4. 遍歷API
4.4.1. 按照慣例以變數g開頭:g =graph.traversal()
4.5. 內部API
4.5.1. 專為創建圖資料庫引擎的開發人員而設計
4.5.2. 圖API
4.5.2.1. 就像關係資料庫中可以通過C/C++、C#或Java等編程語言直接操縱位於SQL語言抽象之下的具體資料庫文件的API
4.5.3. 它是一個介面,用於為Vertex(頂點)、Edge(邊)、VertexProperty(頂點屬性)和Property(屬性)對象的集合定義容器對象
4.5.4. 它也是一種數據結構,不能提供有效的導航方式,只能提供在圖中定位單個數據元素的最基本能力
4.6. 誰是Ted的朋友
4.7. api
g.V().has('person', 'first_name', 'Ted').
out('friends').values('first_name')
==>Josh
4.7.1. g
4.7.1.1. 表示圖的遍歷源
4.7.1.2. 是所有遍歷的基石
4.7.1.3. 可以任意命名,但是TinkerPop圖資料庫在事務模式下的慣例是使用g
4.7.1.4. Gremlin的關鍵概念:g != graph
4.7.1.4.1. g指遍歷源,而不是圖
4.7.2. V()操作
4.7.2.1. 返回一個包含圖中每個頂點的迭代器
4.7.2.2. 兩個全局圖操作之一
4.7.2.3. 另一個全局圖操作是E()
4.7.2.3.1. 返回一個包含圖中每條邊的迭代器
4.7.2.3.2. 為了維護或基於數據完整性考慮時才使用
4.7.2.4. 遍歷的第二個操作始終是這兩個操作之一
4.7.2.5. 使用V()從頂點開始遍歷是目前最常見的做法
4.7.2.5.1. 在遍歷中,幾乎總是從V()開始
4.7.2.6. 為事務操作編寫的每次遍歷幾乎都是從一個或一組頂點開始的
4.7.3. has()操作
4.7.3.1. 篩選操作
4.7.3.2. 它只經過滿足以下篩選條件的頂點或邊
4.7.3.2.1. 匹配指定的標簽(如果指定了)
4.7.3.2.2. 具有與指定鍵-值對匹配的鍵-值對
4.7.3.3. hasLabel(label):返回匹配指定標簽類型的所有頂點或邊
4.7.3.4. has(key,value):返回匹配指定鍵-值對的所有頂點或邊
4.7.3.5. has(label,key,value):返回同時匹配標簽類型和指定鍵-值對的所有頂點或邊
4.7.3.5.1. g.V().hasLabel('person').has('first_name', 'Ted')
4.7.3.5.1.1. 等同
4.7.3.6. 出於負載和性能的考慮必須儘快縮減起始遍歷器的數量
4.7.3.7. 起始位置越少通常意味著遍歷圖的總體工作量越少
4.7.3.7.1. 在遍歷的第一個操作中將可能的頂點篩選為具有一個或多個has()操作的小子集是很常見的
4.7.4. out(label)操作
4.7.4.1. 遍歷操作
4.7.4.2. 遍歷所有出邊到帶有指定標簽的相鄰頂點(如果指定了標簽)
4.7.4.3. 如果沒有指定標簽,那麼就會遍歷所有出邊
4.7.4.4. 沿任一方向遍歷關係的靈活性是圖資料庫的基本功能,但也可能是一把雙刃劍
4.7.4.5. 方向性會篩選我們的遍歷,雖然既有助於可讀性又有助於性能,但也有局限性
4.7.4.6. 另一個常見的遍歷操作是in(label),它將遍歷所有入邊到帶有指定標簽的相鄰頂點(如果指定了標簽)
4.7.4.7. both(label)
4.7.4.7.1. 沿著給定標簽的邊從一個頂點遍歷到相鄰頂點
4.7.4.7.2. 同時在入和出兩個方向遍歷邊
4.7.5. values(keys...)操作
4.7.5.1. 值操作檢索屬性
4.7.5.2. 返回元素屬性的值
4.7.5.3. 如果元素有N個屬性,那麼輸出將包含N行
4.7.5.4. 如果指定了一個或多個鍵,則僅返回具有這些鍵的屬性
4.7.5.5. valueMap(keys...),它返回匹配這些鍵的屬性(包括鍵和值)
5. 遞歸遍歷
5.1. 迴圈遍歷
5.2. 處理需要連續多次執行遍歷某些部分的問題
5.2.1. 物料清單
5.2.1.1. 標準物料清單由多個零件組成,每個零件又由多個零件組成,這些零件還是由多個零件組成
5.2.2. 地圖導航
5.2.2.1. 給定地圖上的兩個位置,提供從起始位置到結束位置的街道和轉彎的列表
5.2.2.2. 儘管這兩個位置是相連的,但是無法提前預測所需的轉彎次數
5.2.3. 任務依賴關係
5.2.3.1. 對於每一個項,都可以將其鏈接到任何它依賴的工作項,也就是說在圖中將這些項連接到它們的依賴項,以此類推
5.3. 圖資料庫是為處理高度互連的數據而優化過的,因此圖資料庫的查詢語言和底層數據結構也經過優化,能快速執行遞歸查詢
5.3.1. 在關係資料庫中,這可能會通過遞歸CTE來處理,很難編碼和維護
6. 使用Gremlin編寫遞歸遍歷
6.1. 為Ted找到“朋友的朋友”
6.2. api
g.V().has('person', 'first_name', 'Ted').
out('friends').
out('friends').
values('first_name')
==>Hank
6.3. api
g.V().has('person','first_name','Ted').
repeat(
out()
).until(has('person','first_name','Dave')).
values('first_name')
6.3.1. repeat(traversal)
6.3.1.1. 重覆迴圈遍歷操作,直到接收到停止指示為止
6.3.1.2. traversal參數表示要在迴圈中重覆的一組Gremlin操作
6.3.2. until(traversal)
6.3.2.1. repeat()迴圈的修飾符
6.3.2.2. traversal參數表示要為每次迴圈計算一遍的一組Gremlin操作
6.3.2.3. 當traversal參數里的計算結果為true時,退出repeat()操作
6.3.2.4. 對於不知道需要遞歸多少次的情況,使用until()操作
6.3.2.5. until()操作允許持續迴圈,直到滿足指定的條件為止
6.3.2.6. 可能會產生性能問題,因為遍歷會一直運行到滿足條件為止
6.3.2.7. 如果條件從未滿足,則繼續執行,直到耗盡圖中所有可能的路徑
6.3.2.7.1. 無界遍歷
6.3.2.8. 建議使用times()操作指定最大迭代次數,或者使用timeLimit()操作指定時間限制
6.3.3. 如果until()操作在repeat()操作之前,則迴圈作為while-do迴圈運行
6.3.3.1. 在迴圈開始就檢查
6.3.3.2. 可能根本不執行
6.3.3.3. api
g.V().has('person', 'first_name', 'Ted').
until(has('person', 'first_name', 'Hank')).
repeat(
out('friends')
).
values('first_name')
==>Hank
6.3.4. 如果until()操作在repeat()操作之後,則迴圈作為do-while迴圈運行
6.3.4.1. 在迴圈末尾才檢查表達式
6.3.4.2. 總是至少執行一次
6.4. api
g.V().has('person', 'first_name', 'Ted').
repeat(
out('friends')
).times(2).
values('first_name')
==>Hank
6.4.1. times(integer)
6.4.1.1. repeat()迴圈的修飾符
6.4.1.2. integer參數表示要迴圈執行的次數
6.5. api
g.V().has('person', 'first_name', 'Ted').
until(has('person', 'first_name', 'Hank')).
repeat(
out('friends')
).emit().
values('first_name')
==>Josh
==>Hank
==>Hank