【neo4j】グラフデータベースを触ってみる

## はじめに
先日、Neo4j社が無料で使えるグラフデータベースのマネージドサービス「Neo4j AuraDB Free」を発表し、いい機会と思いちょっと触ってみたのでそれについて書いてみました。
[Introducing Neo4j AuraDB Free](https://neo4j.com/press-releases/announcing-neo4j-auradb-free/#:~:text=%E2%80%93%20November%203%2C%202021%20%E2%80%93%20Neo4j,card%20required%20to%20get%20started.)

グラフデータベース自体初めて触ったので内容は初歩的なものですが、まだ触ったことないけど興味あるという方の参考になれば嬉しいです。

## グラフデータベースとは
グラフDBはNoSQLの一種で、グラフ構造を持つデータベースです。グラフは以下3つの要素で定義されます。

- ノード：人や物などを表すエンティティ
- エッジ：二つのノード間のつながり、関係性を表すリレーションシップ
- プロパティ：ノード、エッジの属性情報

何はともあれ使ってみると視覚的にもわかりやすいものとなっているので以降で使い方を説明していきます。

## Neo4j AuraDB Freeのセットアップ
まず[neo4jの公式ページ](https://neo4j.com/cloud/aura/)の「Start Free」からアカウントを作成します。
![スクリーンショット 2021-12-06 0.48.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/fbebd853-37b8-fcd9-7b12-45d66ebd33d2.png)

アカウント作成できたら早速「Create a Database」を選択し、DBを作成していきます。
![スクリーンショット 2021-12-05 0.22.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/dc19f15f-53a8-7d51-350b-185e642c5971.png)

今回はお試しなのでDatabase Typeは「AuraDB Free」を選択します。
![スクリーンショット 2021-12-05 0.22.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/13c94668-82f5-0e54-74df-daba7d742ba2.png)

Database Nameは「sample」、GCP Regionは「Singapore」、Starting datasetは空のものとし、いざ「Create Database」を選択してDBを作成してみます。
![スクリーンショット 2021-12-05 0.23.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/4ee57a2a-8d5b-c768-0e99-474985130e00.png)

作成後にDBのCredential情報が表示されます。DBに接続するときに使用しますのでメモしておき、「Continue」で次に行きます。
![スクリーンショット 2021-12-06 1.03.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/4e95c06f-5acd-20d2-33cf-faa80c32f507.png)

マイページに今作成したDBが表示されますのでこれで一旦DB作成は完了となります。
![スクリーンショット 2021-12-05 0.28.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/4abdf6db-e08f-7f90-ff23-f351b6ab2975.png)

## 触ってみる
Neo4j AuraDBはブラウザで接続してクエリを実行できる機能を提供しているのでそれを使ってちょっと触っていきます。
使い方はマイページのDBの右側にある「Open with」を選択するとGUIツールが選択できます。今回は「Neo4j Browser」を使います。
![スクリーンショット 2021-12-06 1.12.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/0ec03a77-acfb-85d9-a1b8-3ed8628f8b25.png)

「Neo4j Browser」を選択すると接続画面が表示されますので、セットアップ時に生成されたCredential情報を入力し、「Connect」で接続します。
![スクリーンショット 2021-12-05 0.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/a90923ad-8f94-0510-b038-ddfa3ed133d5.png)

これでDB上でクエリを実行できるようになりました。neo4jでグラフDBを操作するには「Cypher」というクエリ言語を用います。
またRDBのようにテーブルという概念がないため、いきなりノードを追加していく感じになります。
ここでは詳細の説明は割愛しますが、Cypherの詳しい構文など知りたい方は[neo4j公式のDEVELOPER GUIDES](https://neo4j.com/developer/get-started/)などをご覧いただければと思います。

それでは早速ノードを追加してみます。まずは以下を実行してPersonというノードを追加してみます。

```cypher
CREATE (a:Person { name: "熊谷", age: 25, hobby: "ゴルフ"})
return a
```
![スクリーンショット 2021-12-05 1.16.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/5a938e81-e38b-4134-ea3d-38a7c9b47f89.png)

これでノードが追加されました。
簡単に説明すると、`CREATE (a:Person { name: "熊谷", age: 25, hobby: "ゴルフ"})`でノードを作成します。
グラフDBにはテーブルという概念は存在しないのですが、同じ構造のノードに対してラベルをつけることができ、この文の`Person`がそれにあたります。そして`Person`の前にある`a`はクエリ名となります。RDBでいう`as`の後につける任意の名前に近いかと思います。
その後の`return a`は戻り値指定のようなもので`a`とつけたものを返すとなるので、ここでいうと作成したノードを結果として表示するための文となります。

それではもう一つノードを追加して二つのノードをリレーションさせてみたいと思います。
まずPartyというノードを追加します。

```cypher
CREATE (a:Party { date: "2021-12-11", name: "歓迎会", location: "新橋" })
```

次に二つのノードをつなぎます。

```cypher
MATCH (a:Person{name:"熊谷"}), (b:Party{name:"歓迎会"}) CREATE (a)-[r:参加した]->(b)
RETURN a,r,b
```

これで以下のように「熊谷さんが歓迎会に参加した」というノードとリレーションが作成されます。
![スクリーンショット 2021-12-05 1.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/cf62a004-444f-a3f6-ca2e-00aa4bf23531.png)

またここで構文の説明をしておくと、`MATCH (a:Person{name:"熊谷"}), (b:Party{name:"歓迎会"})`はRDBでいう`SELECT`です。そして`CREATE (a)-[r:参加した]->(b)`でMATCHで取得したaとbのノード間にリレーションを作成しています。

ここまでで基本的なことができたので、もう少しノードとリレーションを追加してシチュエーションに合わせた検索をしてみます。

### Person
熊谷、吉本、清水、今泉、岩森、伊藤、横山

### Party
歓迎会、栄養会、キックオフ会、クリスマスパーティー

### リレーション
いろんな人がいろんなパーティーに参加

### シチュエーション
熊谷さんが高熱なったので接触した人を調べたい

### 参加状況
![スクリーンショット 2021-12-05 2.54.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/20fef116-c32e-6b10-8b6b-cee30ecf1edc.png)

#### ▼ 濃厚接触者の検索
濃厚接触者となる人は熊谷さんとパーティで同席した人になるので以下のように取得できます。

```cypher
MATCH (origin:Person{name:"熊谷"})-[:`参加した`]->(a)<-[:`参加した`]-(close_contact:Person)
return close_contact
```

結果は以下の２名になります。
![スクリーンショット 2021-12-06 2.45.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/28f5361d-e334-b2fb-aace-c7f014510dfc.png)


#### ▼ 二次接触者の検索
二次接触者は熊谷さんとパーティで同席した人と別のパーティで同席した人になるので以下のように取得できます。

```cypher
MATCH (origin:Person{name:"熊谷"})-[:`参加した`]->(a)<-[:`参加した`]-(close_contact:Person),
(close_contact)-[:`参加した`]->(b)<-[:`参加した`]-(second_close_contact:Person)
WHERE NOT (origin)-[:`参加した`]->()<-[:`参加した`]-(second_close_contact) AND origin <> second_close_contact
RETURN second_close_contact
```

結果は以下の3名になります。
![スクリーンショット 2021-12-06 2.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144550/0497756a-f5ef-8ecf-b59d-d716ec3811d3.png)

以上のように関係を辿って接触者を特定することができました。

## おわりに
入門的な内容でしたが、グラフデータベースとはなんぞや？ということが少しでも理解いただける内容となっていれば幸いです。
グラフデータベース自体がRDBだとJOINだらけになって遅くなるような問題を解決するために作られたという話なので、身近で利用シーンが出ることに備えて今後も追っていきたいと思います。
それでは。