TinkerPop Gremlin基礎概念
-
圖計算在結構(圖)和過程(遍歷)之間進行區分。
- 圖的
結構
是由頂點/邊/屬性拓撲定義的數據模型。 - 圖的
過程
是分析結構的手段。圖形處理的典型形式稱為遍歷
。
- 圖的
-
TinkerPop3 結構 API的主要組件:
Graph:維護一組頂點和邊,并訪問數據庫函數(如
事務
)。Element:維護一組屬性和一個表示元素類型的字符串
標簽
。Vertex:擴展Element并維護一組傳入和傳出
頂點
。Edge:擴展Element并維護傳入和傳出
邊緣
。Property
<V>
:與V值關聯的字符串鍵。VertexProperty
<V>
:與V值關聯的字符串鍵以及Property<U>
屬性集合(僅限頂點)
-
TinkerPop3 過程 API的主要組件
TraversalSource:針對特定圖形,域特定語言(DSL)和執行引擎的遍歷生成器。
Traversal
<S,E>
:將類型的S對象轉換為類型對象的功能數據流程E。GraphTraversal:面向原始圖的語義(即頂點,邊等)的遍歷DSL。
GraphComputer:一個并行處理圖形并且可能分布在多機群集上的系統。
VertexProgram:在所有頂點以邏輯并行方式執行的代碼,通過消息傳遞進行相互通信。
MapReduce:并行分析圖中所有頂點并產生單個減少結果的計算。
圖形結構
-
圖
結構
:- 圖的結構是由其頂點,邊和屬性之間的顯式引用形成的拓撲。
- 頂點具有入射邊。如果一個頂點共享一個入射邊,則該頂點與另一個頂點相鄰。
- 一個屬性附加到一個元素上,一個元素具有一組屬性。屬性是一個鍵/值對,其中鍵總是一個字符String。
Graph graph = TinkerGraph.open(); //1.創建一個新的內存TinkerGraph并將其分配給該變量graph。
Vertex marko = graph.addVertex(T.label, "person", T.id, 1, "name", "marko", "age", 29); //2.創建一個頂點以及一組鍵/值對T.label作為頂點標簽并且T.id是頂點ID。
Vertex vadas = graph.addVertex(T.label, "person", T.id, 2, "name", "vadas", "age", 27);
Vertex lop = graph.addVertex(T.label, "software", T.id, 3, "name", "lop", "lang", "java");
Vertex josh = graph.addVertex(T.label, "person", T.id, 4, "name", "josh", "age", 32);
Vertex ripple = graph.addVertex(T.label, "software", T.id, 5, "name", "ripple", "lang", "java");
Vertex peter = graph.addVertex(T.label, "person", T.id, 6, "name", "peter", "age", 35);
marko.addEdge("knows", vadas, T.id, 7, "weight", 0.5f); //3.邊緣標簽被指定為第一個參數的同時創建邊緣以及一組鍵/值對。
marko.addEdge("knows", josh, T.id, 8, "weight", 1.0f);
marko.addEdge("created", lop, T.id, 9, "weight", 0.4f);
josh.addEdge("created", ripple, T.id, 10, "weight", 1.0f);
josh.addEdge("created", lop, T.id, 11, "weight", 0.4f);
peter.addEdge("created", lop, T.id, 12, "weight", 0.2f);
-
實例分析:
- 首先創建所有頂點
Graph.addVertex(Object…?)
,然后創建它們各自的邊Vertex.addEdge(String,Vertex,Object…?)
。有兩個“訪問者令牌”: T.id和T.label。 - 相應的元素連同提供的鍵/值對屬性一起被創建
"name", "josh", "age", 32
。
- 首先創建所有頂點
遍歷過程
-
圖表
過程
-
GraphTraversalSource提供了兩種遍歷方法:
GraphTraversalSource.V(Object…? ids):生成從圖中頂點開始的遍歷(如果沒有提供id,則為所有頂點)。
GraphTraversalSource.E(Object…? ids):生成從圖中邊緣開始的遍歷(如果沒有提供id,則為所有邊)。
返回類型V()和E()是GraphTraversal。
-
每種方法GraphTraversal稱為一個步驟,每個步驟以五種常規方式之一調整前一步驟的結果。
map:將傳入的遍歷器的對象轉換為另一個對象(S→E)。
flatMap:將傳入的遍歷器的對象轉換為其他對象的迭代器(S→E *)。
filter:允許或禁止移動機進行下一步(S→E→S)。
sideEffect:允許移動者不改變,但在過程中產生一些計算副作用(S?S)。
branch:分割移動器并將每個發送到遍歷中的任意位置(S→{S 1 →E *,…,S n →E *}→E *)。
Nearly every step in GraphTraversal either extends MapStep, FlatMapStep, FilterStep, SideEffectStep, or BranchStep.
-
$ bin/gremlin.sh
\,,,/
(o o)
-----oOOo-(3)-oOOo-----
gremlin> graph = TinkerFactory.createModern() //1.打開玩具圖并通過變量引用它graph。
==>tinkergraph[vertices:6 edges:6]
gremlin> g = graph.traversal() //2.使用標準的OLTP遍歷引擎從圖中創建一個圖遍歷源。
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().has('name','marko').out('knows').values('name') //3.從遍歷源中產生一個遍歷,以確定標記頂點知道的人的名字。
==>vadas
==>josh
gremlin> marko = g.V().has('name','marko').next() //1.將變量設置為名為“marko” marko的圖形中的頂點g。
==>v[1]
gremlin> g.V(marko).out('knows') //2.通過知識邊獲取與標記頂點相鄰的傳出頂點。
==>v[2]
==>v[4]
gremlin> g.V(marko).out('knows').values('name') //3.獲取marko-vertex的朋友的名字。
==>vadas
==>josh
- 遍歷器的路徑歷史記錄
gremlin> g.V(marko).out('knows').values('name').path()
==>[v[1],v[2],vadas]
==>[v[1],v[4],josh]
- 遍歷器遍歷遍歷表達式的特定部分(即循環)的次數
gremlin> g.V(marko).repeat(out()).times(2).values('name')
==>ripple
==>lop
頂點屬性
a的所有屬性Vertex都是a VertexProperty。A VertexProperty實現Property,因此它有一個鍵/值對。
但是,VertexProperty也可以實現Element并因此可以具有鍵/值對的集合
-
雖然Edge只能有一個“name”鍵的屬性,但是Vertex可以有多個“name”屬性。通過包含頂點屬性,引入了兩個功能,最終推進了圖形建模工具包:
- 多個屬性(多屬性):頂點屬性鍵可以有多個值。例如,一個頂點可以有多個“name”屬性。
- Properties on properties(元屬性):頂點屬性可以具有屬性(即,頂點屬性可以具有與其關聯的鍵/值數據)
圖事務
- 一個數據庫事務 代表的工作單位來對數據庫執行。
- 事務由Transaction接口的實現控制, 并且該對象可以Graph使用該tx()方法從接口獲取。
- 請注意,該Transaction對象本身并不代表“事務”。它只是公開了處理事務的方法(例如提交,回滾等)。
- 大部分Graph是實現supportsTransactions將實現“自動” ThreadLocal交易,這意味著當后一個讀或寫操作時Graph被實例化,事務就會自動線程內開始。
- 沒有必要手動調用一個方法來“創建”或“啟動”一個事務。只需根據需要修改圖形,然后致電graph.tx().commit()以應用更改或graph.tx().rollback()撤消它們。當下一個讀取或寫入操作發生在圖上時,將在當前執行線程中啟動一個新的事務。
遍歷
-
遍歷由四個主要組成部分組成:
Step
<S,E>
:應用于S產出的單個函數E。步驟在遍歷內鏈接。TraversalStrategy:攔截器方法來改變遍歷的執行(例如查詢重寫)。
TraversalSideEffects:可用于存儲有關遍歷的全局信息的鍵/值對。
Traverser
<T>
:通過Traversal當前表示類型的對象傳播的對象T。
-
圖形遍歷的經典概念GraphTraversal
<S,E>
由此擴展而來Traversal<S,E>
。 GraphTraversal根據頂點,邊緣等提供對圖數據的解釋,并因此提供圖遍歷DSL。
這里寫圖片描述 -
該Traverser
<S>
對象可以訪問:當前遍歷的S對象 -? Traverser.get()。
遍歷器遍歷的當前路徑 -? Traverser.path()。
獲取特定路徑歷史對象的助手速記 -? Traverser.path(String) == Traverser.path().get(String)。
遍歷器通過當前循環的次數 -? Traverser.loops()。
這個遍歷器表示的對象的數量 -? Traverser.bulk()。
與此遍歷器相關的本地數據結構 -? Traverser.sack()。
與遍歷相關的副作用 -? Traverser.sideEffects()。
gremlin> g.V(1).out().values('name') //1.從頂點1到相鄰頂點的名稱值的傳出遍歷。
==>lop
==>vadas
==>josh
gremlin> g.V(1).out().map {it.get().value('name')} //2.相同的操作,但使用lambda來訪問名稱屬性值。
==>lop
==>vadas
==>josh
gremlin> g.V(1).out().map(values('name')) //3.同樣的操作,但使用遍歷表示map()。
==>lop
==>vadas
==>josh
gremlin> g.V().filter {it.get().label() == 'person'} //1.如果過濾器具有“人物”標簽,則只允許頂點通過
==>v[1]
==>v[2]
==>v[4]
==>v[6]
gremlin> g.V().filter(label().is('person')) //2.如果過濾器具有“人物”標簽,則只允許頂點通過
==>v[1]
==>v[2]
==>v[4]
==>v[6]
gremlin> g.V().hasLabel('person') //3.更具體的步驟has()是filter()用各自的謂詞來實現的。
==>v[1]
==>v[2]
==>v[4]
==>v[6]
gremlin> g.V().branch {it.get().value('name')}.
option('marko', values('age')).
option(none, values('name')) //1.如果頂點是“marko”,則獲取他的年齡,否則獲取頂點的名稱。
==>29
==>vadas
==>lop
==>josh
==>ripple
==>peter
gremlin> g.V().branch(values('name')).
option('marko', values('age')).
option(none, values('name')) //2.相同的操作,但使用遍歷表示branch()。
==>29
==>vadas
==>lop
==>josh
==>ripple
==>peter
gremlin> g.V().choose(has('name','marko'),
values('age'),
values('name')) //3.更具體的基于布爾的步驟choose()被實現為a branch()。
==>29
==>vadas
==>lop
==>josh
==>ripple
==>peter
Terminal
- 通常,當一個步驟連接到一個遍歷時,返回一個遍歷。通過這種方式,流暢的,單點式的遍歷就可以建立起來。
- 但是,某些步驟不會返回遍歷,而是執行遍歷并返回結果。這些步驟被稱為終端步驟(終端)
gremlin> g.V().out('created').hasNext() //1.hasNext() 確定是否有可用的結果。
==>true
gremlin> g.V().out('created').next() //2.next() 將返回下一個結果。
==>v[3]
gremlin> g.V().out('created').next(2) //3.next(n)將返回n列表中的下一個結果。
==>v[3]
==>v[5]
gremlin> g.V().out('nothing').tryNext() //4.tryNext()將返回一個Optional,因此,是hasNext()/ 的組合next()。
==>Optional.empty
gremlin> g.V().out('created').toList() //5.tryNext()將返回一個Optional,因此,是hasNext()/ 的組合next()。
==>v[3]
==>v[5]
==>v[3]
==>v[3]
gremlin> g.V().out('created').toSet() //6.toSet() 將返回一個集合中的所有結果(因此,重復刪除)。
==>v[3]
==>v[5]
gremlin> g.V().out('created').toBulkSet() //7.toBulkSet() 將返回加權集合中的所有結果(因此,通過加權保留重復)。
==>v[3]
==>v[3]
==>v[3]
==>v[5]
gremlin> results = ['blah',3]
==>blah
==>3
gremlin> g.V().out('created').fill(results) //8.fill(collection) 會將所有結果放入提供的集合中,并在完成時返回集合。
==>blah
==>3
==>v[3]
==>v[5]
==>v[3]
==>v[3]
gremlin> g.addV('person').iterate() // 9.iterate() 并不完全符合終端步驟的定義,因為它不返回結果,但仍然返回一個遍歷 - 但它確實表現為終端步驟,它重復遍歷并生成副作用而不返回實際結果。
AddEdge
推理
是明確數據中隱含的內容的過程.圖中
顯式
的是圖的對象 - 即頂點
和邊
。-
圖中
隱含
的是遍歷
。- 換句話說,遍歷揭示了意義由遍歷定義確定的位置。
gremlin> g.V(1).as('a').out('created').in('created').where(neq('a')).
addE('co-developer').from('a').property('year',2009) //1.在marko和他的合作者之間添加一個年度財產的合作開發者邊緣。
==>e[13][1-co-developer->4]
==>e[14][1-co-developer->6]
gremlin> g.V(3,4,5).aggregate('x').has('name','josh').as('a').
select('x').unfold().hasLabel('software').addE('createdBy').to('a') //2.將來自josh頂點的傳入createdBy邊添加到lop和波紋頂點。
==>e[15][3-createdBy->4]
==>e[16][5-createdBy->4]
gremlin> g.V().as('a').out('created').addE('createdBy').to('a').property('acl','public') //3.為所有創建的邊添加一個反向創建的邊。
==>e[17][3-createdBy->1]
==>e[18][5-createdBy->4]
==>e[19][3-createdBy->4]
==>e[20][3-createdBy->6]
gremlin> g.V(1).as('a').out('knows').
addE('livesNear').from('a').property('year',2009).
inV().inE('livesNear').values('year') //4.新創建的邊是一個可遍歷的對象。
==>2009
==>2009
gremlin> g.V().match(
__.as('a').out('knows').as('b'),
__.as('a').out('created').as('c'),
__.as('b').out('created').as('c')).
addE('friendlyCollaborator').from('a').to('b').
property(id,23).property('project',select('c').values('name')) //5.可以加入遍歷中的任意兩個綁定from()→ , where `id可以為支持用戶提供的id的圖提供`to()。
==>e[23][1-friendlyCollaborator->4]
gremlin> g.E(23).valueMap()
==>[project:lop]
gremlin> marko = g.V().has('name','marko').next()
==>v[1]
gremlin> peter = g.V().has('name','peter').next()
==>v[6]
gremlin> g.V(marko).addE('knows').to(peter) //6.給定定向(分離)的頂點參考,在marko和peter之間添加一條邊。
==>e[24][1-knows->6]
gremlin> g.addE('knows').from(marko).to(peter) //7.給定定向(分離)的頂點參考,在marko和peter之間添加一條邊。
==>e[25][1-knows->6]
AddVertex
- 所述addV()-step用于頂點添加到圖表(map/ sideEffect)。
- 對于每個傳入的對象,都會創建一個頂點。此外,GraphTraversalSource維護一個addV()方法。
gremlin> g.addV('person').property('name','stephen')
==>v[13]
gremlin> g.V().values('name')
==>marko
==>vadas
==>lop
==>josh
==>ripple
==>peter
==>stephen
gremlin> g.V().outE('knows').addV().property('name','nothing')
==>v[15]
==>v[17]
gremlin> g.V().has('name','nothing')
==>v[17]
==>v[15]
gremlin> g.V().has('name','nothing').bothE()
AddProperty
- The property():步驟用于將屬性添加到的曲線圖的元素sideEffect。
- 不像addV()和 addE(),property()是一個完整的sideEffect一步,因為它不會返回它創造的財產,而是涌入它的元素。
gremlin> g.V(1).property('country','usa')
==>v[1]
gremlin> g.V(1).property('city','santa fe').property('state','new mexico').valueMap()
==>[country:[usa],city:[santa fe],name:[marko],state:[new mexico],age:[29]]
gremlin> g.V(1).property(list,'age',35) //1.對于頂點,可以為頂點屬性提供基數。
==>v[1]
gremlin> g.V(1).valueMap()
==>[country:[usa],city:[santa fe],name:[marko],state:[new mexico],age:[29,35]]
gremlin> g.V(1).property('friendWeight',outE('knows').values('weight').sum(),'acl','private') //2.可以通過遍歷來選擇屬性值(以及鍵)。
==>v[1]
gremlin> g.V(1).properties('friendWeight').valueMap() //3.對于頂點,property()-step可以添加元屬性。
==>[acl:private]
Aggregate
- aggregate()工序(sideEffect)用于在特定點遍歷成聚集的所有對象 Collection。
- The step uses eager evaluation in that no objects continue on until all previous objects have been fully aggregated (as opposed to store() which lazily fills a collection). The eager evaluation nature is crucial in situations where everything at a particular point is required for future computation. An example is provided below.
gremlin> g.V(1).out('created') //1。marko創建了什么?
==>v[3]
gremlin> g.V(1).out('created').aggregate('x') //2。匯總他所有的創作。
==>v[3]
gremlin> g.V(1).out('created').aggregate('x').in('created') //3。誰是marko的合作者?
==>v[1]
==>v[4]
==>v[6]
gremlin> g.V(1).out('created').aggregate('x').in('created').out('created') //4。marko的合作者創造了什么?
==>v[3]
==>v[5]
==>v[3]
==>v[3]
gremlin> g.V(1).out('created').aggregate('x').in('created').out('created').
where(without('x')).values('name') //5。Marko的合作者創建了什么,他沒有創建?
==>ripple
And
- The and():確保所有提供遍歷得到的結果(濾波)
gremlin> g.V().and(
outE('knows'),
values('age').is(lt(30))).
values('name')
==>marko
- 一個中間符號可以被使用。盡管用中綴符號表示,但只有兩次遍歷可以在一起。
gremlin> g.V().where(outE('created').and().outE('knows')).values('name')
==>marko
As
- The as():不是一個真正的步驟,而是一個類似于by()和的“步調制器” option()。
- 用as(),有可能提供一個標簽到可稍后通過步驟和數據結構,使這些標記的使用被訪問的步驟-例如select(),match()和路徑。
gremlin> g.V().as('a').out('created').as('b').select('a','b') //1.從路徑中選擇標記為“a”和“b”的對象。
==>[a:v[1],b:v[3]]
==>[a:v[4],b:v[5]]
==>[a:v[4],b:v[3]]
==>[a:v[6],b:v[3]]
gremlin> g.V().as('a').out('created').as('b').select('a','b').by('name') //2.從路徑中選擇標記為“a”和“b”的對象,并為每個對象設置其名稱值。
==>[a:marko,b:lop]
==>[a:josh,b:ripple]
==>[a:josh,b:lop]
==>[a:peter,b:lop]
- 一個步驟可以有任何數量的標簽與之相關聯。這對于在未來的步驟中多次引用同一步驟很有用。
gremlin> g.V().hasLabel('software').as('a','b','c').
select('a','b','c').
by('name').
by('lang').
by(__.in('created').values('name').fold())
==>[a:lop,b:java,c:[marko,josh,peter]]
==>[a:ripple,b:java,c:[josh]]
Barrier
The barrier():(屏障)變為懶惰遍歷流水線成批量同步管道。
-
此步驟很有用:
- 當所有的事情都需要被執行之后才能進入barrier()(即排序)之后的步驟。
- 當“stalling”遍歷可能導致遍歷中的“bulking optimization”,這種遍歷反復觸及許多相同的元素(即優化)。
gremlin> g.V().sideEffect{println "first: ${it}"}.sideEffect{println "second: ${it}"}.iterate()
first: v[1]
second: v[1]
first: v[2]
second: v[2]
first: v[3]
second: v[3]
first: v[4]
second: v[4]
first: v[5]
second: v[5]
first: v[6]
second: v[6]
gremlin> g.V().sideEffect{println "first: ${it}"}.barrier().sideEffect{println "second: ${it}"}.iterate()
first: v[1]
first: v[2]
first: v[3]
first: v[4]
first: v[5]
first: v[6]
second: v[1]
second: v[2]
second: v[3]
second: v[4]
second: v[5]
second: v[6]
- “bulking optimization”背后的理論很簡單。
- 如果在頂點1處有一百萬個遍歷器,則不需要計算一百萬個both()計算。相反,將這100萬遍歷作為一個Traverser.bulk()等于一百萬的遍歷器來表示,并執行both()一次。
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> graph.io(graphml()).readGraph('data/grateful-dead.xml')
gremlin> g = graph.traversal().withoutStrategies(LazyBarrierStrategy) //1.明確地刪除LazyBarrierStrategy這會產生一個膨脹優化。
==>graphtraversalsource[tinkergraph[vertices:808 edges:8049], standard]
gremlin> clockWithResult(1){g.V().both().both().both().count().next()} //2.處理每個移動程序的非擴充遍歷。
==>10555.215011999999
==>126653966
gremlin> clockWithResult(1){g.V().repeat(both()).times(3).count().next()} //3.每個進入者repeat()都有其遞歸權重。
==>32.586223
==>126653966
gremlin> clockWithResult(1){g.V().both().barrier().both().barrier().both().barrier().count().next()} //4.沒有處理隱式遍歷的遍歷遍歷。
==>24.458371
==>126653966
- 如果barrier()提供了一個整數參數,那么在將n聚合遍歷器排空到下一步之前,屏障將只保留唯一遍歷器的數量。
- LazyBarrierStrategy插入 - barrier()在適當的地方進行遍歷,以獲得“膨脹優化”。
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> graph.io(graphml()).readGraph('data/grateful-dead.xml')
gremlin> g = graph.traversal() //1.LazyBarrierStrategy 是一種默認策略,因此不需要明確激活。
==>graphtraversalsource[tinkergraph[vertices:808 edges:8049], standard]
gremlin> clockWithResult(1){g.V().both().both().both().count().next()}
==>15.593098999999999
==>126653966
gremlin> g.V().both().both().both().count().iterate().toString() //2.與LazyBarrierStrategy激活,barrier()步驟被自動插入在適當情況下。
==>[TinkerGraphStep(vertex,[]), VertexStep(BOTH,vertex), NoOpBarrierStep(2500), VertexStep(BOTH,vertex), NoOpBarrierStep(2500), VertexStep(BOTH,edge), CountGlobalStep, NoneStep]
By
- The by():一步不是一個實際的步驟,而是一個類似于as()和 的“階躍調節器” 。
- 如果一個步驟能夠接受遍歷,函數,比較等,那么by()就是它們被添加的方式。一般模式是step().by()…?by()。有些步驟只能接受一個,by() 而其他步驟可以采取任意數量。
gremlin> g.V().group().by(outE().count()) //1.by(outE().count())將按元素的邊數(遍歷)對元素進行分組。
==>[1:[v[2],v[5],v[6]],3:[v[1],v[3],v[4]]]
gremlin> g.V().group().by(bothE().count()).by('name') //2.by('name')將按名稱處理分組元素(元素屬性投影)。
==>[1:[vadas,ripple,peter],3:[marko,lop,josh]]
gremlin> g.V().group().by(bothE().count()).by(count()) //3.by(count())將計算每個組中元素的數量(遍歷)。
==>[1:3,3:3]
-
以下步驟都支持by()調制:
dedup():對調制結果進行by()重復數據刪除。
cyclicPath():如果遍歷器的路徑是循環給定by()調制,則進行過濾。
simplePath():如果遍歷器的路徑在給定by()調制的情況下是簡單的,則進行過濾。
sample():使用由by()調制返回的值進行采樣。
where():確定給定測試結果的謂詞 - by()調制。
groupCount():計數那些組密鑰是by()調制結果的組。
group():根據by()-modulation 創建組鍵和值。
order():通過by()調制的結果對對象進行排序。
path():獲取每個路徑元素被by()調制的遍歷器的路徑。
project():by()從當前對象中投影給定各種調制結果的地圖。
select():選擇路徑元素并通過by()調制進行轉換。
tree():獲取對象已被by()調制的遍歷器對象樹。
aggregate():將所有對象聚合到一個集合中,但只存儲它們的by()-modulated值。
store():將所有對象存儲到一個集合中,但只存儲它們的by()-modulated值。
Cap
- The cap(): 迭代遍歷到本身并發射通過所提供的密鑰所引用的sideEffect。如果提供了多個鍵,則會Map
gremlin> g.V().groupCount('a').by(label).cap('a') //1.按標簽對頂點進行分組和計數。發出標記為'a'的副作用,這是按標簽計算的組數。
==>[software:2,person:4]
gremlin> g.V().groupCount('a').by(label).groupCount('b').by(outE().count()).cap('a','b') //2.與語句1相同,但也會發出標記為'b'的副作用,該副作用按照出邊的數量對頂點進行分組。
==>[a:[software:2,person:4],b:[0:3,1:1,2:1,3:1]]
Choose
- The choose():(分支)的路線橫移到一個特定的遍歷分支選項。
- 有了choose()它,就可以實現if / then / else-semantics以及更復雜的選擇。
gremlin> g.V().hasLabel('person').
choose(values('age').is(lte(30)),
__.in(),
__.out()).values('name') //1.如果遍歷產生一個元素,那么do in,else do out(即基于true / false的選項選擇)。
==>marko
==>ripple
==>lop
==>lop
gremlin> g.V().hasLabel('person').
choose(values('age')).
option(27, __.in()).
option(32, __.out()).values('name') //2.使用遍歷的結果作為遍歷選項的映射關鍵(即基于值的選項選擇)。
==>marko
==>ripple
==>lop
- 請注意,choose()可以有任意數量的選項,而且可以采用匿名遍歷作為其選擇功能。
gremlin> g.V().hasLabel('person').
choose(values('name')).
option('marko', values('age')).
option('josh', values('name')).
option('vadas', valueMap()).
option('peter', label())
==>29
==>[name:[vadas],age:[27]]
==>josh
==>person
- choose() 可以利用Pick.none選項匹配。對于與指定選項不匹配的任何內容,將采用none-option。
gremlin> g.V().hasLabel('person').
choose(values('name')).
option('marko', values('age')).
option(none, values('name'))
==>29
==>vadas
==>josh
==>peter
Coalesce 合并
- This coalesce(): 評估,以便所提供的遍歷,并返回該發射的至少一種元素的第一遍歷。
gremlin> g.V(1).coalesce(outE('knows'), outE('created')).inV().path().by('name').by(label)
==>[marko,knows,vadas]
==>[marko,knows,josh]
gremlin> g.V(1).coalesce(outE('created'), outE('knows')).inV().path().by('name').by(label)
==>[marko,created,lop]
gremlin> g.V(1).property('nickname', 'okram')
==>v[1]
gremlin> g.V().hasLabel('person').coalesce(values('nickname'), values('name'))
==>okram
==>vadas
==>josh
==>peter
Coin
- This coin():要隨機篩選出一個遍歷器.
- 提供的雙重論點偏向于“擲硬幣”。
gremlin> g.V().coin(0.5)
==>v[1]
==>v[2]
==>v[6]
gremlin> g.V().coin(0.0)
gremlin> g.V().coin(1.0)
==>v[1]
==>v[2]
==>v[3]
==>v[4]
==>v[5]
==>v[6]
Constant 常量
- This constant():要為移動器指定常量值
- 通常適用于像choose()-step或coalesce()-step這樣的條件步驟。
gremlin> g.V().choose(hasLabel('person'),
values('name'),
constant('inhuman')) //1.顯示人物的名字,但顯示其他頂點的“inhuman”。
==>marko
==>vadas
==>inhuman
==>josh
==>inhuman
==>peter
gremlin> g.V().coalesce(
hasLabel('person').values('name'),
constant('inhuman')) //2.與陳述1相同(除非有沒有名字的人頂點)。
==>marko
==>vadas
==>inhuman
==>josh
==>inhuman
==>peter
Count 計數
- This count():對在該流表示traversers的總數(即,批量計數)。
gremlin> g.V().count()
==>6
gremlin> g.V().hasLabel('person').count()
==>4
gremlin> g.V().hasLabel('person').outE('created').count().path() //1.count()-step是一個減少的屏障步驟,意味著所有以前的遍歷器都被折疊成一個新的遍歷器。
==>[4]
gremlin> g.V().hasLabel('person').outE('created').count().map {it.get() * 10}.path() //2.從... count()開始的移動器的路徑從count()。
==>[4,40]
CyclicPath 循環路徑
- 每個遍歷器通過遍歷圖 - 即其路徑來維護其歷史。如果遍歷器重復它的過程很重要,那么cyclic()應該使用-path(過濾器)
- 該步驟至此分析遍歷器的路徑,并且如果有任何重復,遍歷器將在遍歷計算中被濾除。如果需要非循環行為,請參閱simplePath()。
gremlin> g.V(1).both().both()
==>v[1]
==>v[4]
==>v[6]
==>v[1]
==>v[5]
==>v[3]
==>v[1]
gremlin> g.V(1).both().both().cyclicPath()
==>v[1]
==>v[1]
==>v[1]
gremlin> g.V(1).both().both().cyclicPath().path()
==>[v[1],v[3],v[1]]
==>[v[1],v[2],v[1]]
==>[v[1],v[4],v[1]]
gremlin> g.V(1).as('a').out('created').as('b').
in('created').as('c').
cyclicPath().
path()
==>[v[1],v[3],v[1]]
gremlin> g.V(1).as('a').out('created').as('b').
in('created').as('c').
cyclicPath().from('a').to('b').
path()
Dedup 刪除重復
- This dedup():反復看到的對象將從遍歷流中移除。
- 請注意,如果移動器的體積大于1,則在發射之前將其設置為1。
gremlin> g.V().values('lang')
==>java
==>java
gremlin> g.V().values('lang').dedup()
==>java
gremlin> g.V(1).repeat(bothE('created').dedup().otherV()).emit().path() //1。遍歷所有created邊,但不要碰兩邊。
==>[v[1],e[9][1-created->3],v[3]]
==>[v[1],e[9][1-created->3],v[3],e[11][4-created->3],v[4]]
==>[v[1],e[9][1-created->3],v[3],e[12][6-created->3],v[6]]
==>[v[1],e[9][1-created->3],v[3],e[11][4-created->3],v[4],e[10][4-created->5],v[5]]
- 如果提供了逐步調制dedup(),則在確定是否已經看到對象之前對該對象進行相應處理。
gremlin> g.V().valueMap(true, 'name')
==>[id:1,name:[marko],label:person]
==>[id:2,name:[vadas],label:person]
==>[id:3,name:[lop],label:software]
==>[id:4,name:[josh],label:person]
==>[id:5,name:[ripple],label:software]
==>[id:6,name:[peter],label:person]
gremlin> g.V().dedup().by(label).values('name')
==>marko
==>lop
- 如果dedup()提供了一個字符串數組,那么它將確保重復數據刪除不是針對當前的遍歷器對象,而是針對遍歷器的路徑歷史記錄。
gremlin> g.V().as('a').out('created').as('b').in('created').as('c').select('a','b','c')
==>[a:v[1],b:v[3],c:v[1]]
==>[a:v[1],b:v[3],c:v[4]]
==>[a:v[1],b:v[3],c:v[6]]
==>[a:v[4],b:v[5],c:v[4]]
==>[a:v[4],b:v[3],c:v[1]]
==>[a:v[4],b:v[3],c:v[4]]
==>[a:v[4],b:v[3],c:v[6]]
==>[a:v[6],b:v[3],c:v[1]]
==>[a:v[6],b:v[3],c:v[4]]
==>[a:v[6],b:v[3],c:v[6]]
gremlin> g.V().as('a').out('created').as('b').in('created').as('c').dedup('a','b').select('a','b','c') //1。如果之前已經看到電流a和b組合,則過濾移動器。
==>[a:v[1],b:v[3],c:v[1]]
==>[a:v[4],b:v[5],c:v[4]]
==>[a:v[4],b:v[3],c:v[1]]
==>[a:v[6],b:v[3],c:v[1]]
Drop 下降
- This drop():用于除去從所述圖形元素和屬性(即刪除)。
- 這是一個過濾步驟,因為遍歷不會產生傳出對象。
gremlin> g.V().outE().drop()
gremlin> g.E()
gremlin> g.V().properties('name').drop()
gremlin> g.V().valueMap()
==>[age:[29]]
==>[age:[27]]
==>[lang:[java]]
==>[age:[32]]
==>[lang:[java]]
==>[age:[35]]
gremlin> g.V().drop()
gremlin> g.V()
Emit
- This emit():不是實際的一步,但不是為一個步調制器repeat()(找到更多的文檔emit()存在)。
Explain 解釋
This explain():(終端)將返回一個TraversalExplanation。
遍歷解釋詳細說明了遍歷(之前explain())將如何在給定注冊遍歷策略的情況下編譯。
-
A TraversalExplanation具有toString()3列的表示。
- 第一列是應用的遍歷策略。
- 第二列是遍歷策略類別:[D]生態化,[O]優化,[P]漫游器優化,[F]實現和[V]驗證。
- 最后,第三列是遍歷后策略應用程序的狀態。最后的遍歷是由此產生的執行計劃。
gremlin> g.V().hasLabel('person').outE().identity().inV().count().is(gt(5)).explain()
==>Traversal Explanation
=====================================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), CountGlobalStep, IsStep(gt(5))]
ConnectiveStrategy [D] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), CountGlobalStep, IsStep(gt(5))]
RepeatUnrollStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), CountGlobalStep, IsStep(gt(5))]
IncidentToAdjacentStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), CountGlobalStep, IsStep(gt(5))]
MatchPredicateStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), CountGlobalStep, IsStep(gt(5))]
PathRetractionStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), CountGlobalStep, IsStep(gt(5))]
CountStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
FilterRankingStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
InlineFilterStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
AdjacentToIncidentStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
LazyBarrierStrategy [O] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
TinkerGraphCountStrategy [P] [GraphStep(vertex,[]), HasStep([~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
TinkerGraphStepStrategy [P] [TinkerGraphStep(vertex,[~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
ProfileStrategy [F] [TinkerGraphStep(vertex,[~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
StandardVerificationStrategy [V] [TinkerGraphStep(vertex,[~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
Final Traversal [TinkerGraphStep(vertex,[~label.eq(person)]), VertexStep(OUT,edge), IdentityStep, EdgeVertexStep(IN), RangeGlobalStep(0,6), CountGlobalStep, IsStep(gt(5))]
Fold 折疊
- 遍歷流需要一個“屏障”來聚合所有對象并發出一個計算函數作為聚合函數
gremlin> g.V(1).out('knows').values('name')
==>vadas
==>josh
gremlin> g.V(1).out('knows').values('name').fold() //1。無參數fold()會將所有對象聚合到列表中,然后發出列表。
==>[vadas,josh]
gremlin> g.V(1).out('knows').values('name').fold().next().getClass() //2。無參數fold()會將所有對象聚合到列表中,然后發出列表。
==>class java.util.ArrayList
gremlin> g.V(1).out('knows').values('name').fold(0) {a,b -> a + b.length()} //3。fold() 可以提供兩個參數 - 一個種子值和一個減少雙向函數(“vadas”是5個字符+“josh”,4個字符)。
==>9
gremlin> g.V().values('age').fold(0) {a,b -> a + b} //4。圖中人的總年齡是多少?
==>123
gremlin> g.V().values('age').fold(0, sum) //5。與以前一樣,但使用內置的雙功能。
==>123
gremlin> g.V().values('age').sum() //6。與以前一樣,但使用內置的雙功能。
==>123
From
- This from():不是一個實際的步驟,而是一個類似于as()和 的“階躍調節器” by()。
- 如果一個步驟能夠接受遍歷或字符串,那么from()它們就是添加它們的手段。一般模式是step().from()。見 - to()步。
gremlin> g.V().has('name', within('marko', 'vadas', 'josh')).as('person').
V().has('name', within('lop', 'ripple')).addE('uses').from('person')
==>e[13][1-uses->3]
==>e[14][1-uses->5]
==>e[15][2-uses->3]
==>e[16][2-uses->5]
==>e[17][4-uses->3]
==>e[18][4-uses->5]
Graph
- This graph():通常用于啟動GraphTraversal,但也可以使用中間穿越。
remlin> g.V().has('name', within('marko', 'vadas', 'josh')).as('person').
V().has('name', within('lop', 'ripple')).addE('uses').from('person').toString() //1。通常這個步驟V()將遍歷所有的頂點。但是,圖策略可以折疊HasContainer’s into a `GraphStep以允許索引查找。
==>[GraphStep(vertex,[]), HasStep([name.within([marko, vadas, josh])])@[person], GraphStep(vertex,[]), HasStep([name.within([lop, ripple])]), AddEdgeStep({~from=[[SelectOneStep(last,person)]], label=[uses]})]
gremlin> g.V().has('name', within('marko', 'vadas', 'josh')).as('person').
V().has('name', within('lop', 'ripple')).addE('uses').from('person').iterate().toString() //2。圖形系統提供者是否支持中間遍歷V()索引查找可以通過檢查toString()迭代遍歷的輸出來輕松確定。如果has條件被折疊成步驟,則將V()使用索引(如果存在的話)。
==>[TinkerGraphStep(vertex,[name.within([marko, vadas, josh])])@[person], TinkerGraphStep(vertex,[name.within([lop, ripple])]), AddEdgeStep({~from=[[SelectOneStep(last,person)]], label=[uses]}), NoneStep]
Group 組
- 當遍歷器遍歷一個由遍歷定義的圖時,有時需要sideEffect計算。
- 也就是說,所采用的實際路徑或者移動器的當前位置不是計算的最終輸出,而是遍歷的一些其他表示。
- 所述group()工序(地圖 / sideEffect)就是這樣一種sideEffect,根據對象的某些功能組織的對象。然后,如果需要,該組織(列表)將減少。
gremlin> g.V().group().by(label) //1.按照它們的標簽對頂點進行分組。
==>[software:[v[3],v[5]],person:[v[1],v[2],v[4],v[6]]]
gremlin> g.V().group().by(label).by('name') //2.對于組中的每個頂點,獲取它們的名稱。
==>[software:[lop,ripple],person:[marko,vadas,josh,peter]]
gremlin> g.V().group().by(label).by(count()) //3.對于每個分組,它的大小是多少?
==>[software:2,person:4]
-
可以group()通過的兩個投影參數by()是:
Key-projection:組合對象的哪個特征(產生map鍵的函數)
價值投影:該組的哪些功能要存儲在密鑰列表中
GroupCount 分組統計
- This groupCount():特定對象在遍歷的特定部分有多少次
gremlin> g.V().hasLabel('person').values('age').groupCount()
==>[32:1,35:1,27:1,29:1]
gremlin> g.V().hasLabel('person').groupCount().by('age') //1.您還可以提供預組投影,其中提供的by()調制決定了將傳入對象分組的內容。
==>[32:1,35:1,27:1,29:1]
Has 有
-
This has():根據其屬性過濾頂點,邊和頂點屬性。有很多變化,has()包括:
has(key,value):如果元素沒有提供的鍵/值屬性,則移除該移動器。
has(label, key, value):如果元素沒有指定的標簽并提供鍵/值屬性,則移除該移動器。
has(key,predicate):如果元素沒有滿足雙謂詞的鍵值,則移除該移動器。有關謂詞的更多信息,請閱讀關于謂詞的注釋。
hasLabel(labels…?):如果元素沒有任何標簽,則移除移動器。
hasId(ids…?):如果元素沒有任何id,則移除移動器。
hasKey(keys…?):如果屬性沒有提供所有提供的鍵,則移除移動器。
hasValue(values…?):如果移動器的屬性沒有提供所有提供的值,則移除移動器。
has(key):如果移動元素的元素沒有鍵值,則移除移動元素。
hasNot(key):如果元素的值為該鍵,則移除該移動器。
has(key, traversal):如果移動器的對象沒有通過遍歷屬性值產生結果,則移除移動器。
gremlin> g.V().hasLabel('person')
==>v[1]
==>v[2]
==>v[4]
==>v[6]
gremlin> g.V().hasLabel('person').out().has('name',within('vadas','josh'))
==>v[2]
==>v[4]
gremlin> g.V().hasLabel('person').out().has('name',within('vadas','josh')).
outE().hasLabel('created')
==>e[10][4-created->5]
==>e[11][4-created->3]
gremlin> g.V().has('age',inside(20,30)).values('age') //1.查找年齡在20(含)和30(不含)之間的所有頂點。
==>29
==>27
gremlin> g.V().has('age',outside(20,30)).values('age') //2.查找年齡不在20(含)和30(不含)之間的所有頂點。
==>32
==>35
gremlin> g.V().has('name',within('josh','marko')).valueMap() //3.查找名稱完全匹配集合中任何名稱的所有頂點[josh,marko],顯示這些頂點的所有鍵和值對。
==>[name:[marko],age:[29]]
==>[name:[josh],age:[32]]
gremlin> g.V().has('name',without('josh','marko')).valueMap() //4.查找名稱不在集合中的所有頂點[josh,marko],顯示這些頂點的所有鍵,值對。對。
==>[name:[vadas],age:[27]]
==>[name:[lop],lang:[java]]
==>[name:[ripple],lang:[java]]
==>[name:[peter],age:[35]]
gremlin> g.V().has('name',not(within('josh','marko'))).valueMap() //5.和前面的例子一樣,使用noton within來保存without。
==>[name:[vadas],age:[27]]
==>[name:[lop],lang:[java]]
==>[name:[ripple],lang:[java]]
==>[name:[peter],age:[35]]
gremlin> g.V().properties().hasKey('age').value() //6.查找所有年齡屬性并發布其價值。
==>29
==>27
==>32
==>35
gremlin> g.V().hasNot('age').values('name') //7.查找所有沒有年齡屬性并發出其名稱的頂點。
==>lop
==>ripple
Id
- 接受一個Element,并從中提取其標識符。
gremlin> g.V().id()
==>1
==>2
==>3
==>4
==>5
==>6
gremlin> g.V(1).out().id().is(2)
==>2
gremlin> g.V(1).outE().id()
==>9
==>7
==>8
gremlin> g.V(1).properties().id()
==>0
==>1
Identity 恒定
- This identity():是恒等函數,其中當前對象映射到其自身。
gremlin> g.V().identity()
==>v[1]
==>v[2]
==>v[3]
==>v[4]
==>v[5]
==>v[6]
Inject 注入
- This inject():將對象任意插入到遍歷流中
gremlin> g.V(4).out().values('name').inject('daniel')
==>daniel
==>ripple
==>lop
gremlin> g.V(4).out().values('name').inject('daniel').map {it.get().length()}
==>6
==>6
==>3
gremlin> g.V(4).out().values('name').inject('daniel').map {it.get().length()}.path()
==>[daniel,6]
==>[v[4],v[5],ripple,6]
==>[v[4],v[3],lop,3]
Is 是
- This is():過濾標量值
gremlin> g.V().values('age').is(32)
==>32
gremlin> g.V().values('age').is(lte(30))
==>29
==>27
gremlin> g.V().values('age').is(inside(30, 40))
==>32
==>35
gremlin> g.V().where(__.in('created').count().is(1)).values('name') //1.查找只有一個貢獻者的項目。
==>ripple
gremlin> g.V().where(__.in('created').count().is(gte(2))).values('name') //2.查找有兩個或更多貢獻者的項目。
==>lop
gremlin> g.V().where(__.in('created').values('age').
mean().is(inside(30d, 35d))).values('name') //3.查找貢獻者平均年齡在30歲到35歲之間的項目。
==>lop
==>ripple
Key 鍵
- This key():需要Property,并從中提取的關鍵。
gremlin> g.V(1).properties().key()
==>name
==>location
==>location
==>location
==>location
gremlin> g.V(1).properties().properties().key()
==>startTime
==>endTime
==>startTime
==>endTime
==>startTime
==>endTime
==>startTime
Label 標簽
- 需要一個Element并從中提取其標簽。
gremlin> g.V().label()
==>person
==>person
==>software
==>person
==>software
==>person
gremlin> g.V(1).outE().label()
==>created
==>knows
==>knows
gremlin> g.V(1).properties().label()
==>name
==>age
Limit 限制
- 類似于range()-步驟保存的下端范圍被設定為0。
gremlin> g.V().limit(2)
==>v[1]
==>v[2]
gremlin> g.V().range(0, 2)
==>v[1]
==>v[2]
- 這個步驟limit()也可以應用Scope.local,在這種情況下,它在收到的收集上運行。
gremlin> g.V().valueMap().select('location').limit(local,2) //1.List<String> 對于包含前兩個位置的每個頂點。
==>[san diego,santa cruz]
==>[centreville,dulles]
==>[bremen,baltimore]
==>[spremberg,kaiserslautern]
gremlin> g.V().valueMap().limit(local, 1) //2.Map<String, Object> 為每個頂點,但只包含第一個屬性值。
==>[name:[marko]]
==>[name:[stephen]]
==>[name:[matthias]]
==>[name:[daniel]]
==>[name:[gremlin]]
==>[name:[tinkergraph]]
Local 本地
- A GraphTraversal在連續的對象流上運行。
- 在很多情況下,在該流內的單個元素上操作非常重要。為了做這種對象局部遍歷計算
gremlin> g.V().as('person').
properties('location').order().by('startTime',incr).limit(2).value().as('location').
select('person','location').by('name').by() //1.根據歷史最悠久的地點開始時間獲取前兩個人和他們各自的位置。
==>[person:daniel,location:spremberg]
==>[person:stephen,location:centreville]
gremlin> g.V().as('person').
local(properties('location').order().by('startTime',incr).limit(2)).value().as('location').
select('person','location').by('name').by() //2.對于每個人來說,他們的兩個最具歷史意義的地點
==>[person:marko,location:san diego]
==>[person:marko,location:santa cruz]
==>[person:stephen,location:centreville]
==>[person:stephen,location:dulles]
==>[person:matthias,location:bremen]
==>[person:matthias,location:baltimore]
==>[person:daniel,location:spremberg]
==>[person:daniel,location:kaiserslautern]
Loops 循環
- This loops():提取的次數的數目Traverser已經通過電流環路消失。
remlin> g.V().emit(__.has("name", "marko").or().loops().is(2)).repeat(__.out()).values("name")
==>marko
==>ripple
==>lop
Match 匹配
- 提供了一個更加聲明 基于的概念圖表查詢的形式圖案匹配。
- 用戶提供了一組“遍歷碎片”,稱為模式,它們定義了必須在整個持續時間內保持為真的變量match()。
- 當一個遍歷器進入時match(),一個注冊 MatchAlgorithm分析遍歷器的當前狀態(也就是基于其路徑數據的歷史 ),遍歷模式的運行時統計信息,并返回遍歷器應該接下來嘗試的遍歷模式。
- MatchAlgorithm提供的默認值被調用CountMatchAlgorithm并且它通過根據模式的過濾能力對模式進行排序來動態修改模式執行計劃(即,最大集合縮減模式首先執行)。
gremlin> g.V().match(
__.as('a').out('created').as('b'),
__.as('b').has('name', 'lop'),
__.as('b').in('created').as('c'),
__.as('c').has('age', 29)).
select('a','c').by('name')
==>[a:marko,c:marko]
==>[a:josh,c:marko]
==>[a:peter,c:marko]
- 為了提高可讀性,as()可以為步驟提供有意義的標簽,以更好地反映您的域名。因此,以前的查詢可以用更具表現力的方式編寫,如下所示。
gremlin> g.V().match(
__.as('creators').out('created').has('name', 'lop').as('projects'), //1.找到創建東西的頂點并將它們匹配為“創建者”,然后找出他們創建的名為“lop”并將這些頂點匹配為“項目”的頂點。
__.as('projects').in('created').has('age', 29).as('cocreators')). //2.使用這些'項目'頂點,找出他們的創作者29歲,并記住這些'共同創作者'。
select('creators','cocreators').by('name') //3.返回'創作者'和'共同創作者'的名字。
==>[creators:marko,cocreators:marko]
==>[creators:josh,cocreators:marko]
==>[creators:peter,cocreators:marko]
使用匹配的地方
- 匹配通常與兩者select()(先前演示)和where()(在此展示)一起使用。
- A- where()step允許用戶進一步限制由提供的結果集match()。
gremlin> g.V().match(
__.as('a').out('created').as('b'),
__.as('b').in('created').as('c')).
where('a', neq('c')).
select('a','c').by('name')
==>[a:marko,c:josh]
==>[a:marko,c:peter]
==>[a:josh,c:marko]
==>[a:josh,c:peter]
==>[a:peter,c:marko]
==>[a:peter,c:josh]
- where()-步驟可以采取任一個P-predicate(例如上文)或一個Traversal(下面例子)。使用時 MatchPredicateStrategy,where()-clauses自動折疊match(),因此受制于查詢優化器match()。
gremlin> traversal = g.V().match(
__.as('a').has(label,'person'), //1\
__.as('a').out('created').as('b'),
__.as('b').in('created').as('c')).
where(__.as('a').out('knows').as('c')). //2\
select('a','c').by('name'); null //3\
gremlin> traversal.toString() //4\
==>[GraphStep(vertex,[]), MatchStep(AND,[[MatchStartStep(a), HasStep([~label.eq(person)]), MatchEndStep], [MatchStartStep(a), VertexStep(OUT,[created],vertex), MatchEndStep(b)], [MatchStartStep(b), VertexStep(IN,[created],vertex), MatchEndStep(c)]]), WhereTraversalStep([WhereStartStep(a), VertexStep(OUT,[knows],vertex), WhereEndStep(c)]), SelectStep(last,[a, c],[value(name)])]
gremlin> traversal // (5)
==>[a:marko,c:josh]
gremlin> traversal.toString() //7\
==>[TinkerGraphStep(vertex,[~label.eq(person)])@[a], MatchStep(AND,[[MatchStartStep(a), VertexStep(OUT,[created],vertex), MatchEndStep(b)], [MatchStartStep(b), VertexStep(IN,[created],vertex), MatchEndStep(c)], [MatchStartStep(a), WhereTraversalStep([WhereStartStep, VertexStep(OUT,[knows],vertex), WhereEndStep(c)]), MatchEndStep]]), SelectStep(last,[a, c],[value(name)])]
Math
- 科學計算器功能
gremlin> g.V().as('a').out('knows').as('b').math('a + b').by('age')
==>56.0
==>61.0
gremlin> g.V().as('a').out('created').as('b').
math('b + a').
by(both().count().math('_ + 100')).
by('age')
==>132.0
==>133.0
==>135.0
==>138.0
gremlin> g.withSideEffect('x',10).V().values('age').math('_ / x')
==>2.9
==>2.7
==>3.2
==>3.5
gremlin> g.withSack(1).V(1).repeat(sack(sum).by(constant(1))).times(10).emit().sack().math('sin _')
==>0.9092974268256817
==>0.1411200080598672
==>-0.7568024953079282
==>-0.9589242746631385
==>-0.27941549819892586
==>0.6569865987187891
==>0.9893582466233818
==>0.4121184852417566
==>-0.5440211108893698
==>-0.9999902065507035
-
通過計算器支持的運營商包括:*,+,\,^,和%。此外,還提供了以下內置功能:
abs: 絕對值
acos:反余弦
asin:反正弦
atan:反正切
cbrt:立方根
ceil:最接近的大整數
cos:余弦
cosh:雙曲余弦
exp:歐拉的號碼提升到了力量(e^x)
floor:最接近的較小整數
log:logarithmus naturalis(基數e)
log10:對數(基數10)
log2:對數(基數2)
sin:正弦
sinh:雙曲正弦
sqrt: 平方根
tan:切線
tanh:雙曲正切
signum:signum函數
Max
- 最大值
gremlin> g.V().values('age').max()
==>35
gremlin> g.V().repeat(both()).times(3).values('age').max()
==>35
Mean 平均值
- 操作數的流,并確定這些數字的平均值。
gremlin> g.V().values('age').mean()
==>30.75
gremlin> g.V().repeat(both()).times(3).values('age').mean() //1\
==>30.645833333333332
gremlin> g.V().repeat(both()).times(3).values('age').dedup().mean()
==>30.75
Min 最小值
- 操作數的流,并確定它是在流中的最小數目。
gremlin> g.V().values('age').min()
==>27
gremlin> g.V().repeat(both()).times(3).values('age').min()
==>27
Not
- (過濾器時遍歷提供作為參數不返回任何對象)去除遍歷流對象。
gremlin> g.V().not(hasLabel('person')).valueMap(true)
==>[id:3,name:[lop],label:software,lang:[java]]
==>[id:5,name:[ripple],label:software,lang:[java]]
gremlin> g.V().hasLabel('person').
not(out('created').count().is(gt(1))).values('name') //1.喬什創建了兩個項目,而沒有任何項目
==>marko
==>vadas
==>peter
Option
- An option to a branch() or choose().
Optional
- 如果它產生的結果,否則返回調用元件
- 返回指定遍歷的結果identity()。
gremlin> g.V(2).optional(out('knows')) //1.vadas沒有離開的知識邊緣,所以vadas被返回。
==>v[2]
gremlin> g.V(2).optional(__.in('knows')) //2.vadas確實有一個傳入知識邊緣,所以marko被返回。
==>v[1]
Or 或者
- This or():確保了提供遍歷中的至少一個產生的結果
gremlin> g.V().or(
__.outE('created'),
__.inE('created').count().is(gt(1))).
values('name')
==>marko
==>lop
==>josh
==>peter
- 一個中間符號可以被使用。盡管用中綴表示法,只有兩次遍歷可以在一起。
gremlin> g.V().where(outE('created').or().outE('knows')).values('name')
==>marko
==>josh
==>peter
Order 排序
- 當遍歷流的對象需要排序時
gremlin> g.V().values('name').order()
==>josh
==>lop
==>marko
==>peter
==>ripple
==>vadas
gremlin> g.V().values('name').order().by(decr)
==>vadas
==>ripple
==>peter
==>marko
==>lop
==>josh
gremlin> g.V().hasLabel('person').order().by('age', incr).values('name')
==>vadas
==>marko
==>josh
==>peter
- 遍歷中最遍歷的對象之一是Element。元素可以具有與其關聯的屬性(即鍵/值對)。在許多情況下,需要根據元素屬性的比較對元素遍歷流進行排序。
gremlin> g.V().values('name')
==>marko
==>vadas
==>lop
==>josh
==>ripple
==>peter
gremlin> g.V().order().by('name',incr).values('name')
==>josh
==>lop
==>marko
==>peter
==>ripple
==>vadas
gremlin> g.V().order().by('name',decr).values('name')
==>vadas
==>ripple
==>peter
==>marko
==>lop
==>josh
- 可以用來order(local)排序當前的本地對象,而不是整個遍歷流。這適用于 Collection- 和Map- 類型的對象。對于任何其他對象,該對象將保持不變。
gremlin> g.V().values('age').fold().order(local).by(decr) //1。年齡被收集到一個列表中,然后該列表按降序排列。
==>[35,32,29,27]
gremlin> g.V().values('age').order(local).by(decr) //2。年齡不收集,因此order(local)是“排序”單個整數,因此,什么都不做。
==>29
==>27
==>32
==>35
gremlin> g.V().groupCount().by(inE().count()).order(local).by(values, decr) //3。該groupCount()地圖是由它的遞減順序值進行排序。
==>[1:3,0:2,3:1]
gremlin> g.V().groupCount().by(inE().count()).order(local).by(keys, incr) //4。該groupCount()圖是通過其在遞增的順序排列的鍵。
==>[0:2,1:3,3:1]
Path 路徑
- 遍歷器在遍歷中的一系列步驟中進行轉換。遍歷器的歷史通過用path()-step(地圖)檢查其路徑來實現。
gremlin> g.V().out().out().values('name')
==>ripple
==>lop
gremlin> g.V().out().out().values('name').path()
==>[v[1],v[4],v[5],ripple]
==>[v[1],v[4],v[3],lop]
- 可以通過循環方式后處理路徑的元素by()。
gremlin> g.V().out().out().path().by('name').by('age')
==>[marko,32,ripple]
==>[marko,32,lop]
Profile
- 為了讓開發者介紹他們的遍歷,以確定像步運行,計數等統計信息
gremlin> g.V().out('created').repeat(both()).times(3).hasLabel('person').values('age').sum().profile()
==>Traversal Metrics
Step Count Traversers Time (ms) % Dur
=============================================================================================================
TinkerGraphStep(vertex,[]) 6 6 0.076 11.61
VertexStep(OUT,[created],vertex) 4 4 0.108 16.39
NoOpBarrierStep(2500) 4 2 0.050 7.63
VertexStep(BOTH,vertex) 10 4 0.045 6.86
NoOpBarrierStep(2500) 10 3 0.025 3.81
VertexStep(BOTH,vertex) 24 7 0.028 4.34
NoOpBarrierStep(2500) 24 5 0.030 4.62
VertexStep(BOTH,vertex) 58 11 0.040 6.15
NoOpBarrierStep(2500) 58 6 0.046 7.03
HasStep([~label.eq(person)]) 48 4 0.033 5.08
PropertiesStep([age],value) 48 4 0.042 6.37
SumGlobalStep 1 1 0.133 20.11
>TOTAL - - 0.662 -
Project
- 突出的當前對象到Map
gremlin> g.V().out('created').
project('a','b').
by('name').
by(__.in('created').count()).
order().by(select('b'),decr).
select('a')
==>lop
==>lop
==>lop
==>ripple
gremlin> g.V().has('name','marko').
project('out','in').
by(outE().count()).
by(inE().count())
==>[out:3,in:0]
Program
是“lambda”步驟GraphComputer的作業。
該步驟將 VertexProgram作為參數并相應地處理傳入圖。
-
因此,用戶可以創建自己的VertexProgram并在遍歷中執行它。提供給頂點程序的配置包括:
gremlin.vertexProgramStep.rootTraversal是PureTraversal根遍歷的一種形式的序列化。
gremlin.vertexProgramStep.stepId是program()正在執行的-step 的步驟字符串id 。
gremlin> g = graph.traversal().withComputer()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], graphcomputer]
gremlin> g.V().hasLabel('person').
program(PageRankVertexProgram.build().property('rank').create(graph)).
order().by('rank', incr).
valueMap('name', 'rank')
==>[name:[marko],rank:[0.11375510357865541]]
==>[name:[peter],rank:[0.11375510357865541]]
==>[name:[vadas],rank:[0.14598540152719106]]
==>[name:[josh],rank:[0.14598540152719106]]
Properties 屬性
- 提取屬性Element遍歷流。
gremlin> g.V(1).properties()
==>vp[name->marko]
==>vp[location->san diego]
==>vp[location->santa cruz]
==>vp[location->brussels]
==>vp[location->santa fe]
gremlin> g.V(1).properties('location').valueMap()
==>[startTime:1997,endTime:2001]
==>[startTime:2001,endTime:2004]
==>[startTime:2004,endTime:2005]
==>[startTime:2005]
gremlin> g.V(1).properties('location').has('endTime').valueMap()
==>[startTime:1997,endTime:2001]
==>[startTime:2001,endTime:2004]
==>[startTime:2004,endTime:2005]
PropertyMap
- 步驟產生一個元素的屬性的地圖表示
gremlin> g.V().propertyMap()
==>[name:[vp[name->marko]],age:[vp[age->29]]]
==>[name:[vp[name->vadas]],age:[vp[age->27]]]
==>[name:[vp[name->lop]],lang:[vp[lang->java]]]
==>[name:[vp[name->josh]],age:[vp[age->32]]]
==>[name:[vp[name->ripple]],lang:[vp[lang->java]]]
==>[name:[vp[name->peter]],age:[vp[age->35]]]
gremlin> g.V().propertyMap('age')
==>[age:[vp[age->29]]]
==>[age:[vp[age->27]]]
==>[]
==>[age:[vp[age->32]]]
==>[]
==>[age:[vp[age->35]]]
gremlin> g.V().propertyMap('age','blah')
==>[age:[vp[age->29]]]
==>[age:[vp[age->27]]]
==>[]
==>[age:[vp[age->32]]]
==>[]
==>[age:[vp[age->35]]]
gremlin> g.E().propertyMap()
==>[weight:p[weight->0.5]]
==>[weight:p[weight->1.0]]
==>[weight:p[weight->0.4]]
==>[weight:p[weight->1.0]]
==>[weight:p[weight->0.4]]
==>[weight:p[weight->0.2]]
Range
- This range():當遍歷器通過遍歷傳播時,可能只允許一定數量的它們通過.
- 當范圍的低端不符合時,對象繼續迭代。在低(包含)和高(獨占)范圍內,發射移動器。當在高范圍以上時,遍歷就會脫離迭代。最后,-1高范圍的使用將在低范圍開始后發射剩余的移動器。
gremlin> g.V().range(0,3)
==>v[1]
==>v[2]
==>v[3]
gremlin> g.V().range(1,3)
==>v[2]
==>v[3]
gremlin> g.V().range(1, -1)
==>v[2]
==>v[3]
==>v[4]
==>v[5]
==>v[6]
gremlin> g.V().repeat(both()).times(1000000).emit().range(6,10)
==>v[1]
==>v[5]
==>v[3]
==>v[1]
- range()也可以應用Scope.local,在這種情況下,它在收到的收集上運行。例如,可以Map
gremlin> g.V().as('a').out().as('b').in().as('c').select('a','b','c').by('name').range(local,1,2)
==>[b:lop]
==>[b:lop]
==>[b:lop]
==>[b:vadas]
==>[b:josh]
==>[b:ripple]
==>[b:lop]
==>[b:lop]
==>[b:lop]
==>[b:lop]
==>[b:lop]
==>[b:lop]
Repeat
- 用于遍歷給予一定的休息謂詞遍歷。
gremlin> g.V(1).repeat(out()).times(2).path().by('name') //1.do-while semantics stating to do out() 2 times.
==>[marko,josh,ripple]
==>[marko,josh,lop]
gremlin> g.V().until(has('name','ripple')).
repeat(out()).path().by('name') //2.while-do語義如果遍歷器位于名為“ripple”的頂點,則聲明為中斷。
==>[marko,josh,ripple]
==>[josh,ripple]
==>[ripple]