Re:Dashでpythonデータソースを使ってクエリ結果をごにょごにょしたい

# はじめに

Re:Dashは画面を作りたくないエンジニアにとって、
クエリを組むだけでそれっぽい画面やグラフ化なんかもできてとっても便利。
でもクエリを作るだけじゃなくて、もう少しデータをごにょごにょしたいことありませんか？
もっというと、異なるデータソースのクエリ結果を結合させたいって思う事ありませんか？？

Re:Dashには「pythonデータソース」なるものが用意されていて、
ちょっと設定をすればpythonでデータをごにょごにょできるようになっちゃいます。
これがとっても便利だったので、今回は設定の仕方から主要な機能・使い方の紹介をさせて頂きます。

# pythonデータソースを使用できるようにする

デフォルトではpythonデータソースは使用できないようになっています。
下記設定を追加すればデータソースからpythonが指定できるようになります。

## /opt/redash/.env の修正

```/opt/redash/.env 
export REDASH_ADDITIONAL_QUERY_RUNNERS=redash.query_runner.python
```

## 設定を反映させる

>sudo supervisorctl restart redash_server


## 新しいデータソースの追加

`Data Sources` から `+ New Data Sources`をクリック。
`Type`に`Python`が選択できるようになっているので選択し、`Name`に適当な名前を入れて`save`すると
クエリ作成時にPythonデータソースが選択できるようになります。

![redash_datasource.png](https://qiita-image-store.s3.amazonaws.com/0/142453/0d70290e-c7a1-8fcd-0c9b-c9de5e5ada7a.png)

![redash_datasource_select.png](https://qiita-image-store.s3.amazonaws.com/0/142453/9b027999-7438-f7b7-2958-f4d1f592d579.png)


# ごにょごにょしたいデータを用意する

予めごにょごにょする前のデータを準備しておきます。
詳しくはこの記事では割愛させて頂きますが、定期実行を設定して必要なデータのみを必要なタイミングで取得・キャッシュさせておきましょう。

今回は「異なるデータソース間の数値を合算させて表示させる」という目的を想定して準備してみます。
簡単なクエリ結果を下記のように2つ用意。

## データ①

作成したクエリのクエリIDをメモしておく。今回このクエリは `クエリID=76` とする

![redash_data1.png](https://qiita-image-store.s3.amazonaws.com/0/142453/2fe8677d-86d7-1a92-8552-56dba73ea195.png)


## データ②

作成したクエリのクエリIDをメモしておく。今回このクエリは `クエリID=77` とする

![redash_data2.png](https://qiita-image-store.s3.amazonaws.com/0/142453/5f319e46-ccd2-cc4e-3221-0276e3524b23.png)



# データをごにょごにょしてみる

どんな想定かはさておきｗ
2つの異なるデータソースから取得したクエリ結果から
同じIDのCOUNTを合算させて表示させるようごにょごにょしてみます。

## ざっくり書いてみたコード全容

APIを使用してクエリ結果を取得し、pythonで行いたい処理を書いたらAPIで結果をセットしてあげればOK
※APIについては下記参照
※下記は適当なコードですがforやif文など普通に使えるよ！という例で。。
※get_query_resultで取得したクエリ結果は `rows['rows'][行数][カラム名]=値` の形で取得されます。

```
# 指定したクエリIDのクエリ結果を取得する
queryResults1 = get_query_result(76)
queryResults2 = get_query_result(77)

result = {}
for rows1 in queryResults1['rows']:
    for rows2 in queryResults2['rows']:
        if rows1['id'] == rows2['id']:
            # 行データを追加する
            add_result_row(result, {
                'id'    :rows1['id'],
                'count' :rows1['count'] + rows2['count']
            })
            break

# カラム名を指定する
add_result_column(result, 'id', '', 'integer')
add_result_column(result, 'count', '', 'integer')
```

![redash_result.png](https://qiita-image-store.s3.amazonaws.com/0/142453/1c61173e-c8c4-532b-aaa5-f8b6b15a798c.png)


## 主要なAPI

|      API      |      内容      |       例       |
|---------------|----------------|---------------|
|get_query_result(queryId)|指定したクエリIDのクエリ結果を取得する|get_query_result(1)|
|add_result_row(result, values)|行データを追加する|add_result_row(result, {'id':rows['id'],'count':rows['count']})|
|add_result_column(result, columnName, friendlyName, columnType)|カラム名を指定する|add_result_column(result, 'id', '', 'integer')|
|execute_query(dataSourceName, query)|queryをdataSourceName上で実行し結果を取得する|execute_query('testDataSource', 'select * FROM test WHERE id = 1')|

詳しくは[実際のRe:dash内部のソース](https://github.com/getredash/redash/blob/aa5d14ed02a888ccb00ed9e718185ea690acb2f5/redash/query_runner/python.py)を読んでみてください

## モジュールを使いたい場合

Data Sourceのsetting画面からモジュールを追加することで使用できるようになります。
複数追加したい場合はカンマ区切りで追加します。
saveをしたらコード上でimportしてあげるだけで使用できるようになります。

![redash_module.png](https://qiita-image-store.s3.amazonaws.com/0/142453/4f94ee48-944f-4dc7-953c-229a0eb91ad8.png)

# さいごに

普通にpythonでコードが書けてしまうので、少し複雑な処理もさせることができ
利用の幅が広がるのではないかと思います。なにより画面を作らなくていいという時点で素晴らしい。。
是非利用してみてください！

# 関連記事

[Re:Dashのアップグレードをしたい](http://qiita.com/axm-aoki/items/41e92722400e17513b78)
[Re:Dashで便利な小技まとめ](http://qiita.com/axm-aoki/items/23af956d333e4fe9115f
)