kintone のデータを Redash で可視化する

目次

はじめに

kintone に蓄積した売上データや案件情報などを使ってデータを分析する場合、kintone のグラフ機能では物足りないから、ファイルに出力して Excel を使っているという方もいらっしゃると思います。

しかし、データ分析するたびにファイル出力しなければなりません。
また一度に出力できるファイルサイズは 100MB までなので、大量のデータを出力するときは分割出力する必要があります。

そんなとき、データを可視化できるツールと kintone が連携できたら便利かと思います。
この記事では、オープンソースのデータ可視化ツール「 Redash (External link) 」と kintone を連携し、kintone で管理しているデータを Redash で可視化する方法を説明します。

kintone と Redash の連携

Redash と MySQL などの一般的なデータソースと連携させるには、あらかじめ提供されているコネクタを利用します。
コネクタが用意されていないデータソースに対しても、所定の書式の JSON を返す Web サーブレットを「 Querying URLs (External link) 」で呼び出すことで、外部のアプリケーションからのデータ取得ができます。

kintone には Redash が用意したコネクタがないので、この「Querying URLs」というしくみを使ってデータを取得します。

今回、 Web サーブレットは Google Apps Script を使って構築しています。

Redash でアプリ ID を指定してクエリを実行すると、Redash から Google Apps Script へリクエストが送信されます。
Google Apps Script は kintone REST API を実行してレコード情報を取得し、Redash 用の書式に整形して Redash へ返します。

事前に必要なもの

  • Redash 環境
    この記事では、v6.0.0 で確認しています。
  • Google アカウント
  • kintone アカウント
information

kintone アカウントを持っていない方は、 1 年間無料の「 開発者ライセンス」を利用してください。

開発の流れ

  1. Google Apps Script によるプログラム作成
  2. Redash へのデータソース追加とクエリ作成
  3. おまけ:Query Results を使ったフィルターリング

Google Apps Script によるプログラム作成

設定方法

  1. Google Apps Script (External link) から、[Start Script]ボタンをクリックします。

  2. 後述のプログラム を貼り付けます。

  3. [ファイル]メニュー >[保存]ボタンをクリックして保存します。
    適当なプロジェクト名(今回は、「kintone-redash-quering-url」)を入力し、[OK]ボタンをクリックします。

  4. [ファイル]メニュー >[プロジェクトのプロパティ]を選択します。
    [プロジェクトのプロパティダイアログ]が表示されるので、[スクリプトのプロパティ]タブを選択します。

  5. [行を追加]リンクをクリックし、次のプロパティを入力します。

    3 つすべて入力したら、[保存]ボタンをクリックします。

    プロパティ
    KINTONE_SUBDOMAIN 「xxxxx.cybozu.com」
    kintone のサブドメインを入力します。
    KINTONE_USER_ID kintone にログインするユーザー名を入力します。
    対象アプリに閲覧権限をもつユーザーとしてください。
    KINTONE_USER_PASSWORD kintone にログインするパスワードを入力します。
  6. [公開]メニュー >[Web アプリケーションとして導入]を選択します。

  7. [Web アプリケーションとして導入]ダイアログが表示されます。
    次のように入力し、[導入]ボタンをクリックします。

    項目
    プロジェクトバージョン 「New」を選択します。(初期値)
    次のユーザーとしてアプリケーションを実行 「自分」を選択します。(初期値)
    アプリケーションにアクセスできるユーザー 「全員(匿名ユーザーを含む)」を選択します。
  8. [現在の Web アプリケーションの URL]欄に表示される URL をメモしておいてください。
    [OK]を押して、ダイアログを閉じます。

    caution
    警告

    この URL にアクセスすると kintone アプリで保存しているレコード情報を取得できます。  
    URL が外部へ漏れないようにしてください。
    

  9. スクリプトのページは閉じてもかまいません。

    information

    URL 発行後に、修正したソースコードを反映する場合は、プロジェクトバージョンを上げる必要があります。  
    4. からの手順で、再度[Web アプリケーションとして導入]ダイアログを表示します。  
    [プロジェクトバージョン]項目で「New」を選択し[更新]ボタンをクリックします。
    

プログラム

以下のプログラムを、Google Apps Script に貼り付けてください。

caution
警告

レコード一括取得時にその結果として 1 万を超える可能性がある場合は、運用・適用中のプログラムのご確認および修正対応の検討をお願いします。
詳細は offset の制限値を考慮した kintone のレコード一括取得について の「レコード ID を利用する方法」を確認ください。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * Redash visualization for kintone sample program
 * Copyright (c) 2019 Cybozu
 *
 * Licensed under the MIT License
*/

/**
 * スクリプトプロパティに保存した kintone の接続情報を取得する.
 */
const userId = PropertiesService.getScriptProperties().getProperty('KINTONE_USER_ID');
const password = PropertiesService.getScriptProperties().getProperty('KINTONE_USER_PASSWORD');
const subdomain = PropertiesService.getScriptProperties().getProperty('KINTONE_SUBDOMAIN');
/**
 * Redash からのリクエストを受け付ける.
 * @param {Object} e  リクエストパラメータ
 * @return {Object} Redash に返すレスポンス
 */
function doGet(e) {
  const appId = e.parameter.appId;
  if (!appId || appId <= 0) {
    return makeResponse({columns: [], rows: []});
  }
  const records = getKintoneRecords(appId);
  return makeResponse(convertContent4Redash(records));
}
/**
 * kintone REST API を実行し全件レコードを取得する.
 * @param {string} appId アプリID
 * @return {Array.<Object>} レコードオブジェクトの配列
 */
function getKintoneRecords(appId) {
  const token = Utilities.base64Encode(userId + ':' + password);
  const baseurl = 'https://' + subdomain + '/k/v1/records.json?app=' + appId + '&query=order by $id asc';
  const options = {
    method: 'GET',
    headers: {'X-Cybozu-Authorization': token}
  };
  return fetch();
  const offset_range = 100;
  // kintone レコードを取得する
  function fetch(opt_offset, opt_records) {
    const offset = opt_offset || 0;
    let records = opt_records || [];
    const url = baseurl + ' offset ' + parseInt(offset, 10);
    const resp = UrlFetchApp.fetch(url, options);
    const json = JSON.parse(resp.getContentText());
    const respRecord = json.records;
    records = records.concat(respRecord);
    if (respRecord.length === 100) {
      // 残りのレコードを取得する
      return fetch(offset + 100, records);
    }
    return records;
  }
}
/**
 * kintone レコードの値一覧を取得する.
 * @param {string} appId アプリID
 * @return {Array} kintone レコードの値を詰めた配列
 */
function getRecordValues(records) {
  const rows = [];
  for (let i = 0; i < records.length; i++) {
    const record = records[i];
    const row = {};
    for (const key in record) {
      if (Object.prototype.hasOwnProperty.call(record, key)) {
        if (key === '更新者' || key === '作成者') {
          // 「更新者」と「作成者」はプロパティの構造が異なる
          row[key] = record[key].value.code;
        } else {
          row[key] = record[key].value;
        }
      }
    }
    rows.push(row);
  }
  return rows;
}
/**
 * kintone のフィールド情報一覧を取得する.
 * @param {Object} record レコード
 * @return {Array} kintone フィールド情報一覧
 */
function getFieldInfo(record) {
  const columns = [];
  for (const key in record) {
    if (Object.prototype.hasOwnProperty.call(record, key)) {
      const column = {};
      column.name = key;
      column.friendly_name = key;
      if (key === '更新者' || key === '作成者') {
        // 「更新者」と「作成者」はフィールドタイプがないので、強制的に文字列型にする。
        column.type = 'string';
      } else {
        column.type = judgeFieldType(record[key].type);
      }
      columns.push(column);
    }
  }
  return columns;
}
/**
 * kintone のフィールドタイプを Redash のフィールドタイプに変換する.
 * @param {string} kintoneType kintone のフィールドタイプ
 * @return {string} Redash のフィールドタイプ
 */
function judgeFieldType(kintoneType) {
  let redashType = '';
  switch (kintoneType) {
    case 'DATETIME':
      redashType = 'datetime';
      break;
    case 'NUMBER':
      redashType = 'float';
      break;
    default:
      redashType = 'string';
      break;
  }
  return redashType;
}
/**
 * Redash へのレスポンスを作る.
 * @param {Object} content Redash で表示できる形式のデータ
 * @return {Object} Redash へのレスポンス
 */
function makeResponse(content) {
  return ContentService.createTextOutput(JSON.stringify(content)).setMimeType(ContentService.MimeType.JSON);
}
/**
 * Redash で表示できる形式のデータに変換する
 * @param {Array} records kintone のレコード一覧
 * @return {Object} Redash で表示できる形式のデータ
 */
function convertContent4Redash(records) {
  return {columns: getFieldInfo(records[0]), rows: getRecordValues(records)};
}

Redash へのデータソース追加とクエリ作成

  1. Redash を開きます。

  2. 画面右上のユーザー名を選択し、[Data Sources]を選択します。

  3. [+ New Data Source]ボタンをクリックします。

  4. データソースの一覧から[Url]を選択します。

  5. データソースを追加します。
    次のように入力し、[Save]ボタンをクリックします。

    項目
    Name データソースの名前です。
    今回は「kintone」としました。
    URL Base Path 「https://script.google.com/macros/s/」と入力します。
    HTTP Basic Auth Username 空欄
    HTTP Basic Auth Password 空欄
  6. 画面上部の[Create]ボタンをクリックし、[Query]を選択します。

  7. 新規 Query 画面が表示されます。
    次のように入力し、[Save]ボタンをクリックします。

    項目
    左側のドロップダウン 先ほど追加した「Url」データソースを指定します。
    今回は「kintone」を選びます。
    右側のクエリ画面 「『Google Apps Script によるプログラム作成』の手順 8. でメモしたURLの https://script.google.com/macros/s/以降」
    + 「?appId=」 + 「連携したいアプリID」を指定します。

    たとえば、
    • URL:https://script.google.com/macros/s/xxxxxxx/exec
    • 連携したいアプリID:1
    の場合、入力する値は以下になります。
    xxxxxxx/exec?appId=1
  8. [Execute]ボタンを押下し、データを取得します。
    Google Apps Script にリクエストが送られ、返却された kintone のデータが表示されます。

これで Redash で kintone のデータを閲覧できるようになりました。

あとは「Visualization」機能を使ってグラフを作成したり、グラフを元にダッシュボードを作ってみましょう。
Redash の使い方については、 Redash Help (External link) を参照してください。
Redash では、こんな 2 軸グラフを作ることもできます。

Query Results を使ったフィルターリング

概要

「URL」データソースで実行される Google Apps Script のプログラムは、kintone のレコード全件を取得します。
そのため、条件で絞ったレコード抽出ができません。

グラフを作る場合、期間が今年などある程度フィルターリングしたデータを使いたいという場面が多いと思います。
その場合、「 Query Results (External link) 」(要 v3.0.0 以上)というデータソースを使うと、「Url」データソースで取得したデータの絞り込みができます。

Redash では、クエリの実行結果をと Redash の内部データベースに保存しています。
「Query Results」は内部データベースで保存された実行結果に問い合わせするデータソースです。

手順

  1. Redash を開きます。

  2. 画面右上のユーザー名を選択し、[Data Sources]を選択します。

  3. [+ New Data Source]ボタンをクリックします。

  4. データソースの一覧から[Query Results]を選択します。

  5. データソースを追加します。
    次のように入力し、[Save]ボタンをクリックします。

    項目
    Name データソースの名前です。
    今回は「query-results」としました。
  6. 画面上部の[Create]ボタンをクリックし、[Query]を選択します。

  7. 新規 Query 画面が表示されます。
    次のように入力し、[Save]ボタンをクリックし、保存します。
    [Execute]ボタンをクリックすると、SQL の WHERE 句で指定した条件に一致するデータだけを取得できるようになりました。

    項目
    左側のドロップダウン 先ほど追加した「Url」データソースを指定します。
    今回は「query-results」を選びます。
    右側のクエリ画面 SQL クエリを記述します。
    このとき、FROM 句に「query_クエリID>」を指定することで、内部 DB に保存されたそのクエリの実行結果を取得できます。

    クエリID が 1の場合は「query_1」になります。

    たとえば、「日時」フィールドが 2019 年 03 月 01 日以降になるデータに絞り込み、かつ「日時」の降順に並び替える場合は、次のような SQL になります。
    SELECT * FROM query_1 a
    WHERE a.日時 >= '2019-03-01 00:00:00'
    ORDER BY a.日時 DESC
information

クエリ ID は、「Redash へのデータソース追加とクエリ作成」手順 7. で作成したクエリの URL で確認できます。
http://サーバのURL/queries/数字 の数字部分がクエリ ID です。

おまけ: Query Parameters (External link) 機能を使うと、SQL に条件をべた書きすることなく絞り込み条件を指定できます。

ダッシュボードからも絞り込み条件を指定できます。

おわりに

Redash はオープンソースで利用できる便利なデータ可視化ツールです。

今回紹介した「Url」データソースを使えば、kintone のデータを Redash に連携できます。
kintone に蓄積したさまざまなデータを Redash が提供する柔軟なグラフやダッシュボードで可視化できると、データ分析作業の効率化につながるかもしれません。

information

この Tips は、2019 年 8 月版 kintone で動作を確認しています。