D3.js とデータベースデータで動的な Web アプリを構築



D3.js は、SVG、HTML5、CSS といった広く実装されている標準技術を活用して、Web ブラウザ上で動的かつインタラクティブなデータビジュアライゼーションを実現する JavaScript ライブラリです。CData API Server は軽量な Web アプリケーションであり、カスタム開発なしでデータから API を作成・公開できます。この記事では、CData API Server をセットアップして SQLite データベース用の REST API を作成し、データベースデータにリアルタイムでアクセスできるシンプルな D3.js Web アプリケーションを構築する方法を解説します。D3.js アプリは、データベースデータに基づいてシンプルな棒グラフを動的に生成します。記事ではコードの大部分を説明していますが、完全なソースコードを確認して機能をテストするには、サンプルプロジェクトと SQLite データベースをダウンロードしてください。

API Server のセットアップ

まだお済みでない場合は、CData API Server をダウンロードしてください。API Server をインストールしたら、以下の手順でアプリケーションを実行し、データへの接続を設定します(この記事では付属のサンプルデータベースを使用)。次に、D3 アプリでアクセスしたいテーブル用の REST API を作成するための設定を行います。

CORS の有効化

D3 Web アプリと API Server が異なるドメインにある場合、D3 ライブラリはクロスドメインリクエストを生成します。つまり、D3 Web アプリからクエリするサーバーでは CORS(クロスオリジンリソースシェアリング)を有効にする必要があります。CORS は、設定ページの Server タブで有効にできます:

  1. トグルボタンをクリックして、CORS(クロスオリジンリソースシェアリング)を有効にします。
  2. トグルボタンをクリックして '*' なしですべてのドメインを許可するか、接続を許可するドメインを Access-Control-Allow-Origin に指定します。
  3. Access-Control-Allow-Methods を "GET,PUT,POST,OPTIONS" に設定します。
  4. Access-Control-Allow-Headers を "authorization" に設定します。
  5. Save Changes をクリックします。

データベース接続の設定

以下の手順で、API Server からデータベースへの接続を設定します:

  1. まず、Connections ページに移動します。
  2. Add Connection をクリックし、SQLite 接続を検索して選択します。
  3. 表示されるダイアログで接続を設定します:接続に名前を付け、Data Source フィールドに SQLite データベースのフルパスを入力します(付属のデータベースは SQLite Tutorial の chinook.db です)。
  4. 接続を設定したら、 Save & Test をクリックして、SQLite データベースへの接続が成功したことを確認します。

ユーザーの設定

次に、API Server 経由でデータベースデータにアクセスするためのユーザーを作成します。Users ページでユーザーを追加・設定できます。このシンプルな D3 データ表示アプリでは、読み取り専用アクセス権を持つユーザーを作成します: Add User をクリックし、Role を Query に設定、Username を入力し、PrivilegesGET を選択して、Add User をクリックします。

ユーザーの Authtoken が生成されます。各ユーザーの Authtoken やその他の情報は Users ページで確認できます:

テーブルへのアクセス

ユーザーを作成したら、データベーステーブルへのアクセスを有効にします:

  1. まず、API ページに移動し、 Add Table をクリックします。
  2. アクセスしたい接続を選択し、Next をクリックします。
  3. 接続を選択した状態で、各テーブル名を選択し、Confirm をクリックしてテーブルを有効にします。

REST API のサンプル URL

データベースへの接続を設定し、ユーザーを作成し、API Server にリソースを追加したら、OData プロトコルに基づいた REST API が利用可能になります。API Server の API ページから、API の API エンドポイントを表示・コピーできます:

標準の OData フィードと同様に、返されるフィールドを制限したい場合は、クエリに $select パラメータを追加できます。また、$filter$orderby$skip$count$top などの標準 URL パラメータも使用できます。JavaScript で使用する場合は、デフォルトで JSON データを返さない URL の末尾に @json パラメータを追加できます。

D3.js アプリケーションの構築

API Server のセットアップが完了したら、サンプル D3.js アプリを構築していきましょう。以下の手順では、.zip ファイルに含まれる Web アプリのソースコードを解説し、関連するセクションについて説明します。

index.html


このファイルには、D3.js Web アプリのすべてのソースが含まれています。スクリプト参照、スタイル、Web アプリの基本レイアウトを作成する HTML、そして D3.js ライブラリを使用してアプリを動的に構築し API Server からのデータに基づいて棒グラフを生成する JavaScript コードが含まれます。

<body>

この HTML 要素には、Web アプリの基本的な HTML コードが含まれています:テーブルを選択するドロップダウンメニュー、棒グラフのドメインとレンジ用のドロップダウンメニュー、そして棒グラフ自体を含む SVG です。各要素の属性と値は、D3 JavaScript ライブラリを使用して動的に定義されます。

body 要素には、Web アプリを動的に構築するための JavaScript を含む script 要素も含まれています。

<script>

JavaScript の最初の数行では、棒グラフ用の SVG を設定し、他のグローバル変数を初期化します。初期設定の後、テーブルとカラムのドロップダウンメニューを設定する関数が呼び出されます。

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 120, left: 60},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleBand().rangeRound([0, width]).padding(0.2),
    y = d3.scaleLinear().rangeRound([height, 0]);

var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var userName = "read_only";
var authToken = "********************";

var selectedTable = "";
var selectedDomain = "";
var selectedRange = "";

populateTableOptions();

populateDomainAndRangeOptions();

populateTableOptions

この関数は、D3.js ライブラリを使用して API Server に対して HTTP GET を実行し、テーブルの一覧を取得します。また、テーブルを選択するドロップダウンメニューのオプションを設定し、選択が変更されたときの動作を定義し、Web アプリ用に選択されたテーブルを設定し、特定のテーブルデータを取得するボタンを設定します。

function populateTableOptions() {
    d3.json("http://localhost:8080/api.rsc/")
        .header("Authorization", "Basic " + btoa(userName + ":" + authToken))
        .get(function(error, data) {
            if (error) throw error;

            var values = data.value;

            d3.select("select.tableSelect")
                .on('change', function() {
                    clearChart();
                    selectedTable = d3.select("select.tableSelect").property("value");
                    populateDomainAndRangeOptions(selectedTable);
                    d3.select("button.dataButton")
                        .text(function(d) {
                            return "Get [" + selectedTable + "] Data";
                        });
                })
                .selectAll('option')
                .data(values)
                .enter().append("option")
                .text(function(d) {
                    return d.name;
                });

            selectedTable = d3.select("select.tableSelect").property("value");

            d3.select("button.dataButton")
                .on('click', function() {
                    clearChart();
                    buildChart();
                })
                .text(function(d) {
                    return "Get [" + selectedTable + "] Data";
                });
        });
}

populateDomainAndRangeOptions

この関数は、選択されたテーブルに基づいて API Server から利用可能なカラムの一覧を取得し、populateColumnOptions 関数を呼び出してドメインとレンジのドロップダウンメニューにそれらのカラムを設定し、選択されたドメインとレンジを設定します。

function populateDomainAndRangeOptions() {
    d3.json("http://localhost:8080/api.rsc/" + selectedTable + "/$metadata?@json")
        .header("Authorization", "Basic " + btoa(userName+":"+authToken))
        .get(function(error, data) {
            if (error) throw error;
            populateColumnOptions("domain", data);
            populateColumnOptions("range", data);
            selectedDomain = d3.select("select.domainSelect").property("value");
            selectedRange = d3.select("select.rangeSelect").property("value");
        });
}

populateColumnOptions

この関数は、API Server のカラムリクエストから取得した生データを使用して、ドメインとレンジのドロップダウンメニューを設定し、選択が変更されたときの両方のドロップダウンメニューの動作を定義します。

fucntion populateColumnOptions(data) {
    var values = data.items[0]["odata:cname"];
    var axes = ["domain", "range"];

    axes.forEach(function(axis) {

        d3.select("select." + axis + "Select")
            .selectAll("*")
            .remove();

        d3.select("select." + axis + "Select")
            .on('change', function() {
                clearChart();
                if (axis == "domain")
                    selectedDomain = d3.select("select." + axis + "Select").property("value");
                else if (axis == "range")
                    selectedRange = d3.select("select." + axis + "Select").property("value");
            })
            .selectAll('option')
            .data(values)
            .enter().append("option")
            .text(function(d) {
                return d;
            });
    });
}

buildChart

この関数は棒グラフを構築するためのすべての処理を行います。選択されたドメインカラムの値で X 軸を埋め、選択されたレンジカラムの値でバーの高さと Y 軸を設定します。この関数は、API Server に対して HTTP GET リクエストを実行し、選択されたテーブルから選択されたカラムのみを要求することでこれらの値を取得します。

function buildChart() {
    d3.json("http://localhost:8080/api.rsc/" + selectedTable + "/?$select=" + selectedDomain + "," + selectedRange)
        .header("Authorization", "Basic " + btoa(userName + ":" + authToken))
        .get(function(error, data) {
            if (error) throw error;

            var values = data.value;

            x.domain(values.map(function(d) { return d[selectedDomain].toString(); }));
            y.domain([0, d3.max(values, function(d) { return d[selectedRange]; })]);

            g.append("g")
                .attr("class", "axis axis--x")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x));

            g.selectAll("g.tick")
                .attr("text-anchor", "end")
                .selectAll("text")
                .attr("transform", "rotate(-45)");

            g.append("g")
                .attr("class", "axis axis--y")
                .call(d3.axisLeft(y))
                .append("text")
                .attr("transform", "rotate(-90)")
                .attr("y", 6)
                .attr("dy", "0.71em")
                .attr("text-anchor", "end")
                .text("Value");

            g.selectAll(".bar")
                .data(values)
                .enter().append("rect")
                .attr("class", "bar")
                .attr("x", function(d) { return x(d[selectedDomain].toString()); })
                .attr("y", function(d) { return y(d[selectedRange]); })
                .attr("width", x.bandwidth())
                .attr("height", function(d) { return height - y(d[selectedRange]); })
                .attr("title", function(d) { return d[selectedRange]; })
                .text(function(d) { return d[selectedRange]; });
        });

}

clearChart

この関数は、SVG からすべての棒グラフ要素を削除するだけのシンプルな関数で、必要なときにいつでも新しいグラフを作成できるようにします。

function clearChart() {
    d3.select("svg")
        .select("g")
        .selectAll("*")
        .remove();
}

D3.js Web アプリの設定

データへの接続を設定し、Web アプリのソースコードを確認したら、Web アプリを起動する準備が整いました。マシンに Node.js がインストールされている必要があり、Web アプリと API Server 間のリクエストとレスポンスを適切に管理するために Web サーバーをインストールまたは実行する必要があります。

Web アプリのセットアップ

次の手順で Web アプリをセットアップし、package.json ファイルを作成・設定します。

  1. まだお済みでない場合は、Node.js をマシンにインストールしてください。
  2. コマンドラインで、ソースファイルがあるディレクトリに移動します:
    cd ./apiserver-d3
  3. ディレクトリに移動したら、package.json ファイルを対話形式で作成します:

    npm init
  4. プロンプトに従って、パッケージの名前、バージョン、説明などを設定します。これはサンプルプロジェクトなので、test command、git repository、keywords、author、license にはデフォルト値または空白を使用しても問題ありません。package.json が作成されたら、ファイルを編集して "scripts" 要素内の "test": "echo \"Error: no test specified\" && exit 1""start": "node node_modules/http-server/bin/http-server -p 30001 -o" に置き換えます。これにより、npm start で Web アプリを実行したときに軽量 HTTP サーバーが起動します。

軽量 HTTP サーバーのインストール

package.json ファイルを作成したら、必要に応じて Web アプリを実行するための軽量 HTTP サーバーをインストールできます:

npm install http-server --save

Web アプリの実行

package.json ファイルを作成し、必要なモジュールをインストールしたら、Web アプリを実行する準備が整いました。コマンドラインインターフェースで Web アプリのディレクトリに移動し、以下のコマンドを実行するだけです:

npm start

Web アプリが起動すると、テーブル、ドメイン、レンジ用のドロップダウンメニューと、グラフを作成するためのボタンが表示されます。テーブルとカラムの一覧は API Server から取得され、API Server の設定時にリソースとして追加したすべてのテーブルが含まれます。

テーブルとカラムを選択したら、Get [table] Data ボタンをクリックして、API Server 経由でデータベースからデータを取得できます。棒グラフは、選択したテーブルと、ドメインとレンジに選択したカラムに基づいて作成されます。

以下は、曲のトラックに含まれるバイト数をトラックタイトル別に表示したサンプル棒グラフです。

無料トライアルと詳細情報

動的な Web ページでデータベースデータに接続する手順を完了しました。API Server をダウンロードして、SQLite、MySQL、SQL Server、Oracle、PostgreSQL などのオンプレミスおよびクラウドベースのデータベースのライブデータを使用した動的な Web ページの構築を始めましょう!いつものように、ワールドクラスのサポートチームがご質問にお答えします。