Google SpreadSheetを元にグラフを描く場合
Google Chart Toolsでグラフを作れるAPIがあるんだけど、そのデータをGoogle SpreadSheetを使って描写が出来るらしい、という事でやってみたら何点かハマったのでメモ。
- sendMethodは無効にする
- QueryのURLはhttpsに => https://spreadsheets.google.com/tq?key=ファイルID&gid=0
- GeoChartは、最初のロードするパッケージに追加する => google.load("visualization", "1", {packages:["corechart", "geochart"]});
<html> <head> <meta charset="UTF-8"> <title>日本の現状::2013年1月時点</title> <script type="text/javascript" src="https://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("visualization", "1", {packages:["corechart"]}); google.setOnLoadCallback(drawChart); function drawChart() { //SpreadSheet var opts = { //sendMethod: 'xhr' #無効にする }; var query = new google.visualization.Query( 'https://spreadsheets.google.com/tq?key=0AqYMJut9ccjYdFBZeFFES1hhOVpVeTN1dm9KMUV3dXc&gid=0', opts); //URLはhttpsにする。ブラウザーで見ているURLと違うので要注意 query.setQuery('SELECT A,C,D'); query.send(handleQueryResponse); } function handleQueryResponse(response) { if (response.isError()) { alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage()); return; } var data_query = response.getDataTable(); var lineChart = new google.visualization.LineChart(document.getElementById('chart_div_age')); lineChart.draw(data_query, {title: '年齢(各歳)/男女別人口−総人口(平成23年10月1日現在)'}); } </script> </head> <body> <div id="chart_div_age"></div> </body> </html>
で間違ったカラム名を変更する方法
class Resource < ActiveRecord::Base
attr_accessible :resource_id, :type_id, :user_id
belongs_to :resource_type
この中のtype_idをbelongs_toのresource_typeのidを紐づけたいと思っていたんだけど、間違ってカラム名をつけてDBに作ってしまった。
↓本当はしたいカラム名(type_id => resource_type_id )
class Resource < ActiveRecord::Base
attr_accessible :resource_id, :resource_type_id, :user_id
belongs_to :resource_type
# $ rails g migration Renameカラム名Toテーブル名 新しいカラム名と型 $ rails g migration RenameTypeToResource resource_type:integer invoke active_record create db/migrate/20130106071025_rename_type_to_resource.rb
生成されたファイルを編集する
↓最初はこんな感じ
class RenameTypeToResource < ActiveRecord::Migration def up end def down end end
↓追記する
class RenameTypeToResource < ActiveRecord::Migration def up rename_column :resources, :type_id, :resource_type_id #:テーブル名 :古いカラム名 :新しいカラム名 end def down rename_column :resources, :resource_type_id, :type_id #:テーブル名 :新しいカラム名 :古いカラム名 end end
反映させる
$ rake db:migrate == RenameTypeToResource: migrating =========================================== -- rename_column(:resources, :type_id, :resource_type_id) -> 0.0312s == RenameTypeToResource: migrated (0.0313s) ==================================
Mac OS Xにインストールする方法
今までインストールしていない場合は
brew update brew outdated brew install erlang brew install couchdb
セカンダリー・インデックス
セカンダリー・インデックスとは、MapReduceを活用した追加のインデックス機能である
https://cloudant.com/for-developers/views/
セカンダリー・インデックスは、mapファンクションを利用するして、データをドキュメントから取り出し、reduceファンクションで、データを集約する。
これらのファンクションはJavaScriptで書けるが、専有サービスカスタマーのみしか使えないらしい
プライマリ・インデックス
プライマリ・インデックス機能
#名前の通り
ソート順
順番
#最初に実施されるソートのタイプ null false true #次の数字 1 10 4.0 #次のテキスト "a" #同じ文字であれば小文字一番、大文字二番 "A" "aa" "b" "B" "ba" "bb" #次の配列 ["a"] ["b"] #違う要素と比較されるまでソートされた要素 ["b","c"] ["b","c", "a"] ["b","d"] ["b","d", "e"] #最後にオブジェクト、キー・バリューのリストを違うリストと比較されるまでソートする {a:1} {a:2} {b:1} {b:2} {b:2, a:1} {b:2, c:2}
animaldbドキュメント内容
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs
返却値
{ "total_rows":11, "offset":0, "rows":[ {"id":"_design\/views101","key":"_design\/views101","value":{"rev":"12-dfa39d5771438be0671b9aeb9cfaf03f"}}, {"id":"aardvark","key":"aardvark","value":{"rev":"3-fe45a3e06244adbe7ba145e74e57aba5"}}, {"id":"badger","key":"badger","value":{"rev":"4-51aa94e4b0ef37271082033bba52b850"}}, {"id":"elephant","key":"elephant","value":{"rev":"3-f812228f45b5f4e496250556195372b2"}}, {"id":"giraffe","key":"giraffe","value":{"rev":"3-7665c3e66315ff40616cceef62886bd8"}}, {"id":"kookaburra","key":"kookaburra","value":{"rev":"4-6038cf35dfe1211f85484dec951142c7"}}, {"id":"lemur","key":"lemur","value":{"rev":"3-552d9dbf91fa914a07756e69b9ceaafa"}}, {"id":"llama","key":"llama","value":{"rev":"4-631ea89ca94b23a3093c1ef7dfce10e0"}}, {"id":"panda","key":"panda","value":{"rev":"2-f578490963b0bd266f6c5bbf92302977"}}, {"id":"snipe","key":"snipe","value":{"rev":"3-4b2fb3b7d6a226b13951612d6ca15a6b"}}, {"id":"zebra","key":"zebra","value":{"rev":"3-750dac460a6cc41e6999f8943b8e603e"}} ] }
検索オプション
limit : 返却値を制限する
skip: 指定の返却値を飛ばす(ページネーションなどに使うとよし)
skip
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs?skip=5
返却値
{ "total_rows":11, "offset":5, "rows":[ {"id":"kookaburra","key":"kookaburra","value":{"rev":"4-6038cf35dfe1211f85484dec951142c7"}}, {"id":"lemur","key":"lemur","value":{"rev":"3-552d9dbf91fa914a07756e69b9ceaafa"}}, {"id":"llama","key":"llama","value":{"rev":"4-631ea89ca94b23a3093c1ef7dfce10e0"}}, {"id":"panda","key":"panda","value":{"rev":"2-f578490963b0bd266f6c5bbf92302977"}}, {"id":"snipe","key":"snipe","value":{"rev":"3-4b2fb3b7d6a226b13951612d6ca15a6b"}}, {"id":"zebra","key":"zebra","value":{"rev":"3-750dac460a6cc41e6999f8943b8e603e"}} ] }
limit
$ curl https://{アカウント名}:{パスワード}@{アカウント名.cloudant.com/animaldb/_all_docs?limit=2
返却値
{ "total_rows":11, "offset":0, "rows":[ {"id":"_design\/views101","key":"_design\/views101","value":{"rev":"12-dfa39d5771438be0671b9aeb9cfaf03f"}}, {"id":"aardvark","key":"aardvark","value":{"rev":"3-fe45a3e06244adbe7ba145e74e57aba5"}} ] }
limit + skip
skip+limitでも同じ結果
&をエスケープする
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs?limit=3\&skip=3
返却値
{ "total_rows":11, "offset":0, "rows":[ {"id":"elephant","key":"elephant","value":{"rev":"3-f812228f45b5f4e496250556195372b2"}}, {"id":"giraffe","key":"giraffe","value":{"rev":"3-7665c3e66315ff40616cceef62886bd8"}}, {"id":"kookaburra","key":"kookaburra","value":{"rev":"4-6038cf35dfe1211f85484dec951142c7"}} ] }
startkey(始まりのテキスト) + endkey(終わりのテキスト)
&はエスケープが必要
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs?startkey=\"d\"\&endkey=\"giraffe\"
返却値
{ "total_rows":11, "offset":7, "rows":[ {"id":"elephant","key":"elephant","value":{"rev":"3-f812228f45b5f4e496250556195372b2"}}, {"id":"giraffe","key":"giraffe","value":{"rev":"3-7665c3e66315ff40616cceef62886bd8"}} ] }
key
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs?key=\"llama\"
返却値
{ "total_rows":11, "offset":10, "rows":[ {"id":"llama","key":"llama","value":{"rev":"4-631ea89ca94b23a3093c1ef7dfce10e0"}} ] }
一覧
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/llama
返却値
{ "_id":"llama", "_rev":"4-631ea89ca94b23a3093c1ef7dfce10e0", "min_weight":130, "max_weight":200, "min_length":1.6999999999999999556, "max_length":1.8000000000000000444, "latin_name":"Lama glama", "wiki_page":"http:\/\/en.wikipedia.org\/wiki\/Llama", "class":"mammal", "diet":"herbivore" }
include_docs
レコード全部を取得する
$ curl https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs?limit=2\&skip=3\&include_docs=true
返却値
{ "total_rows":11, "offset":3, "rows":[ {"id":"elephant","key":"elephant","value":{"rev":"3-f812228f45b5f4e496250556195372b2"}, "doc": {"_id":"elephant","_rev":"3-f812228f45b5f4e496250556195372b2","wiki_page":"http:\/\/en.wikipedia.org\/wiki\/African_elephant","min_weight":4700,"max_weight":6050,"min_length":3.2000000000000001776,"max_length":4,"class":"mammal","diet":"herbivore"}}, {"id":"giraffe","key":"giraffe","value":{"rev":"3-7665c3e66315ff40616cceef62886bd8"}, "doc": {"_id":"giraffe","_rev":"3-7665c3e66315ff40616cceef62886bd8","min_weight":830,"min_length":5,"max_weight":1600,"max_length":6,"wiki_page":"http:\/\/en.wikipedia.org\/wiki\/Giraffe","class":"mammal","diet":"herbivore"} } ] }
配列をPOSTして抽出する
$ curl -d '{"keys": ["elephant", "snipe", "panda"]}' -X POST https://{アカウント名}:{パスワード}@{アカウント名}.cloudant.com/animaldb/_all_docs -H "Content-Type:application/json"
返却値
{ "total_rows":11, "offset":0, "rows":[ {"id":"elephant","key":"elephant","value":{"rev":"3-f812228f45b5f4e496250556195372b2"}}, {"id":"snipe","key":"snipe","value":{"rev":"3-4b2fb3b7d6a226b13951612d6ca15a6b"}}, {"id":"panda","key":"panda","value":{"rev":"2-f578490963b0bd266f6c5bbf92302977"}} ] }
コマンドラインで操作
https://cloudant.com/for-developers/crud/
開発者向けドキュメントを実際にやってみる
ドキュメント内のデータ一覧を見る
$ curl https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/_all_docs
データを見てみる(id:1a80cb1cd4b37090afc0f46cdbb43ac4)
$ curl https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/1a80cb1cd4b37090afc0f46cdbb43ac4
返却値
{"_id":"1a80cb1cd4b37090afc0f46cdbb43ac4","_rev":"1-85add8f5bff234d37903d156d1285b99","season":"spring","weather":"cool with rain and sun"}
新しくデータを追加する
$ curl -d '{"season": "fall", "weather":"getting cold.."}' -X POST https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/ -H "Content-Type:application/json"
返却値
{"ok":true,"id":"ab8ec51de21e46f207c0120096bc8291","rev":"1-7cb081e4a57080cf847230ff99d089e4"}
特定のID(ab8ec51de21e46f207c0120096bc8291)のレコードを取得
$ curl -i -X HEAD https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/ab8ec51de21e46f207c0120096bc8291
返却値
E-Tagと上記rev値は同じ
HTTP/1.1 200 OK X-Couch-Request-ID: bdefc588 Server: CouchDB/1.0.2 (Erlang OTP/R14B) Etag: "1-7cb081e4a57080cf847230ff99d089e4" Date: Thu, 03 Jan 2013 07:03:49 GMT Content-Type: text/plain;charset=utf-8 Content-Length: 130 Cache-Control: must-revalidate
特定のIDのレコードを削除
$ curl -i -X DELETE https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/ab8ec51de21e46f207c0120096bc8291\?rev\=1-7cb081e4a57080cf847230ff99d089e4
返却値
HTTP/1.1 200 OK X-Couch-Request-ID: e494b619 Server: CouchDB/1.0.2 (Erlang OTP/R14B) Etag: "2-3160fe2ec8f2768c6bbe084c6c2b70f7" Date: Thu, 03 Jan 2013 07:06:53 GMT Content-Type: text/plain;charset=utf-8 Content-Length: 95 Cache-Control: must-revalidate {"ok":true,"id":"ab8ec51de21e46f207c0120096bc8291","rev":"1-7cb081e4a57080cf847230ff99d089e4"}
もしくはPUTに対して削除するフラグを付ける事で削除が可能
$ curl -d '{"_rev": "1-773b6a59e2f933059c6739df8717b44c", "_deleted":true}' -X PUT https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/ab8ec51de21e46f207c0120096bc8291
返却値
{"ok":true,"id":"ab8ec51de21e46f207c0120096bc8291","rev":"1-7cb081e4a57080cf847230ff99d089e4"}
削除されたかどうかの確認(エラー表示)
$ curl https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/ab8ec51de21e46f207c0120096bc8291
{"error":"not_found","reason":"deleted"}
認証に失敗した時
$ curl https://{アカウント名}.cloudant.com/{ドキュメント名}/ab8ec51de21e46f207c0120096bc8291
{"error":"unauthorized","reason":"_reader access is required for this request"}
一気に追加する
bulk.jsonをファイルで作成する
{"docs":[ {"name":"document-1"}, {"name":"document-2"}, {"name":"document-3"} ]}
$ curl -d @bulk.json https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/_bulk_docs -H "Content-Type:application/json"
返却値
[{"id":"32e95e4b33f172f9d03f449223054add","rev":"1-220fa148deee1e7bddb76f9dbfb9e438"},{"id":"32e95e4b33f172f9d03f449223055534","rev":"1-16afea3573a93bc9338ddb43c1ec9491"},{"id":"32e95e4b33f172f9d03f44922305563d","rev":"1-9d9ebabc84a1dd8c7b19f5b3e1feaa24"}]
ファイルの添付方法
どんなタイプのファイルでも添付可能
添付方法
- inline か standalone
inlineはデータが小さい場合によい
standaloneは、データが大きくて何度も呼び出す場合によい
mime-typeは必須。Content-Typeにて取り扱いする
インラインで追加
※inlineはデータが小さいとはいえ、コマンドラインに全部書くのは大変なので、外部ファイルにすると便利
myphoto.json
{ "_id":"myprofile", "_attachments": { "myphoto.png": { "content_type":"image\/png", "data": "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAABiElEQVQYlQXBzUvbYAAH4N/7sYQkbRpTjGuJzDK/0INYd9hB8Dhhh8EY7DDYceexm7D9CWMH6al3T571IMomePDshlWY7TZs2mLatGls35rk3fOQyNn68mgwKX79sD3a0TX6bbGAo/MzHGSe4I3npdW906yVmTrkakd8HL3btHcK03idtbBWKmLW3sZqL8LYUGBhChAT0NDV/aprAlQRbxdmY0PlsZ0x4lfzbmzOuaI1ZwIPg5BWXqzTT4TgpeWwnELZVe2S3TT+sLDfZ0EsWVRyAHQo/ew4BIaNZ7IH0W2i43fBOUPt1wXuhCBJ0QbQBi+PfPi6ju/9IfzCPDZXTNgsgaYqcINUyl4EAOB3po6kdYMfMwtkVTKiC4HBMJBM19AgkuxuLOF57j04OE3SeAAwK5mEkaxPRkjugX/tFo77URLkDVZZL6cchGa9pyU4rWtlX2M4N1SUrQx+Dw0E1ye8lF8Gv480TsbjGoiKiHVDK/DYzwdHXvz1MEMS5B4X0nqvk0dw2/wPAziepZ5qttMAAAAASUVORK5CYII=" } } }
$ curl -d @myphoto.json -X POST https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/ -H "Content-Type:application/json
返却値
"{"ok":true,"id":"myprofile","rev":"1-2b0a2ad6d1ba8a4ec811aa67ccb30db1"}
追加されたかどうか再度確認
$ curl https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/myprofile
返却値
{"_id":"myprofile","_rev":"1-2b0a2ad6d1ba8a4ec811aa67ccb30db1","_attachments":{"myphoto.png":{"content_type":"image\/png"," revpos":1,"digest":"md5-VY\/bvWh3RCG0BNObBVlMGw==","length":449,"stub":true}}}
バイナリーデータのまま追加する
画像ファイルが例えばtest.pngとすると
$ curl -H "Content-Type: image/png" -X PUT --data-binary @test.png https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/test/picture.png
返却値
{"ok":true,"id":"test","rev":"1-495147af493705593ca20bd47a57f55d"} ||< 確認する >|sh| $ curl https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/test
返却値
{"_id":"test","_rev":"1-495147af493705593ca20bd47a57f55d","_attachments":{"picture.png":{"content_type":"image\/png","revpos":1,"digest":"md5-JRYzmXDXEIGVhfkHc66+Cg==","length":12799,"stub":true}}}
追加済みのドキュメントに新しく追加する場合
movie.txtをtestドキュメントに追加(PUT)
$ curl -H "Referer: https://{アカウント名}.cloudant.com" -H "Content-Type: text/plain" -X PUT --data-binary @movie.txt https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/test/movie.txt?rev=1-495147af493705593ca20bd47a57f55d
返却値
{"ok":true,"id":"test","rev":"2-2cd8278133b20af9aa974652d08097d1"}
確認
$ curl https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/test
返却値
{ "_id":"test", "_rev":"2-2cd8278133b20af9aa974652d08097d1", "_attachments": { "movie.txt": {"content_type":"text\/plain","revpos":2,"digest":"md5-PjtfW8YfeSD1QpOxcPGClA==","length":24,"stub":true}, "picture.png": {"content_type":"image\/png","revpos":1,"digest":"md5-JRYzmXDXEIGVhfkHc66+Cg==","length":12799,"stub":true} } }
movie2.txtをtestドキュメントに追加(POST)
$ curl -H "Referer: https://{アカウント名}.cloudant.com" -H "Content-Type: multipart/form-data" -X POST -F "_attachments=@movie2.txt" -F '_rev=3-94b808999da47c1cc5c360217d8913c8' https://{ユーザー名}:{パスワード}@{アカウント名}.cloudant.com/{ドキュメント名}/test
返却値
{"ok":true,"id":"test","rev":"4-33d32c8f6e0378b3ef9b1ad27c305429"}