こんにちは。もーすけです。
Web上でのデータのグラフ化にどんな方法をとっていますか?いろいろ検討してD3.jsが非常に良さそうだったので使ってみています。今回、データベースにあるデータを読み込ませる方法についていくつか検討してみました。
例えば以下の状況を考えます。
やりたいこと
「DBに格納されているデータを使って、D3.jsで折れ線グラフを描く」
DBの構造
すごく単純に下記のテーブル構造とします。
カラム名 | データ型 |
---|---|
date | datetime |
value | int |
※また、下記ではSinatra上で行っているが、他の言語でも同じ考え方が可能です。
(1) 簡単なAPIのようなものを利用する
先に結論から書くと、今まで次の(2)(3)のようなやりかたをやっていたのだけれど、 これが一番複雑にならずに良いと思いました。
Sinatra側で/csvにアクセスするとcsvファイルをダウンロードできるようにします。
#Sinatra側
get '/csv' do
content_type 'application/csv'
attachment 'download.csv'
#DBからデータ取得(Activerecord利用)
@data = Model.all()
#出力するCSVデータの変数。csvヘッダーを先につけている。
@csv = "date,value\n"
#DBのデータをCSVの形にして格納
@data.each do |d|
@csv += d.date.to_s + "," + d.value.to_s + "\n"
end
#csvtest.erbというビューに出力
erb :csvtest, :layout => false
end
こうすることでhttp://*****/csv
にアクセスするとcsvファイルとしてダウンロードできる状態になります。
条件指定をしてデータをダウンロードできるようにしたい場合はGETでパラメータ指定できるようにすれば良いと思います。
また、今回はcsvにしているがjsonなどの他の形式でも同様のことがいえる。もっと複雑な構造のデータを扱うのであればjsonを利用すべきです。
このエンドポイントを使って、D3.js側で以下のように読み込ませる。 d3.jsのcsvを読み込ませる関数の引数にURLを指定してあげればそれで終了。
d3.csv("/csv", function(error, data) {
(中略)
}
(2) javascriptコードの中でRuby変数を展開させる
d3.jsのdatasetの中でRuby変数を展開させる。ビューにJavascriptを書いているので、ビューの中で変数展開するのと同じ要領。 しかし、jsコードにRubyコードも交じるのはアンチパターンと言えよう。
var dataset = [
<% @data.each do |d| %>
{date:<%= d.date%>, value:<%= d.value %>},
<% end %>
];
(3) CSVファイルをおいておく
こちらはリアルタイムな更新でなれけばこれはこれでありかもしれない。 publicのフォルダに予めcsvファイルを設置しておき、以下のようにd3.jsで読み込ませる。
d3.csv("test.csv", function(error, data) {
(中略)
}