時間がない人へのまとめ

この記事では、Dockerを使いOSS版Redashの環境を整えRedash APIを使用してみます。 APIの紹介では、クエリのキャッシュされた結果を引っ張ってくることや、新たにクエリを実行してその結果を取得する方法などを記載しています。

目次

そもそもRedashってなに?

Redashは、OSSのBIツールの一つです。

どういったことができるか大雑把に言うと、以下のような感じです。

  • DBなどに接続してRedash上でクエリを書いて結果を取得する
  • クエリの実行をスケジュールして定期実行できる
  • 結果をグラフや表として表示できる
  • 複数クエリの結果をダッシュボードにまとめてわかりやすく表示できる

app.redash.ioでホストされているRedashサービスは2021年11月に提供を終了したみたいです。 なので、使用する場合はOSS版を自前のホストに立ててください。

前準備

今回はDockerを使ってOSS版Redashの環境を立ててAPIを試していきたいと思います。

docker環境を立てる

さっそく、OSS版Redashを使えるようにしていきましょう! 適当なディレクトリを作成してその中に以下のようなdocker-compose.ymlを作ります。 (Re:Dashのインストール(Docker)のものを使わせていただきました。)

version: '2'
x-redash-service: &redash-service
  image: redash/redash:latest
  depends_on:
    - postgres
    - redis
  env_file: redash.env
  restart: always
services:
  server:
    <<: *redash-service
    command: server
    ports:
      - "5000:5000"
    environment:
      REDASH_WEB_WORKERS: 4
  scheduler:
    <<: *redash-service
    command: scheduler
    environment:
      QUEUES: "celery"
      WORKERS_COUNT: 1
  scheduled_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "scheduled_queries,schemas"
      WORKERS_COUNT: 1
  adhoc_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "queries"
      WORKERS_COUNT: 2
  redis:
    image: redis:latest
    restart: always
  postgres:
    image: postgres:latest
    env_file: redash.env
    restart: always
    ports:
      - "5436:5432"
  nginx:
    image: redash/nginx:latest
    ports:
      - "80:80"
    depends_on:
      - server
    links:
      - server:redash
    restart: always

そして同じディレクトリに以下のようなredash.envを作成しましょう

REDASH_HOST=http://localhost/redash
PYTHONUNBUFFERED=0
REDASH_LOG_LEVEL=INFO
REDASH_REDIS_URL=redis://redis:6379/0
POSTGRES_DB= redash
POSTGRES_USER= redash
POSTGRES_PASSWORD= hogehoge
REDASH_COOKIE_SECRET=redash-selfhosted
REDASH_SECRET_KEY=redash-selfhosted
REDASH_DATABASE_URL=postgresql://redash:hogehoge@postgres/postgres

これで以下のようにコマンドを叩くとredashが使えるようになります。

$ docker-compose run --rm server create_db
$ docker-compose up -d

問題なくコンテナが立ち上がったら、http://localhost/redash/にアクセスしてみましょう。

そうすると、以下のような画面が表示されると思います。

redashのセットアップ画面

適当に入力してsetupボタンをクリックします。

以下のようなRedashのトップページが表示されればセットアップ完了です! redashのトップページ

テストデータをDBに流す

次に、DBにデータを流していこうと思います まず、サンプルDBのデータを以下のページからDLしてきましょう。

DLリンクは下の方にあります。 redashのトップページ DLしてきたものを解凍して、でてきたtarファイルを先程のdocker-compose.ymlを置いているディレクトリに配置しましょう。 そして以下のコマンドを打って、DBにデータを流しましょう!

ホスト側にPostgreSQLが入っている前提です。

pg_restore -h localhost -p 5436 -U redash -d redash ./dvdrental.tar

データがDBにリストアされればOKです。

Redashのデータソース設定

続いて、redashのデータソース登録をやっていきます。 先程サンプルデータを流したDBをredashで使えるようにしましょう。 トップページの右上にあるsettingsをクリックします。

redashのsettingsの位置 クリックすると以下のような管理画面になると思います。 redashの管理画面 この「New Data Sources」をクリックします。 すると以下のような画面になるので、テキストボックスに`postgresql`と入力するとフィルターされて選択肢が出てくるので`PostgrSQL`をクリックします。 redashのデータソース選択画面 続いて、接続の設定が出てくるので以下のように記入し終了。 redashのデータソース詳細入力画面
Host: postgres # docker-compose.ymlで設定しているpostgrsqlコンテナのホスト名
User: redash   # redash.envで設定したユーザー名
Password: hogehoge  # redash.envで設定したパスワード
Database Name: redash # redash.envで設定したDB

これで、準備したPostgrSQLのDBをRedashで使えるようになりました。

簡単なクエリを実行してみる

それでは、さっそく簡単なクエリを実行してみましょう。 Redashのヘッダーにある「Create」から「Query」を選択しましょう。 すると以下のような画面になるので、クエリを書いて「Execute」してみます。 redashのquery画面 以下のように、結果が帰ってきましたね。 redashでqueryの実行

APIをためす

ようやく本題のRedash APIをためしていきたいとおもいます。

公式のAPIドキュメントの場所です。

クエリの結果を取得する

まず、クエリーページから「Show API key」をクリックします。 redashでshow api keyの場所 そうすると以下のように、API Keyと例としてリクエストURLが書かれています。 redashクエリのapi key さっそく、このリクエストURLを使ってクエリの結果を取ってみます。 今回はCurlでいきましょう。

$  curl get "http://localhost/api/queries/1/results.json?api_key=apikey" |jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: get
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 21924  100 21924    0     0   382k      0 --:--:-- --:--:-- --:--:--  382k
{
  "query_result": {
    "retrieved_at": "2021-12-19T04:42:10.577Z",
    "query_hash": "db936c708c77683dd372f1ada72b8777",
    "query": "select *\nfrom actor;",
    "runtime": 0.015136957168579102,
    "data": {
      "rows": [
        {
          "first_name": "Penelope",
          "last_name": "Guiness",
          "actor_id": 1,
          "last_update": "2013-05-26T14:47:57.620"
        },
        {
          "first_name": "Nick",
          "last_name": "Wahlberg",
          "actor_id": 2,
          "last_update": "2013-05-26T14:47:57.620"
        },
....

しっかりと結果が取れましたね。

パラメーター付SQLの結果を取得する。

続いてパラメーター付きのものを試してみたいと思います。 まず、以下のようにパラメーターを使用するようにRedashのクエリを変更します。 redashでパラメータ付きのクエリを書いている様子 クエリ

select *
from actor
where actor_id = {{ id }};

これで一回Redash上で結果を見てみると、actor_idが1の結果のみ帰ってきていますね。

それでは、Curlを使って結果を取得してみます。

$ curl -X POST -H "Content-Type: application/json" -d '{"parameters":{"id": 1}}' "http://localhost/api/queries/1/results?api_key=token"|jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   511  100   487  100    24  16233    800 --:--:-- --:--:-- --:--:-- 17033
{
  "query_result": {
    "retrieved_at": "2021-12-19T04:59:35.423Z",
    "data": {
      "rows": [
        {
          "first_name": "Penelope",
          "last_name": "Guiness",
          "actor_id": 1,
          "last_update": "2013-05-26T14:47:57.620"
        }
      ],
      "columns": [
        {
          "friendly_name": "actor_id",
          "type": "integer",
          "name": "actor_id"
        },
        {
          "friendly_name": "first_name",
          "type": null,
          "name": "first_name"
        },
        {
          "friendly_name": "last_name",
          "type": null,
          "name": "last_name"
        },
        {
          "friendly_name": "last_update",
          "type": "datetime",
          "name": "last_update"
        }
      ]
    }
  }
}

こちらも無事結果が帰ってきましたね。

もし以下のようにエラーが帰ってくる場合は、redashのパラメーターのテキストボックスの上にある設定⚙を押して見てください。

{
  "job": {
    "status": 4,
    "error": "This query contains potentially unsafe parameters and cannot be executed on a shared dashboard or an embedded visualization."
  }
}

そこで表示されるTypeの型にCurlのPOSTするパラメーターを合わせてください。

キャッシュされていないクエリの結果を取得する

先程までのものは、一度Redash上で実行されたものでキャッシュが残っているパターンを取得していました。

それでは、Redash上でキャッシュの残っていないクエリの結果を取得してみたいと思います。

以下のコマンドを叩きます。

$ curl -X POST -H "Content-Type: application/json" -d '{"parameters":{"id": 2}}' "http://localhost/api/queries/1/results?api_key=token"|jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   147  100   123  100    24   3000    585 --:--:-- --:--:-- --:--:--  3585
{
  "job": {
    "status": 1,
    "error": "",
    "id": "92d7f7eb-1491-4cfa-810d-f4fa992a6076",
    "query_result_id": null,
    "updated_at": 0
  }
}

上記のように、クエリの結果ではなくjobの情報が帰ってきたと思います。

jobの状態を取得する

ここから、クエリの結果を取るには帰ってきたジョブが終了している必要があります。 なので、少し経って以下のコマンドを実行してみましょう。

エンドポイント:/api/jobs/<job_id>

このとき、使用するAPI_keyは先程までのものではなく、ユーザーに紐付いたAPI_keyである必要があります。 Redashの画面右上にあるメニューから「Edit Profile」をクリックし、下の方にあるAPI Keyを使用しましょう。 redashのユーザーAPI Key

もし、今までのKeyを使用していると以下のようになると思います

hara% curl "http://localhost/api/jobs/92d7f7eb-1491-4cfa-810d-f4fa992a6076?api_key=key" |jq
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    71  100    71    0     0   5916      0 --:--:-- --:--:-- --:--:--  5916
{
  "message": "Couldn't find resource. Please login and try again."
}

$ curl "http://localhost/api/jobs/先程帰ってきたjobのid?api_key=user-token"|jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   120  100   120    0     0  12000      0 --:--:-- --:--:-- --:--:-- 12000
{
  "job": {
    "status": 3,
    "error": "",
    "id": "92d7f7eb-1491-4cfa-810d-f4fa992a6076",
    "query_result_id": 7,
    "updated_at": 0
  }
}

帰ってきたステータスの意味は以下のとおりです。

  • 1 == PENDING(実行待ち)
  • 2 ==開始(実行中)
  • 3 ==成功
  • 4 ==失敗
  • 5 ==キャンセル

https://redash.io/help/user-guide/integrations-and-api/api

jobからクエリの結果を取得する

上記例だと、成功しているのでクエリの結果を取得してみましょう。 エンドポイント /api/query_results/<query_result_id>

$ curl "http://localhost/api/query_results/7?api_key=key"|jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   651  100   651    0     0  28304      0 --:--:-- --:--:-- --:--:-- 29590
{
  "query_result": {
    "retrieved_at": "2021-12-19T05:10:38.654Z",
    "query_hash": "04bb6c6ca4e4f15ef3941d86296b18a4",
    "query": "select *\nfrom actor\nwhere actor_id = 2;",
    "runtime": 0.009379863739013672,
    "data": {
      "rows": [
        {
          "first_name": "Nick",
          "last_name": "Wahlberg",
          "actor_id": 2,
          "last_update": "2013-05-26T14:47:57.620"
        }
      ],
      "columns": [
        {
          "friendly_name": "actor_id",
          "type": "integer",
          "name": "actor_id"
        },
        {
          "friendly_name": "first_name",
          "type": null,
          "name": "first_name"
        },
        {
          "friendly_name": "last_name",
          "type": null,
          "name": "last_name"
        },
        {
          "friendly_name": "last_update",
          "type": "datetime",
          "name": "last_update"
        }
      ]
    },
    "id": 7,
    "data_source_id": 1
  }
}

しっかり結果が帰ってきましたね。

注意しなければいけないのは、このリクエストに使用するAPI Keyもユーザーに紐づくものではないといけないようです。 queryに対するもの以外はすべてユーザーに紐づくAPI keyの方ってことですね。

キャッシュされたものを使いたくない場合

キャッシュされたデータではなく、新しくじっこうしたクエリの結果を取得したい場合以下のようにmax_ageパラメータで指定してあげるといいみたいです。

 curl -X POST -H "Content-Type: application/json" -d '{"parameters":{"id": 1},"max_age":0}' "http://localhost/api/queries/1/results?api_key=key" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   159  100   123  100    36   3967   1161 --:--:-- --:--:-- --:--:--  5129
{
  "job": {
    "status": 1,
    "error": "",
    "id": "4ad82496-f1b0-4b2d-a72b-347af8c3a0b1",
    "query_result_id": null,
    "updated_at": 0
  }
}

この場合でも、帰ってくるのはjobの情報なので先程のようにjobからクエリの結果を引っ張って来てくださいね。

おわりに

今回Redashの環境構築から、APIを使用してデータを引っ張ってくるところまでをおこないました。 ここからGASをつかって毎日情報をSlackに送ることなどいろいろなことができるとおもいます。 Redashのダッシュボード機能も便利だと思うので使っていきたいですね。

参考にさせていただいたもの