Neo4jでポイント交換レートを計算していれば沖縄に行けたかもしれない話

## 経緯
今年の夏、どうしても沖縄旅行に行きたいと思い、所有している20000GポイントをA○Aマイルに交換しました。交換レートは30Gポイント＝10マイルでしたので、6666マイルに交換できました。ところが、A○Aマイルで沖縄に行くには15000マイル必要で、マイルが全然足りませんでした。

Neo4jを使っていれば、、、という後悔からこの記事をかいています（フィクションです）。

| 状況       | 　　 |
|:-----------|:---------|
| 所持金      | 0円|
| Gポイント      | 20000ポイント|

## Neo4jとは？

Neo4jがなにかについては、こちらを参考にさせていただきました。
https://www.creationline.com/lab/7168
https://neo4j.com/

## 前提条件

Neo4jを簡単に動かしてみたいので、Desktop版を利用しました。

| 環境       | バージョン　　 |
|:-----------|:---------|
| Mac      | 10.15.4   |
| Neo4j      | Neo4j Desktop 1.3.3   |


## 環境構築

#### ダウンロード
こちらからダウンロード
https://neo4j.com/download-center/#desktop

#### インストール
dmgを展開してアプリケーションをApplicationディレクトリへコピーするだけ
<img width="400" alt="install.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/8386e7cb-e1e5-3998-3960-72ebf52e68c3.png">

#### プロジェクトの作成
Neo4j起動後に以下の手順でプロジェクトを作成します。
① Newをクリックする
② プロジェクト名を変更する
③ Add Database
④ Create a Local Database
<img width="713" alt="スクリーンショット 2020-08-04 14.24.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/8eb56e87-7b2e-90a9-47e1-363f87b50481.png">

⑤ DBMSNameとPasswordを設定して、Createする
<img width="400" alt="スクリーンショット 2020-08-04 14.27.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/7e59ee58-21d7-0f0d-b01b-870299df0a4d.png">

### マイル交換レートの登録

#### 交換レート

今回以下のようにマイル交換レートを作成しました。
(こちら実在するポイントプログラムとは一切関係ありません)

| From       | To　　　　 |    Cost   | 備考 |
|:-----------|:---------|:----------|:----------|
| GPoint     | AoAMile  | 0.333(10/30) | 30Gポイント＝10マイル |
| GPoint     | JoPoint  | 0.9(9000/10000) | 10000Gポイント＝9000Joポイント |
| JoPoint    | AoAMile  | 0.9(9000/10000) | 10000Joポイント＝9000マイル |


#### Neo4jへの登録

これをNeo4jに登録するにはCypherクエリというクエリ言語を利用します。

```　CypherQuery
CREATE (gpoint:Program {name: 'GPoint'}),
(jopoint:Loc {name: 'JoPoint'}),
(aoamile:Loc {name: 'AoAMile'}),
(gpoint)-[:Rate {cost: 0.9}]->(jopoint),
(gpoint)-[:Rate {cost: 0.333}]->(aoamile),
(jopoint)-[:Rate {cost: 0.9}]->(aoamile);
```
以下実際の手順です。
Databaseを起動して、「Open」をクリックするとNeo4jBrowserが立ち上がります。
<img width="706" alt="スクリーンショット 2020-08-04 14.55.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/c51c98a3-286e-cb7e-3460-86dbe49a50b1.png">

Neo4jBrowserにCypherクエリを記述して実行ボタンをクリックすると、データの登録が完了します。
<img width="1284" alt="スクリーンショット 2020-08-04 14.45.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/ab8aaa23-c9a4-8390-2b0c-c09e5a9973ba.png">

#### リレーションシップの確認

Relationship TypesのRateをクリックすると、関連するリレーションシップをグラフで確認することができます。
<img width="771" alt="スクリーンショット 2020-08-04 15.01.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/9ee7ad5e-4a46-90e9-ec97-a97b3b170933.png">

### マイル交換の計算

今回20000GポイントをA○Aに交換したかったので、以下のようなクエリを作成して実行しました。

```
MATCH route = (:Program{name:"GPoint"})-[:Rate*]-(:Program{name:"AoAMile"})
RETURN route, 20000*REDUCE(cost=1, r in RELATIONSHIPS(route) | cost*r.cost) AS Score
ORDER BY Score;
```

実行後にTextタブをクリックすると、経路(Route)とその経路で交換した時のマイル数（Score）が表示されます。

<img width="799" alt="スクリーンショット 2020-08-04 15.16.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32289/4f1bb982-ef5f-1f2e-caf4-8d98b5a748c5.png">

これは便利。

### 反省

今回Neo4jをつかってマイルへ交換ルートを計算してみたところ、Joポイントを経由していれば、１６２００マイル（15000マイル以上）に交換できたので、沖縄に行くことができたということがわかりました、悔しいです！　

### まとめ

Neo4jではノード間の経路を洗い出してくれるのがとても便利だなとおもいました。
また、Neo4jではGraph Data Science Libraryというのを追加することで、いろいろなアルゴリズムを使えるようになるようなので、こちらも試しつつNeo4jの使い所を理解していきたいとおもいます。


（参考）最短経路の算出とか便利そう
The Shortest Path algorithm
https://neo4j.com/docs/graph-data-science/current/alpha-algorithms/shortest-path/#algorithms-shortest-path-sample