GremlinコンソールのTips

[TinkerPop](https://tinkerpop.apache.org/)フレームワークの[Gremlinコンソール](http://tinkerpop.apache.org/docs/3.4.6/tutorials/the-gremlin-console/)についての豆知識をまとめておきます。

## コマンド

### :help

Gremlinコンソールで何ができるかについては`:help`または`?`で一覧が表示される

### :remote

Gremlinサーバーに接続するには`:remote`を使う。基本的には以下のコマンドを丸暗記すればよい。

```groovy
gremlin> :remote connect tinkerpop.server conf/remote.yaml [session|session-managed]
```

サーバーのドメインやポート番号を変えた場合はconf/remote.yamlをコピーして書き換えたものを使う。
~~末尾に`session`をつけるとリモートコマンドの結果を変数として受け取ることができる。つけないとコマンド実行毎に環境がリセットされる。ただし、`session`を付けた場合他プロセスからのグラフ変更が出来なくなる(ロックされる？)ことに注意。グラフの操作に慣れたらもう付けない方がいい。~~

[2020/04/28加筆]
:remoteコマンド末尾には`session`または`session-managed`オプションを付け加えることができる。これらの効果について以下に示す。

*未指定(セッションレス)*
オプションを指定しない場合はセッションレス接続となる。コンソール上で1つ命令を送信するたびにトランザクションが開始され、コミットされる。すなわち、`addVertex`や`addV`のようなグラフに対する変更は都度自動的にコミットされる。また、1命令ごとに環境がリセットされるため、変数を持つことが出来ない。すなわち、戻り値を受け取るようなコードを記述しても、戻り値は消失するため使用することは出来ない。

*session*
オプション`session`を指定した場合はセッションモードになる。トランザクションは自分で管理する必要がある。すなわち、グラフに対する変更は自分でコミットしない限り反映されない。その一方で、ロールバックを行うことも可能なので、自由度が高い。セッションが継続している間は変数が保持されるため、命令の戻り値を使用することができる。

*session-managed*
オプション`session-managed`を指定した場合はセッションモードになる。`session`との違いは、セッションレスの場合と同様に1つ命令を送信するたびにトランザクションの開始とコミットが行われる点である。セッションが継続している間は変数が保持されるため、セッションレスの場合よりは融通が利く。

|オプション|トランザクション|変数|
|---|---|---|
|未指定|自動|保持されない|
|session|手動|保持される|
|session-managed|自動|保持される|


### :exit

Gremlinコンソールを閉じる

### :load

指定したスクリプトファイルに記述されたコマンドを1行ずつ順に実行する。

```groovy
gremlin> :load sample.groovy
```


## グラフの生成

練習用あるいは解析用のグラフを生成する方法はいくつかある。

### TinkerGraph

空のグラフを作るには`open`関数を用いる

```groovy
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
```

### TinkerFactory

TinkerPopのチュートリアル用グラフファクトリー

以下の5種類のグラフ生成関数がある。

|関数名|説明|図|
|---|---|---|
|createModern()|チュートリアル用グラフ(TinkerPop ver3以降)<br>頂点数6辺数6|[リンク](https://tinkerpop.apache.org/docs/current/reference/#graph-computing)<br>[画像直](https://tinkerpop.apache.org/docs/current/images/tinkerpop-modern.png)|
|createClassic()|チュートリアル用グラフ(TinkerPop ver2以前)※仕様が古く、頂点ラベルを持たない。今からあえて使う理由はない|
|createKitchenSink()|検証用グラフ。自己ループを持つ頂点を含む。<br>頂点数3辺数3|なし|
|createTheCrew()|チュートリアル用グラフ。createModernより情報が多いバージョン<br>頂点数6辺数14|[リンク](https://tinkerpop.apache.org/docs/current/reference/#vertex-properties)<br>[画像直](https://tinkerpop.apache.org/docs/current/images/the-crew-graph.png)|
|createGratefulDead()|ロックバンド・グレイトフルデッドのシングル曲データを格納したグラフ。頂点数808辺数8049|なし|

```groovy
gremlin> graph = TinkerFactory.createModern()
==>tinkergraph[vertices:6 edges:6]
gremlin> graph = TinkerFactory.createTheCrew()
==>tinkergraph[vertices:6 edges:14]
gremlin> graph = TinkerFactory.createGratefulDead()
==>tinkergraph[vertices:808 edges:8049]
```

また、`generate*`関数を用いると、既存のグラフに対してデータを挿入することができる。

```groovy
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> TinkerFactory.generateModern(graph)
==>null
gremlin> graph
==>tinkergraph[vertices:6 edges:6]
```


## Groovyリフレクション

オブジェクトの型やメソッドが分かるとクエリの動作の理解に役立つ。

### クラス名の取得

```groovy
gremlin> graph.class  // 変数名.classでクラス名を取得できる
==>class org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph
```

`クラス名 javadoc current`でググれば最新版JavaDocのページに辿り着ける。`クラス名.java`で検索するとgithubのページ(実装ソースコード)に辿り着ける。地味に役立つ。


### メソッド一覧の取得

```groovy
gremlin> graph.class.methods  // 変数名.class.methodsでメソッド一覧を取得できる
==>public java.lang.String org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.toString()
==>public void org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.clear()
==>public void org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.close()
==>public org.apache.tinkerpop.gremlin.process.computer.GraphComputer org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.compute()
==>public org.apache.tinkerpop.gremlin.process.computer.GraphComputer org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.compute(java.lang.Class)
...
```

正直読みにくいので使いどころはあまりない。


## その他

### リモートコマンドの戻り値をローカルで使う

リモートコマンドの結果は、ローカルの`result`という変数に格納されている。

```groovy
gremlin> :> g.V().values("name")
==>marko
==>bob
gremlin> result
==>result{object=marko class=java.lang.String}
==>result{object=bob class=java.lang.String}
gremlin> result[0]["object"]
==>marko
gremlin> result[1]["object"]
==>bob
```

使うかと言えば使わない……。

### 自動Terminal-Step実行を阻止

Gremlinコンソール上でクエリを実行すると、自動的に[Terminal-Steps](https://tinkerpop.apache.org/docs/current/reference/#terminal-steps)を送ってクエリが完了してしまう。それが嫌で、クエリを作るだけに留めたい場合は以下のようにする。

```groovy
gremlin> query = g.V(); null  // クエリを作る(実行はしない)
==>null
gremlin> vertices = query.toList(); null  // クエリを実行して結果を得る
==>null
gremlin> vertices  // 結果を確認する
==>v[1]
==>v[2]
==>v[3]
==>v[4]
==>v[5]
==>v[6]
```

コマンドの戻り値がGraphTraversal系の型だと、自動的にTerminal-Stepsを実行してしまうので、セミコロンで区切った後で、nullを評価するようにすると、Terminal-Steps実行は行われない。Gremlinコンソール上でTerminal-Stepsの動きを勉強する際にしか役に立たない情報だが、個人的には一応役に立ったので記しておく。