【初心者】Amazon Neptune を使ってみる

# 1. 目的
- AWSのデータベース関連サービスの復習をしている。Amazon Neptune について、マネージドのGraphDBとのことだが、そもそもGraphDBを全く触ったことがなかったため、GraphDBって何？？から学習して概要を理解する。

# 2. Amazon Neptune とは（自分の理解）
- GraphDB は、例えばFacebookでの人間関係(AさんとBさんが友達関係、AさんがCさんをフォロー)とか、物と物の関係性をデータベース化したい時に適しているデータベース。GraphDBをマネージドで使えるようにしているのがAmazon Neptune。
- 他の人のやってみた記事を見てざっくりどんなものなのか確認した。
    - 「[Amazon NeptuneでグラフDBを使ってみる](https://www.blog.danishi.net/2021/02/03/post-4493/)」
        - DB環境の作成、サンプルレコードの作成までが記載されており、とっかかりになった。
    - 「[はじめてのGraphDB Amazon Neptune](https://dev.classmethod.jp/articles/first-time-graphdb-amazon-neptune/)」
        - Vertex, Edge といったGraphDBの要素の初心者向け説明もあり参考になった。

# 3. やったこと
- 利用環境を整備する。(Neptune DBの作成、Jupyter Notebookからの接続)
- アンパンマンのキャラクターの関係をデータ入力し、検索してみる。

# 4. 構成図
- 利用環境の構成図

![nep構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/390102f1-b91a-0de0-e780-86048dfaabcb.png)

# 5. 設定手順
## 5.1 Neptune DBの作成
- あらかじめ、サブネットを2つ持つVPCを作成しておく。
- マネージドコンソールの「Neptune」-「データベース」-「データベースの作成」を選択し、以下のように作成する。

![nep01a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/834fc7ba-a4b0-a44c-0e2a-d0c0325d1f49.png)

![nep02a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/98903206-7ce2-7dab-01a4-f9b2978d639f.png)

## 5.2 Notebookの作成
- Neptune DBの操作（データの入力や検索など）を行うためのJupyter Notebookを作成する。（以前はEC2インスタンスを立てて、データ操作用のソフトをインストールして、DBに接続して…という環境構築が必要だったがようだが、簡便化された様子。接続したいNeptune DBを指定してNotebookを作成するだけで、すぐにデータ操作を開始することができる。）
- 「Neptune」- 「Notebooks」-「ノートブックの作成」を選択し、以下のように作成する。

![nep04a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/3c81e291-888f-83de-2cea-bb2cd5aa7e44.png)


- 作成したノートブックインスタンスを開き、Python3の新しいノートブックを作成する。

![nep06a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/98627849-1776-86d5-fa75-e65f9ab10987.png)

- Status コマンドで、Neptune DBと問題なく接続していることを確認する。

![nep07a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/34d1e3bd-15b8-eade-796c-0cbe4c8cc990.png)



## 5.3 データの設計

- アンパンマンのキャラクターの関係を例にデータベースを作成してみる。

![nep08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/262a3412-cab6-3928-63e4-7be9d66701d3.png)

- 表現したい内容は以下の通り。
    - アンパンマン、しょくぱんまん、カレーパンマンは友達。
    - ばいきんまんはアンパンマンが嫌い。
    - ばいきんぱんとホラーマンはドキンちゃんが好き。ドキンちゃんはしょくぱんまんが好き。
    - アンパンマン、しょくぱんまん、カレーパンマンは善。ばいきんまんとドキンちゃんは悪。ホラーマンは中立。
    - ばいきんまんの乗り物はばいきんUFOとだだんだん。

- 上記の表現をGraphDBのやり方に合わせると以下の通り。 
    - Vertex(頂点)として、キャラクター(アンパンマンなど)や乗り物(ばいきんUFOなど)を定義する。
    - Vertexにはidを付与する。(c1: アンパンマン、c2: ばいきんまん、v1: ばいきんUFO など)　※idは自分でつけない場合自動的にUUIDが付与される。見た目が良くないので今回はidを明示的に付与。
    - VertexのLabelとして、「Character」(キャラクター)、「Vehicle」(乗り物)を定義する。
    - VertexのPropertyとして、「name」でキャラクターや乗り物の名前を、「side」で立場(good(正義)、evil(悪)、neutral(中立))を定義する。
    - Edge(関係)として、like,hate,friend,rideを定義する。

- 各キャラクターの関係性については念のため「[アンパンマン恋愛相関図・恋人まとめ【複雑すぎる恋愛事情】](https://manga-manga.site/2019/01/31/%E3%82%A2%E3%83%B3%E3%83%91%E3%83%B3%E3%83%9E%E3%83%B3%E6%81%8B%E6%84%9B%E7%9B%B8%E9%96%A2%E5%9B%B3%E3%83%BB%E6%81%8B%E4%BA%BA%E3%81%BE%E3%81%A8%E3%82%81%E3%80%90%E8%A4%87%E9%9B%91%E3%81%99%E3%81%8E/)」も参照。


## 5.4 データの投入
- データ操作を行うフレームワークとして、「Gremlin」と「SPARQL」が用意されている。他の人の記事などを見た感じだとGremlin派のほうが多そうなため、Gremlinで練習することにする。前の手順で作成したJupyter Notebookにて、Gremlinを用いたデータ操作が可能。

- 最初にVertexのデータを入力する。id, label, propertyを指定してVertexを追加していく。 ※idを付与する時に、「'id'」ではなく「id」にする必要があることにハマった。

```
%%gremlin
g.addV('character').property(id,'c1').property('name', 'アンパンマン').property('side', 'good').toSet()
g.addV('character').property(id,'c2').property('name', 'ばいきんまん').property('side', 'evil').toSet()
g.addV('character').property(id,'c3').property('name', 'カレーパンマン').property('side', 'good').toSet()
g.addV('character').property(id,'c4').property('name', 'しょくぱんまん').property('side', 'good').toSet()
g.addV('character').property(id,'c5').property('name', 'ドキンちゃん').property('side', 'evil').toSet()
g.addV('character').property(id,'c6').property('name', 'ホラーマン').property('side', 'neutral').toSet()
g.addV('vehicle').property(id,'v1').property('name', 'ばいきんUFO').toSet()
g.addV('vehicle').property(id,'v2').property('name', 'だだんだん').toSet()
```

- 次にEdgeのデータを入力する。両端のVertex及び方向を指定してEdgeを追加していく。※複数行いっぺんに入れるとなぜかエラーになり、1行ずつ投入した。

```
%%gremlin
g.addE('friend').from_(g.V().has('name','アンパンマン')).to(g.V().has('name','カレーパンマン')).toSet()
g.addE('friend').from_(g.V().has('name','アンパンマン')).to(g.V().has('name','しょくぱんまん')).toSet()
g.addE('friend').from_(g.V().has('name','しょくぱんまん')).to(g.V().has('name','カレーパンマン')).toSet()
g.addE('friend').from_(g.V().has('name','しょくぱんまん')).to(g.V().has('name','アンパンマン')).toSet()
g.addE('friend').from_(g.V().has('name','カレーパンマン')).to(g.V().has('name','アンパンマン')).toSet()
g.addE('friend').from_(g.V().has('name','カレーパンマン')).to(g.V().has('name','しょくぱんまん')).toSet()
g.addE('hate').from_(g.V().has('name','ばいきんまん')).to(g.V().has('name','アンパンマン')).toSet()
g.addE('like').from_(g.V().has('name','ばいきんまん')).to(g.V().has('name','ドキンちゃん')).toSet()
g.addE('like').from_(g.V().has('name','ホラーマン')).to(g.V().has('name','ドキンちゃん')).toSet()
g.addE('like').from_(g.V().has('name','ドキンちゃん')).to(g.V().has('name','しょくぱんまん')).toSet()
g.addE('ride').from_(g.V().has('name','ばいきんまん')).to(g.V().has('name','ばいきんUFO')).toSet()
g.addE('ride').from_(g.V().has('name','ばいきんまん')).to(g.V().has('name','だだんだん')).toSet()
```

## 5.5 データの検索

- Vertexの一覧を取得する。

```
%%gremlin
g.V().valueMap()

1 	{'side': ['good'], 'name': ['アンパンマン']}
2 	{'side': ['evil'], 'name': ['ばいきんまん']}
3 	{'side': ['good'], 'name': ['カレーパンマン']}
4 	{'side': ['good'], 'name': ['しょくぱんまん']}
5 	{'side': ['evil'], 'name': ['ドキンちゃん']}
6 	{'side': ['neutral'], 'name': ['ホラーマン']}
7 	{'name': ['ばいきんUFO']}
8 	{'name': ['だだんだん']} 
```

- Edgeの一覧を取得する。


```
%%gremlin
g.E()

1 	e[ccbc823d-4a0f-052e-e439-46fd702e99f0][c3-friend->c1]
2 	e[bcbc823d-c150-626a-596f-e2f74b87542e][c6-like->c5]
3 	e[6abc823c-d091-ae7b-1503-c7517a40e387][c1-friend->c4]
4 	e[0cbc823d-63d0-7b17-fbff-d4b67b0f8ff2][c3-friend->c4]
5 	e[8cbc823c-ff59-a1a4-ced4-925497d35304][c4-friend->c3]
6 	e[e2bc823d-db8e-d975-299c-85397e429806][c5-like->c4]
7 	e[70bc823d-83ff-0819-4a4c-81d704a5bdd6][c2-hate->c1]
8 	e[52bc823e-011a-26f3-3ac5-1493defae96a][c2-ride->v1]
9 	e[90bc823c-8b3d-f5d0-1a66-9091d0454a39][c1-friend->c3]
10 	e[72bc823d-29e0-d0bb-b7da-5a8ef31a2ab9][c4-friend->c1] 

```

- 「「悪」サイドのキャラクターは誰か？」を検索する。

```
%%gremlin
g.V().hasLabel('character').has('side','evil').values('name')

1 	ばいきんまん
2 	ドキンちゃん 
```

- 「ドキンちゃんの意中のキャラクターは？」を検索する。

```
g.V().hasLabel('character').has('name', 'ドキンちゃん').outE('like').inV().values('name')

1 	しょくぱんまん 
```

- 「ドキンちゃんのことを好きなのは誰か？」を検索する。

```
%%gremlin
g.V().hasLabel('character').has('name', 'ドキンちゃん').inE('like').outV().values('name')

1 	ホラーマン
2 	ばいきんまん 
```

## 5.6 データの可視化の確認

- DBの内容を可視化できる機能が追加されたとのことで、試してみる。
    - [Amazon Neptune が、Neptune Workbench でのグラフ可視化機能を発表](https://aws.amazon.com/jp/about-aws/whats-new/2020/08/amazon-neptune-announces-graph-visualization-in-neptune-workbench/)

![nep09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/5f677e3a-b69e-8758-888e-58d2cbc5ba08.png)

- 可視化はできたが、VertexのNameの出し方がよく分からなかった。

# 6. 学習メモ
- 検証時、データを間違えて入力したものを消したり、入力したデータが正しく保存されているか確認したりなど、Gremlinのいろいろな操作を覚える必要があった。
- Gremlinでのデータ操作については以下が参考になった。
    - [JanusGraphによるグラフDB入門](https://qiita.com/chromia/items/049c587c3ee0e388be5b)
        - GraphDBの環境はAmazon NeptuneではなくOSSのJanusGraphを用いているが、Gremlinの一連のデータ操作のサンプル、解説あり。
    - [Azure Cosmos DB 自習書: Azure Cosmos DB GremlinAPI編](http://download.microsoft.com/download/a/0/1/a0125fc4-2b8c-4433-925d-4e99769fe0c2/Self_Study_Azure_Cosmos_DB_Gremlin_API.pdf)
        - Azure Cosmos DBにて、Gremlinを使ってデータ操作を行うハンズオン手順書。内容が充実しておりこちらも各種データ操作が網羅されている。

# 7. 所感
- GraphDBというものに初めて触ることができちょっと楽しかった。今後業務に役立つことがあればよいが、、