あまりがっつりとSimpleDBを使い込んでいる訳ではないですが、ちょっとしたデータをつっこんでおくにはなかなか便利です。特にログを残しておきたいときは特別なミドルウェアを用意する必要がないので、サーバやミドルウェアの検証をやるときにはよく使っています。
クライアントはいくつかあるのですが、コマンドラインで使えるクライアントがamazon-simpledb-cliぐらいしか見つからなかったので、一年くらい前に自作しました。
このクライアントの売りはmysqlクライアント感覚でデータを引っ張ってこれるところで、普通にSELECTはたたけるし
ap-northeast-1> select * from employees limit 3; --- - ["100000", {first_name: Hiroyasu, hire_date: "1991-07-02", birth_date: "1956-01-11", last_name: Emden}] - ["100001", {first_name: Jasminko, hire_date: "1994-12-25", birth_date: "1953-02-07", last_name: Antonakopoulos}] - ["100002", {first_name: Claudi, hire_date: "1988-02-20", birth_date: "1957-03-04", last_name: Kolinko}] # 3 rows in set
複数行のUPDATEも(一応)出来るし
ap-northeast-1> update employees set age = '35'; # 100 rows changed
と、結構便利に作っていたのですが、集計処理が出来ないのが難点でした。
一応、SQLのパーサを書いたのですが、SELECT文のパースをSimpleDBに丸投げだったりとなかなかヤクザなパーサです。集計系の構文(MAX、SUM、GROUP BY)をマジでパースしようと思うとかなり骨なので、集計処理の実装については棚上げ状態でした。
もちろん標準出力に出してRubyでこねくり回せばどうとでも出来るのですがめんどくさい!
どうしたものかと悶々としていたところ『だいたいRubyのメソッド使えばいくらでも集計できるじゃん?構文のきれいさにこだわらなければどうとでもなるんじゃね?』と思い至ったのが以下の構文です。
ap-northeast-1> select * from employees limit 3 | map {|i| i.hire_date }; --- - "1991-07-02" - "1994-12-25" - "1988-02-20" # 3 rows in set
『|』以降の文字列をRubyに丸投げというひどい代物になりました。
とはいえRubyをほぼそのまま使えるのはなかなか強力です。
first_nameだけを抽出することも出来ますし
ap-northeast-1> select * from employees limit 3 | first_name; --- - Hiroyasu - Jasminko - Claudi # 3 rows in set
first_nameが『C』で始まる人は何月生まれが多いかとかも集計できますし
ap-northeast-1> select * from employees | select {|i| i.first_name =~ /^C/ }.map {|i| Time.parse(i.birth_date).mon }.inject({}) {|r, i| r[i] ||= 0 \; r[i] += 1\; r }.sort_by {|k,v| k } ; --- - [1, 1] - [3, 1] - [5, 1] - [8, 2] - [10, 1] - [12, 3] # 6 rows in set
itemNameを数値に変換して平均を出すとか訳のわからないことも出来ます。
ap-northeast-1> select * from employees | itemname.to_f.avg; --- 91941.4
というわけで見た目はクソですが意外と便利ですので、興味のある方はどうぞご利用ください。