MongoDBとmetabaseでjsonファイルを見やすくしたい 後編

この記事は<a href="https://qiita.com/advent-calendar/2018/nifty">ニフティグループ Advent Calendar 2018</a> 4日目の記事です。
3日目は@machinanetteさんの<a href="https://qiita.com/machinanette/items/7a3c16728e6015ba81ef">サンタのおもちゃをmicro:bitで制御する</a>でした。

<a href="https://qiita.com/motaHack/items/eaea969eda56f2046e19">2日目の記事</a>に引き続いてMongoDBとmetabaseでjsonの操作をしてみて、使えそうなこと/微妙だと思ったことについてまとめます。

#### 概要
- クエリビルダーを使う
- 複雑なネストのJSONを扱う
- 所感

# クエリビルダーを使ってテーブルやグラフを作成する
metabaseでは、DBの値から自動的に適当なグラフや図などが生成されますが、
必ずしも目的にあったものが生成されるわけではありません。
自分が作成したい図やテーブルを取得するには、テーブルを選択して、クエリビルダーもしくはネイティブクエリを用いる必要があります。


テーブルを確認するにはヘッダー上部の「質問する」（すごい訳ですね）をクリックして、「カスタム」もしくは「ネイティブクエリ」を選択します。

<img width="1376" alt="スクリーンショット 2018-12-04 12.23.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/208347/aa267d26-8bc4-f937-73eb-d9a2c8885c03.png">
絞り込みやグルーピングなどの簡単な操作であればクエリを書かなくてもパネル上からぽちぽちできます。とても楽ですね。

JSONデータはこのように格納されていますが、ネストしているデータも、表示や絞り込み・グルーピングにも使用することができます。
<img width="636" alt="スクリーンショット 2018-12-04 12.16.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/208347/57470992-9f41-d2c5-e8a4-7cd46b73b4c6.png">

<img width="650" alt="スクリーンショット 2018-12-04 12.29.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/208347/029b108f-3a9e-9423-fdc3-89fc3f700d71.png">




このレベルなら、パースしてRDBに入れてそこからグラフを作る・・・よりも圧倒的に早いです。
<img width="1205" alt="スクリーンショット 2018-12-04 12.35.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/208347/4af23f02-621d-f451-4272-89375e45e39b.png">


# 複雑にネストしているJSONの中身を取り出す
ただ、シンプルにネストしているだけのものなら取り出しは容易なのですが、valueが配列になっていたりするとクエリビルダーだけでは難しいため、ネイティブクエリを記述する必要があります。

たとえば、元データが以下のようなJSONであった場合、`weapon_list`のvalueは配列になっており、しかもさらにネストしてしまっています。
このようなデータ構造の場合、metabaseは配列の中身まで取り出そうとはしてくれません。文字列として配列そのままのデータが表示されるだけです。

``` raw.json
"my_result": {
  "dead_count": 4,
  "weapon_list": [
      {
          "weapon": {
              "name": "つよい剣",
              "id": "240"
          },
          "id": "240"
      }
      {
          "id": "40",
          "weapon": {
              "name": "よわい銃",
              "id": "40"
          }
      }
  ]
}
```

その場合はネイティブクエリに以下のようなクエリを書くと、配列の中身を取り出すことができます。
metabaseのMongoDBのクエリはJSON形式で記述します。

Mongo公式ドキュメントをみると`"$my_result.weapon_list.weapon.name.1"`のように取り出せるようなのですが、metabaseから発行するクエリだとうまく変換されないのか、エラーが出てしまいます。

その代わり、<a href="https://docs.mongodb.com/manual/reference/operator/projection/slice/">$slice</a>を使えば、配列の位置を指定して取り出すことができます。

``` nested_json_query
[
	{
		"$project": {
			"weapon1":  {"$slice": ["$my_result.weapon_list.weapon.name",0,1]},
			"weapon2":  {"$slice": ["$my_result.weapon_list.weapon.name",1,1]}
		}
	}
]
```

上記raw.jsonに対してこのクエリを実行した結果は以下のようになります。

|weapon1|weaopn2|
|:------|:------|
|["つよい剣"]|["よわい銃"]|
(そのまま文字列で取り出す方法がわからなかった・・・誰か教えてください。）

# 所感
#### MongoDB+metabaseが使える場面
ネストが必要以上に深くないJSONを扱う場合、パースするコストがかなり減るので、JSON形式のデータを取り出して可視化したーい！という状況が発生した場合めちゃくちゃ楽だと感じました。
metabaseからクエリ結果をCSVやExcelファイルとして取り出すこともできるので、データの加工手段として利用するのはアリかなあと思います。

#### 微妙だと思ったところ
先ほど書いたように、ネストした中に配列が入っていてその中でネストしていて・・・みたいなデータが入っていると操作がちょっと面倒です。
個人的にはmongoのクエリがSQLのそれとは全く異なっているため学習コストがかなり高いと感じており、上記のような複雑なネストのJSONを敢えて扱う必要性は感じなかったです。

とはいえ、普通にプログラムでパースして、そこから値を何かしらのDBにinsertして・・・といった手間は減らせるように感じており、Mongoのクエリが使いこなせるなら、何かしらコードを書くよりはこっちのほうが早いと思います。


<hr>
5日目は　@machinanetteさんの　<a href="https://qiita.com/machinanette/items/b0dcbff47cd00924b7e9">AWS Lambdaでheadless-chromeを動かしてRedashのグラフをキャプチャしてSlackに投稿する</a> です！