Goldstine研究所

mosuke5's tech blog

ブログ移転しました。5秒後にリダイレクトします。

D3.js、DBからのデータ連携方法の検討

最近D3.jsを使う機会があり、DBのデータを読み込ませる方法についていくつか検討した。
例えば以下の状況を考える。
【やりたいこと】
「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

csvtest.erb

<%= @csv %>

こうすることで"http://*****/csv"にアクセスするとcsvファイルとしてダウンロードできる状態になる。
条件指定をしてデータをダウンロードできるようにしたい場合はGETでパラメータ指定できるようにすれば良いと思う。
SinatraCSVファイルを生成するところのコードがナンセンスだと思っているので、もっといい方法があるはず…)

また、今回はcsvにしているがjsonなどの他の形式でも同様のことがいえる。

これをD3.js側で以下のように読み込ませる。

d3.csv("/csv", function(error, data) {

    (中略)

}

d3.jsのcsvを読み込ませる関数の引数にURLを指定してあげればそれで終了。

(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) {

    (中略)

}