一文了解大圖數據庫查詢語言(Gremlin vs Cypher vs nGQL)| 操作入門篇

      網友投稿 1041 2022-05-30

      文章的開頭我們先來看下什么是圖數據庫,根據維基百科的定義:圖數據庫是使用圖結構進行語義查詢的數據庫,它使用節點、邊和屬性來表示和存儲數據。

      雖然和關系型數據庫存儲的結構不同(關系型數據庫為表結構,圖數據庫為圖結構),但不計各自的性能問題,關系型數據庫可以通過遞歸查詢或者組合其他 SQL 語句(Join)完成圖查詢語言查詢節點關系操作。得益于 1987 年 SQL 成為國際標準化組織(ISO)標準,關系型數據庫行業得到了很好的發展。同 60、70 年代的關系型數據庫類似,圖數據庫這個領域的查詢語言目前也沒有統一標準,雖然 19 年 9 月經過國際 SQL 標準委員會投票表決,決定將圖查詢語言(Graph Query Language)納為一種新的數據庫查詢語言,但 GQL 的制定仍需要一段時間。

      介于市面上沒有統一的圖查詢語言標準,在本文中我們選取市面上主流的幾款圖查詢語言來分析一波用法,由于篇幅原因本文旨在簡單介紹圖查詢語言和常規用法,更詳細的內容將在進階篇中講述。

      圖查詢語言·介紹

      圖查詢語言 Gremlin

      Gremlin?是 Apache ThinkerPop 框架下的圖遍歷語言。Gremlin 可以是聲明性的也可以是命令性的。雖然 Gremlin 是基于 Groovy 的,但具有許多語言變體,允許開發人員以 Java、JavaScript、Python、Scala、Clojure 和 Groovy 等許多現代編程語言原生編寫 Gremlin 查詢。

      支持圖數據庫:Janus Graph、InfiniteGraph、Cosmos DB、DataStax Enterprise(5.0+) 、Amazon Neptune

      圖查詢語言 Cypher

      Cypher 是一個描述性的圖形查詢語言,允許不必編寫圖形結構的遍歷代碼對圖形存儲有表現力和效率的查詢,和 SQL 很相似,Cypher 語言的關鍵字不區分大小寫,但是屬性值,標簽,關系類型和變量是區分大小寫的。

      支持圖數據庫: Neo4j、RedisGraph、AgensGraph

      圖查詢語言 nGQL

      nGQL?是一種類 SQL 的聲明型的文本查詢語言,nGQL 同樣是關鍵詞大小寫不敏感的查詢語言,目前支持模式匹配、聚合運算、圖計算,可無嵌入組合語句。

      支持圖數據庫:Nebula Graph

      圖查詢語言·術語篇

      在比較這 3 個圖查詢語言之前,我們先來看看他們各自的術語,如果你翻閱他們的文檔會經常見到下面這些“關鍵字”,在這里我們不講用法,只看這些圖數據庫常用概念在這 3 個圖數據庫文檔中的叫法。

      我們可以看到大體上對點和邊的叫法類似,只不過 Cypher 中直接使用了 Relationship 關系一詞代表邊。其他的術語基本都非常直觀。

      圖查詢語言·語法篇

      了解過 Gremlin、Cypher、nGQL 中常見的術語之后,我們來看看使用這 3 個圖查詢語言過程中會需要了解的常規語法。

      #?Gremlin?創建圖 g?=?TinkerGraph.open().traversal() #?nGQL?創建圖空間 CREATE?SPACE?gods

      圖結構由點和邊組成,一條邊連接兩個點。在 Gremlin 和 nGQL 中稱之為 Vertex,Cypher 則稱之為 Node。如何在圖數據庫中新建一個點呢?可以參考下面的語法

      #?Gremlin?創建/插入點 g.addV(vertexLabel).property() #?Cypher?創建點 CREATE?(:nodeLabel?{property}) #?nGQL?創建/插入點 INSERT?VERTEX?tagName?(propNameList)?VALUES?vid:(tagKey?propValue)

      點允許有對應的類型,在 Gremlin 和 Cypher 叫?label?,在 nGQL 中為?tag?。點類型可對應有多種屬性(Property),例如 _Person _可以有?name、_age _等屬性。

      點類型相關的語法示例如下:

      #?Gremlin?創建點類型 g.addV(vertexLabel).property() #?nGQL?創建點類型 CREATE?tagName(PropNameList)

      這里說明下,無論在 Gremlin 和 nGQL 中存在類似?IF NOT EXISTS? 用法,即:如果不存在則創建,存在則直接返回。

      創建好點之后如何查看點類型呢,可以參考以下方式。

      #?Gremlin?查看(獲?。c類型 g.V().label().dedup(); #?Cypher?查看點類型方法?1 MATCH?(n)? RETURN?DISTINCT?labels(n) #?Cypher?查看點類型方法?2 CALL?db.labels(); #?nGQL?查看點類型 SHOW?TAGS

      上面簡單介紹了點、點類型,下面進入數據庫基本 DML——CRUD,在上文介紹點時順便介紹了點的創建和插入,這里說下如何插入特定類型的點,和點的獲取、刪除和更新。

      和插入點的操作類似,只不過需要指定某種點類型。語法參考:

      #?Gremlin?插入特定類型點 g.addV(String?vertexLabel).property() #?Cypher?插入特定類型點 CREATE?(node:label)? #?nGQL?插入特定類型點 INSERT?VERTEX??(prop_name_list)?VALUES?:(prop_value_list)

      #?Gremlin?查看點 g.V() #?Cypher?查看點MATCH?(n)? WHERE?condition RETURN?properties(n) #?nGQL?查看點 FETCH?PROP?ON??

      術語篇中提過 nGQL 中刪除操作對應單詞有?Delete?和?Drop?,在 nGQL 中 Delete 一般用于點邊,Drop 用于 Schema 刪除,這點和 SQL 的設計思路是一樣的。

      #?Gremlin?刪除點 g.V().drop() #?Cypher?刪除點 MATCH?(node:label)? DETACH?DELETE?node #?nGQL?刪除點 DELETE?VERTEX?

      用數據庫的小伙伴都知道數據的常態是數據變更,來瞅瞅這 3 個圖查詢是使用什么語法來更新點數據的吧

      #?Gremlin?更新點 g.V().property() #?Cypher?更新點 SET?n.prop?=?V #?nGQL?更新點 UPDATE?VERTEX??SET?

      可以看到 Cypher 和 nGQL 都使用 SET 關鍵詞來設置點對應的類型值,只不過 nGQL 中多了 UPDATE 關鍵詞來標識操作,Gremlin 的操作和上文提到的查看點類似,只不過增加了變更 property 值操作。

      在 Gremlin 和 nGQL 稱呼邊為 Edge,而 Cypher 稱之為 Relationship。下面進入到邊相關的語法內容

      和點一樣,邊也可以有對應的類型

      #?Gremlin?創建邊類型 g.edgeLabel() #?nGQL?創建邊類型 CREATE?EDGE?edgeTypeName(propNameList)

      說完邊類型應該進入到邊的常規操作部分了

      可以看到和點的使用語法類似,只不過在 Cypher 和 nGQL 中分別使用?-[]->?和?->?來表示關系,而 Gremlin 則用?to()?關鍵詞來標識指向關系,在使用這 3 種圖查詢語言的圖數據庫中的邊均為有向邊,下圖左邊為有向邊,右邊為無向邊。

      #?Gremlin?插入指定邊類型的邊 g.addE(String?edgeLabel).from(v1).to(v2).property() #?Cypher?插入指定邊類型的邊 CREATE?(:)- ??[(:)]??->(:) #?nGQL?插入指定邊類型的邊 INSERT?EDGE??()?VALUES??->?:?\ ()

      #?Gremlin?刪除邊 g.E().drop() #?Cypher?刪除邊 MATCH?(:)-[r:relationship-label-name]->() DELETE?r #?nGQL?刪除邊DELETE?EDGE???->?

      #?Gremlin?查看指定邊 g.E() #?Cypher?查看指定邊 MATCH?(n)-[r:label]->() WHERE?condition RETURN?properties(r) #?nGQL?查看指定邊 FETCH?PROP?ON???->?

      其他操作

      除了常規的點、邊 CRUD 外,我們可以簡單看看這 3 種圖查詢語言的組合查詢。

      #?Gremlin?指定點查指定邊 g.V().outE() #?Cypher?指定點查指定邊 Match?(n)->[r:label]->[] WHERE?id(n)?=?vid RETURN?r #?nGQL?指定點查指定邊 GO?FROM??OVER?

      在反向查詢中,Gremlin 使用了 in 來表示反向關系,而 Cypher 則更直觀的將指向箭頭反向變成?<-?來表示反向關系,nGQL 則用關鍵詞?REVERSELY?來標識反向關系。

      #?Gremlin?沿指定點反向查詢指定邊 g.V().inE() #?Cypher?沿指定點反向查詢指定邊 MATCH?(n)<-[r:label]-() #?nGQL?沿指定點反向查詢指定邊 GO?FROM??OVER??REVERSELY

      如果在圖中,邊的方向不重要(正向、反向都可以),那 Gremlin 使用?both()?,Cypher 使用?-[]-?,nGQL使用關鍵詞?BIDIRECT?。

      #?Traverse?edges?with?specified?vertices?Gremling. V().bothE() #?Traverse?edges?with?specified?vertices?Cypher MATCH?(n)-[r:label]-() #?Traverse?edges?with?specified?vertices?nGQL GO?FROM???OVER??BIDIRECT

      Gremlin 和 nGQL 分別用 times 和 step 來表示 N 跳關系,而 Cypher 用?relationship*1..N?來表示 N 跳關系。

      #?Gremlin?沿指定點查詢指定邊?N?跳 g.V().repeat(out()).times(N) #?Cypher?沿指定點查詢指定邊?N?跳 MATCH?(n)-[r:label*N]->() WHERE?condition RETURN?r #?nGQL?沿指定點查詢指定邊?N?跳 GO?N?STEPS?FROM??OVER?

      #?Gremlin?返回指定兩點路徑 g.V().repeat(out()).until().path() #?Cypher?返回指定兩點路徑 MATCH?p?=(a)-[.*]->(b) WHERE?condition RETURN?p #?nGQL?返回指定兩點路徑 FIND?ALL?PATH?FROM??TO??OVER?*

      圖查詢語言·實操篇

      一文了解各大圖數據庫查詢語言(Gremlin vs Cypher vs nGQL)| 操作入門篇

      說了一通語法之后,是時候展示真正的技術了——來個具體一點的例子。

      示例圖:The Graphs of Gods

      實操示例使用了?Janus Graph?的示例圖?The Graphs of Gods。該圖結構如下圖所示,描述了羅馬萬神話中諸神關系。

      插入數據

      #?插入點 ##?nGQL nebula>?INSERT?VERTEX?character(name,?age,?type)?VALUES?hash("saturn"):("saturn",?10000,?"titan"),?hash("jupiter"):("jupiter",?5000,?"god"); ##?Gremlin gremlin>?saturn?=?g.addV("character").property(T.id,?1).property('name',?'saturn').property('age',?10000).property('type',?'titan').next(); ==>v[1] gremlin>?jupiter?=?g.addV("character").property(T.id,?2).property('name',?'jupiter').property('age',?5000).property('type',?'god').next(); ==>v[2] gremlin>?prometheus?=?g.addV("character").property(T.id,?31).property('name',??'prometheus').property('age',?1000).property('type',?'god').next(); ==>v[31] gremlin>?jesus?=?g.addV("character").property(T.id,?32).property('name',??'jesus').property('age',?5000).property('type',?'god').next(); ==>v[32] ##?Cypher cypher>?CREATE?(src:character?{name:"saturn",?age:?10000,?type:"titan"}) cypher>?CREATE?(dst:character?{name:"jupiter",?age:?5000,?type:"god"}) #?插入邊 ##?nGQL nebula>?INSERT?EDGE?father()?VALUES?hash("jupiter")->hash("saturn"):(); ##?Gremlin gremlin>?g.addE("father").from(jupiter).to(saturn).property(T.id,?13); ==>e[13][2-father->1] ##?Cypher cypher>?CREATE?(src)-[rel:father]->(dst)

      刪除數據

      #?nGQL nebula>?DELETE?VERTEX?hash("prometheus"); #?Gremlin gremlin>?g.V(prometheus).drop(); #?Cypher cypher>?MATCH?(n:character?{name:"prometheus"})?DETACH?DELETE?n

      更新數據

      #?nGQL nebula>?UPDATE?VERTEX?hash("jesus")?SET?character.type?=?'titan'; #?Gremlin gremlin>?g.V(jesus).property('age',?6000); ==>v[32] #?Cypher cypher>?MATCH?(n:character?{name:"jesus"})?SET?n.type?=?'titan';

      查看數據

      #?nGQL nebula>?FETCH?PROP?ON?character?hash("saturn"); =================================================== |?character.name?|?character.age?|?character.type?| =================================================== |?saturn?????????|?10000?????????|?titan??????????| --------------------------------------------------- #?Gremlin gremlin>?g.V(saturn).valueMap(); ==>[name:[saturn],type:[titan],age:[10000]] #?Cypher cypher>?MATCH?(n:character?{name:"saturn"})?RETURN?properties(n) ??╒════════════════════════════════════════════╕ ??│"properties(n)"?????????????????????????????│ ??╞════════════════════════════════════════════╡ ??│{"name":"saturn","type":"titan","age":10000}│ ??└────────────────────────────────────────────┘

      查詢 hercules 的父親

      #?nGQL nebula>??LOOKUP?ON?character?WHERE?character.name?==?'hercules'?|?\ ??????->?GO?FROM?$-.VertexID?OVER?father?YIELD?$$.character.name; ===================== |?$$.character.name?| ===================== |?jupiter???????????| --------------------- #?Gremlin gremlin>?g.V().hasLabel('character').has('name','hercules').out('father').values('name'); ==>jupiter #?Cypherc ypher>?MATCH?(src:character{name:"hercules"})-[:father]->(dst:character)?RETURN?dst.name ??????╒══════════╕ ??????│"dst.name"│ ??????╞══════════╡ ??????│"jupiter"?│ ??????└──────────┘

      查詢 hercules 的祖父

      #?nGQL nebula>?LOOKUP?ON?character?WHERE?character.name?==?'hercules'?|?\ ?????->?GO?2?STEPS?FROM?$-.VertexID?OVER?father?YIELD?$$.character.name; ===================== |?$$.character.name?| ===================== |?saturn????????????| --------------------- #?Gremlin gremlin>?g.V().hasLabel('character').has('name','hercules').out('father').out('father').values('name'); ==>saturn #?Cypher cypher>?MATCH?(src:character{name:"hercules"})-[:father*2]->(dst:character)?RETURN?dst.name ??????╒══════════╕ ??????│"dst.name"│ ??????╞══════════╡ ??????│"saturn"??│ ??????└──────────┘

      查詢年齡大于 100 的人物

      #?nGQL nebula>?LOOKUP?ON?character?WHERE?character.age?>?100?YIELD?character.name,?character.age; ========================================================= |?VertexID?????????????|?character.name?|?character.age?| ========================================================= |?6761447489613431910??|?pluto??????????|?4000??????????| --------------------------------------------------------- |?-5860788569139907963?|?neptune????????|?4500??????????| --------------------------------------------------------- |?4863977009196259577??|?jupiter????????|?5000??????????| --------------------------------------------------------- |?-4316810810681305233?|?saturn?????????|?10000?????????| --------------------------------------------------------- #?Gremlin gremlin>?g.V().hasLabel('character').has('age',gt(100)).values('name'); ==>saturn ==>jupiter ==>neptune ==>pluto #?Cypher cypher>?MATCH?(src:character)?WHERE?src.age?>?100?RETURN?src.name ??????╒═══════════╕ ??????│"src.name"?│ ??????╞═══════════╡ ??????│??"saturn"?│ ??????├───────────┤ ??????│?"jupiter"?│ ??????├───────────┤ ??????│?"neptune"?│ ??????│───────────│ ??????│??"pluto"??│ ??????└───────────┘

      從一起居住的人物中排除 pluto 本人

      #?nGQL nebula>??GO?FROM?hash("pluto")?OVER?lives?YIELD?lives._dst?AS?place?|?GO?FROM?$-.place?OVER?lives?REVERSELY?WHERE?\ $$.character.name?!=?"pluto"?YIELD?$$.character.name?AS?cohabitants; =============== |?cohabitants?| =============== |?cerberus????| --------------- #?Gremlin gremlin>?g.V(pluto).out('lives').in('lives').where(is(neq(pluto))).values('name'); ==>cerberus #?Cypher cypher>?MATCH?(src:character{name:"pluto"})-[:lives]->()<-[:lives]-(dst:character)?RETURN?dst.name ??????╒══════════╕ ??????│"dst.name"│ ??????╞══════════╡ ??????│"cerberus"│ ??????└──────────┘

      Pluto 的兄弟們

      #?which?brother?lives?in?which?place? ##?nGQL nebula>?GO?FROM?hash("pluto")?OVER?brother?YIELD?brother._dst?AS?god?|?\ GO?FROM?$-.god?OVER?lives?YIELD?$^.character.name?AS?Brother,?$$.location.name?AS?Habitations; ========================= |?Brother?|?Habitations?| ========================= |?jupiter?|?sky?????????| ------------------------- |?neptune?|?sea?????????| ------------------------- ##?Gremlin gremlin>?g.V(pluto).out('brother').as('god').out('lives').as('place').select('god','place').by('name'); ==>[god:jupiter,?place:sky] ==>[god:neptune,?place:sea] ##?Cypher cypher>?MATCH?(src:Character{name:"pluto"})-[:brother]->(bro:Character)-[:lives]->(dst) RETURN?bro.name,?dst.name ??????╒═════════════════════════╕ ??????│"bro.name"????│"dst.name"│ ??????╞═════════════════════════╡ ??????│?"jupiter"????│??"sky"???│ ??????├─────────────────────────┤ ??????│?"neptune"????│?"sea"????│ ??????└─────────────────────────┘

      附錄

      Nebula Graph:一個開源的分布式圖數據庫

      GitHub:https://github.com/vesoft-inc/nebula

      官方論壇:https://discuss.nebula-graph.io

      知乎:zhihu.com/org/nebulagraph/posts

      微博:weibo.com/nebulagraph

      數據庫

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:React Hooks 學習筆記
      下一篇:一篇文章帶你深入了解Dubbo分布式服務框架
      相關文章
      亚洲色偷精品一区二区三区| 亚洲人成小说网站色| 亚洲av综合日韩| 亚洲综合色区中文字幕| 亚洲欧洲春色校园另类小说| 亚洲视频国产视频| 777亚洲精品乱码久久久久久| 婷婷亚洲综合五月天小说| 亚洲av午夜成人片精品网站 | 亚洲中文字幕一二三四区苍井空 | 久久久青草青青国产亚洲免观| 亚洲AV无码一区二区三区在线观看| 精品国产_亚洲人成在线| 国产精品亚洲专区无码不卡| 国产成人亚洲综合无| 亚洲国产精品综合久久一线| 久久亚洲av无码精品浪潮| 亚洲中文字幕无码久久综合网| 国产成人亚洲精品青草天美| 久久精品国产精品亚洲蜜月| 亚洲精品美女久久久久9999| 亚洲国产精品成人综合久久久 | 国产专区一va亚洲v天堂| 国产AV无码专区亚洲AWWW | 亚洲欧美成人综合久久久| 亚洲国产精品精华液| 国产亚洲精品国产福利在线观看| 亚洲日韩中文字幕日韩在线| 国产亚洲精品a在线无码| 亚洲精品免费观看| 亚洲国产成人在线视频| 亚洲精华国产精华精华液网站| 亚洲AⅤ男人的天堂在线观看| 国产青草亚洲香蕉精品久久| 国产国拍亚洲精品福利| 亚洲VA中文字幕无码毛片| 99久久亚洲综合精品成人网| 亚洲一卡二卡三卡| 大桥未久亚洲无av码在线| 久久亚洲国产成人精品无码区| 亚洲高清国产拍精品26U|