各図データベースクエリー言語(Gremlin vs Cypher vs nGQL)|操作入門編

15396 ワード

まず、ウィキペディアの定義に基づいて、図データベースは、ノード、エッジ、属性を使用してデータを表示および格納する図構造を使用して意味クエリを行うデータベースです.
リレーショナル・データベースに格納されている構造とは異なります(リレーショナル・データベースは表構造、図データベースは図構造)が、それぞれのパフォーマンスの問題にかかわらず、リレーショナル・データベースは再帰クエリーまたは他のSQL文(Join)を組み合わせて図クエリー言語クエリー・ノードのリレーションシップ操作を完了できます.1987年にSQLが国際標準化機構(ISO)標準になったおかげで、関係型データベース業界はよく発展した.60、70年代の関係型データベースと同様に、図データベースという分野のクエリー言語には現在も統一基準がなく、19年9月に国際SQL標準委員会の投票採決を経て、図クエリー言語(Graph Query Language)を新しいデータベースクエリー言語に納めることを決定したが、GQLの制定にはまだ時間がかかる.
市場に統一された図検索言語の標準がないことを介在して、本文の中で私達は市場の主流のいくつかの図検索言語を選んで1波の用法を分析して、紙面の原因のため本文は図検索言語と通常の用法を簡単に紹介することを目的として、更に詳しい内容は進級編の中で述べる.
図クエリー言語・紹介
図クエリ言語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言語のキーワードは大文字と小文字を区別しませんが、属性値、ラベル、関係タイプ、変数は大文字と小文字を区別します.
サポート図データベース:Neo 4 j、RedisGraph、AgensGraph
図クエリ言語nGQL
nGQLは一種のSQLの声明型のテキスト検索言語であり、nGQLは同様にキーワードの大文字と小文字に敏感ではない検索言語であり、現在はモードマッチング、集約演算、図計算をサポートし、組合せ文を埋め込むことができない.
サポート図データベース:Nebula Graph
図クエリ言語・用語編
この3つの図クエリー言語を比較する前に、それぞれの用語を見てみましょう.ドキュメントをめくると、次のような「キーワード」がよく見られます.ここでは、使い方を説明せずに、これらの図データベースの一般的な概念がこの3つの図データベースのドキュメントで使われている呼び方だけを見てみましょう.
用語
Gremlin
Cypher
nGQL

Vertex
Node
Vertex
エッジ
Edge
Relationship
Edge
ポイントタイプ
Label
Label
Tag
エッジタイプ
label
RelationshipType
edge type
ポイントID
vid
id(n)
vid
エッジID
eid
id(r)
なし
挿入
add
create
insert
削除
drop
delete
delete/drop
属性の更新
setProperty
set
update
点と辺の呼び方はほぼ似ているが,CypherではRelationship関係という言葉を直接用いて辺を表す.他の用語は基本的に直感的です.
図クエリ言語・文法編
Gremlin、Cypher、nGQLの一般的な用語を理解した後、この3つの図を使用して言語をクエリーするときに理解する必要がある一般的な構文を見てみましょう.
# Gremlin    
g = TinkerGraph.open().traversal()

# nGQL      
CREATE SPACE gods


図構造は点とエッジからなり、1つのエッジに2つの点が接続されています.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という対応するタイプを許容する.ポイント・タイプには、次のようなさまざまなプロパティがあります.Person _name、age _などです.
ポイントタイプの作成
ポイントタイプに関する構文の例は次のとおりです.
# Gremlin      
g.addV(vertexLabel).property()

# nGQL      
CREATE tagName(PropNameList)

ここでは、GremlinおよびnGQLにおいて、IF NOT EXISTSのような使用法が存在する場合、すなわち、存在しない場合は作成され、存在する場合は直接返される.
ビューポイントタイプ
ポイントを作成した後、ポイントタイプをどのように表示するかは、以下の方法を参照してください.
# Gremlin   (  )   
g.V().label().dedup();

# Cypher         1
MATCH (n) 
RETURN DISTINCT labels(n)
# Cypher         2
CALL db.labels();

# nGQL      
SHOW TAGS

ポイントのCRUD
ポイント、ポイントタイプについて簡単に説明しました.次に、データベースの基本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での削除操作に対応する単語はDeleteDropであり,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)

エッジのCRUD
エッジタイプはエッジの通常の操作部分に入るべきだと言いました.
指定したエッジタイプのエッジを挿入
和点の使用文法は似ているが,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) OVER  REVERSELY

むほうこう
でエッジの が でない ( 、 のいずれでもよい)、Gremlinはboth()、Cypherは-[]-、nGQLはキーワードBIDIRECTを する.
# Traverse edges with specified vertices Gremlin
g.V().bothE()

# Traverse edges with specified vertices Cypher
MATCH (n)-[r:label]-()

# Traverse edges with specified vertices nGQL
GO FROM   OVER  BIDIRECT

されたエッジNホップを ポイントクエリに って する
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 

した2 パスを します
# Gremlin         
g.V().repeat(out()).until().path()

# Cypher         
MATCH p =(a)-[.*]->(b)
WHERE condition
RETURN p

# nGQL         
FIND ALL PATH FROM  TO  OVER *


を した 、 の を す だ. な を げてください.
: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
# Cypher
cypher> 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]->()

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