Neo4j ETL CLIを試してみた

## 前提
### ETLとは
* Extract/Transform/Load
* 今の現場に入って初めて聞いたけど、EAIとは少し違う様子
    * [ETLとは？データを使って企業の生産性を劇的に向上！【図説付】](https://boxil.jp/mag/a2415/#2415-9)

### Neo4j ETLとは
* Neo4j Enterprise版で提供されている機能の一つ（Dockerなら現在無料で使用できる）
* 通常はUIとセットで提供され、画面上からRDB→グラフDBへのマッピングを設定することができる。
* こんな感じ ![mapping_sample.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274988/1a38194f-a35e-c258-bdac-00dd1e05dbfe.jpeg)
    * [How-To: Neo4j ETL Tool](https://neo4j.com/developer/neo4j-etl/)

## なぜCLI？

ちょうど業務で使用するかもとなって技術検証の結果を記録することにした。

逆になんでUI版がメインなんだろう。
他のシステムと連携するときにNeo4j APPがないと適用できませんとか、業務系のシステムだとかなりハードル高いと思ったけど、どうやらエンタープライズ版の機能故に情報が絞られている様子。

とりあえずGithubの最新版がV1.3.1なので、それをもともとあったDockerファイルに適用。
https://github.com/neo4j-contrib/neo4j-etl/releases

Postgresはもう一つのコンテナで立ててあるので、container_name指定して実行すればいけるはず。
まずはマッピングのJSON出力。

```
export NEO4J_HOME=/path/to/neo4j-enterprise-3.4.0

mkdir -p /tmp/northwind

$NEO4J_HOME/bin/neo4j-etl generate-metadata-mapping \
  --rdbms:url jdbc:postgresql://[container_name]/postgres \
  --rdbms:user northwind --rdbms:password northwind \
  --rdbms:schema northwind --output-mapping-file /tmp/northwind/mapping.json
```

注意はDB名まででやめておくこと。マニュアルにはユーザ名とパスワード書いてあるけどDB名まで。
下で指定してるのになんでここでもと思ったら案の定エラーになりました。

最後のコマンドを実行するとエラーが発生。
調べると現象的にはこれが似ている。

https://github.com/neo4j-contrib/neo4j-etl/issues/49

中でV1.4.2を試すように言われているのだが、1.3.1までしかないじゃないかと思ったらCLIを使用する人はほとんどいないらしい。

Twitterで問い合わせたら確認してくれるらしいのでしばらく待ち。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/neo4j?ref_src=twsrc%5Etfw">@neo4j</a> I want to use Neo4j ETL CLI on Docker with container networking. Why does released only until V1.3.1 ? V1.4.1 for desktop seems to have resolved the problem to failed to connect other container.<a href="https://t.co/IKKCDmqA1e">https://t.co/IKKCDmqA1e</a></p>&mdash; たくや (@ta_o_zi) <a href="https://twitter.com/ta_o_zi/status/1224506630617718784?ref_src=twsrc%5Etfw">February 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

別環境に同一サーバ上でPostgresとNeo4jが共存しているところがあるので、そっちで試したら普通に疎通確認取れた。。

## 本題

長くなってしまったけど本題。

### Neo4j ETL CLIについて
* 大きく分けて2機能
    * RDBのテーブル仕様からマッピングJSONファイルを出力する
    * マッピングファイルからGDBへデータ転送を行う
* Configファイルでパラメータ指定したりもできるが、汎用的に作るならパラメータ生成の方がコスト低いかなと思ったのであまり触れない。

### generate-metadata-mapping
* マッピングJSONを生成するためのコマンド
* 対象DBへのアクセス情報と生成するテーブルを指定できる

実際に使用するケースを想定して実践的なオプションを追加。

```
$NEO4J_HOME/bin/neo4j-etl generate-metadata-mapping \
  --rdbms:url jdbc:oracle:thin:@localhost:49161:XE \
  --rdbms:user northwind --rdbms:password northwind \
  --rdbms:schema northwind --output-mapping-file /tmp/northwind/mapping.json
  --exclusion-mode-tables include --tables -l hoge_table,huga_table
```

これでhoge_tableとhuga_tableのみからJSONファイルを生成することができる
テーブルの指定方法がマニュアルからうまく読み取れずハマった。
英語力がないせいかもしれないから勉強しなければ。

#### JSONの仕様
* これはどこみても見つからなかった。

* こちらもNeo4jの中の人の記事を見つけたので聞いてみました。
    * 英語力のなさを痛感したけれどなんとか伝わった様子で返信がないのとNeo4jの編集長なる人物からもいいねがきたので、おそらく存在していない。
    * <blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/JMHReif?ref_src=twsrc%5Etfw">@JMHReif</a> This article is easy for me to understand neo4j etl.<br><br>Where is the specification of the JSON file I quoted?<br>I&#39;ve been looking for it since yesterday... <a href="https://t.co/PUBNvY1Kfe">https://t.co/PUBNvY1Kfe</a></p>&mdash; たくや (@ta_o_zi) <a href="https://twitter.com/ta_o_zi/status/1224865769432834048?ref_src=twsrc%5Etfw">February 5, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

* 確かにNode、リレーションごとに取得するSQLとマッピング情報が書いてあるだけだから直感的でわかりやすいのだけど、細かいところがわからず生成させては適用してみるの繰り返しだった。

### export
* マッピングJSONを読み込んでNeo4jへデータを格納する。
* generate-metadata-mappingのオプションも使えばノンストップでNeo4jへデータ投入できるらしい。

```
$NEO4J_HOME/bin/neo4j-etl export  \
  --rdbms:url jdbc:oracle:thin:@localhost:49161:XE \
  --rdbms:user northwind --rdbms :password northwind \
  --rdbms:schema northwind \
  --using bulk:neo4j-import \
  --import-tool $NEO4J_HOME/bin  \
  --csv-directory /tmp/northwind \
  --mapping-file /tmp/northwind/mapping.json \
  --neo4j:user --neo4j:password
  --options-file /tmp/northwind/options.json \
  --quote '"' --force
```

* ~~正常に完了すれば100万件位のデータが8Gメモリのマシンで30秒弱くらいで入ります。~~
* ↑ノードだけなら速いけれど、リレーションを含めたら途端に重くなった
    * CSVの生成過程をみていたけど、どうやらStartId/EndIdで指定したテーブルを実際にみてチェックをしているからと思う。

## 課題
* 少し遅い？
    * もっとパフォーマンス出したければKafka（Streams）使った方が良いよという公式のお言葉をどこかでみた気がするのでKafkaもそのうち記事書く。
    * 
* コンテナ間通信ができない。
    * localhostになぜかアクセスされる。多分固定。CLI版更新しないかな。
* libにおいたneo4j-etl.jarのせいでNeo4jが起動しない
    * これ、Neo4jはよくあります。libの読み込みエラーはSkipしてほしいけどダメみたい。
    * 今回のケースだと、起動するのにETL Libraryを一旦退避させるという荒技。
    * 本体のソースも読みたいから調べてみるつもり。
* SELECT結果のマッピング方法調べ中。
    * JOINとかしたSQLだとうまく行かなかったのでそこは明日チャレンジ。

以上です。

最近どんどんこの界隈詳しくなっていくので、Neo4j勉強したい方や、自社のデータをグラフ化してみたいという要望あれば是非連絡ください！