ラベル H2 Database engine の投稿を表示しています。 すべての投稿を表示
ラベル H2 Database engine の投稿を表示しています。 すべての投稿を表示

2012年10月10日水曜日

マーケットモニタリングアプリの開発(5): スクレイピングTips

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
可能な限り「どのような操作をするか」ではなく「(操作に依存せず)どんな結果を得たいか」をプログラミングしていたい、宣言型プログラミング大好き、たなけんです。
本エントリでは、スクレイピング(Webリソース(e.g. htmlページ)から必要な情報を抽出すること)のTipsを記載します。

FireBug

プログラマであれば、真っ先に思い浮かべるのはFirebugだと思います。御多分に漏れず、私もまずはFirebugでhtmlの構造を(タグを掘り下げながら)解析して行きます。
Firebugの便利な点としては、htmlエディタ(画面下部)上にマウスカーソルを移動させると、対応するhtmlイメージ(画面上部)がハイライトされる点が挙げられます。
スクレイピングしたい部分を画面上部に表示しておき、該当するタグを探って行くことでおおよそ必要な要素を特定することができます。

YQL Console

私がスクレイピングする際に重宝しているもうひとつのツールがYQL Consoleです。
YQLとはYahoo!が開発した『Webリソースに適用出来るSQL』のようなものです。
Firebugで取得したい要素を特定し、enliveのselectorを記述したものの、意図していない結果が返される事が多々あります。なぜならenliveのselectorは該当する要素を全て含んだ結果を返しますが、私が欲しいのはその中の一部だからです。
このような場合、selectorで返される要素を俯瞰し、必要な要素と必要でない要素の違いを見分けるために、私はYQL Consoleを利用します。
具体的には結果をtreeで表示し、必要な要素と必要でない要素を比較します。
理論的にはEmacs上でも結果の比較は可能なのですが、YQL Consoleは階層を可視化して
くれるので、直感的に要素の違いを見分けることができます。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間15分)


マーケットモニタリングアプリの開発(4): ランキングの更新

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
バイト先のレストランからビールを一箱もらってご機嫌の、たなけんです。
本エントリでは、モニタリング対象のランキングの更新について記載します。

ランキング更新の必要性と処理の流れ

取引が成立した理由を探る為には、出品時のランキングだけではなく、実際に売買が成立した時点のランキングも必要だと考えています。(出品後に人気が出て売れたのかどうかを検証するため)
そこで、モニタリング対象の本については、たとえそれが1200位(一括で取得できる上限)以下であっても、日々のランキングを取得する必要があります。
そこで、下記の流れで、ランキング情報を管理します。

  1. 本日のランキング上位1200を取得
  2. 前日までの累積されたISBN(ISBNマスタに登録済み)と比較
  3. 本日のランキング上位1200とISBNマスタとの差分を取得
  4. ISBNマスタに存在せず、本日のランキング上位1200に入ったものは、ISBNマスタに追加
  5. 本日のランキング上位1200に存在しないが、ISBNマスタに存在するものは、個別にランクを取得する


ソースコードと解説

ソースコードは下記の通りです。

ランキングは商品詳細ページに含まれるため、まずは商品詳細ページにアクセスします。(詳細ページのurlはhttp://www.amazon.co.jp/dp/商品コード(ISBN))順位を含むタグから値を取得、また順位が含まれない場合はnilを設定します。ただし、18禁のコンテンツは直接商品詳細ページにアクセス出来ないため、仮置として-1を設定しています。
技術的には特に新規要素は無く、ただenliveを用いて必要な情報を取得しているだけです。
取得した情報はRDBMSのランキングテーブルに追加されます。

今日の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)

マーケットモニタリングアプリの開発(3): 取引情報取得

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
日本に帰国したら、携帯キャリアは何にしようか決めかねている、たなけんです。
本エントリでは、アマゾンマーケットプレイスの出品情報の取得について記載します。

ブラウザからアクセス

アマゾンの商品詳細ページから、中古の出品リンクをクリックすると、出品情報の一覧が表示されます。その時のurlは下記のようなものでした。
http://www.amazon.co.jp/gp/offer-listing/4121020618/ref=dp_olp_used?ie=UTF8&condition=used
このurlからhttp://www.amazon.co.jp/gp/offer-listing/にISBNを付けると、取引情報の先頭ページにアクセスできることが予想されます。
実際に別のISBNで試した所、予想通り取引情報の先頭ページにアクセスすることができました。
また、先頭ページのhtmlを解析したところ、次ページへのリンクはa要素のidがolp_page_nextであるタグのhrefの値であることが分かりました。

プログラムからスクレイピング

上記の観察に基づき、ISBNから出品情報を取得するため、下記の様な関数を作成しました。


  • condマクロ: JavaなどのCase文のようなもの
  • その他工夫した点: Lispらしく、再帰を利用。次ページがあれば、結果をリストに追加して、再帰。次ペーがなければ結果を返す。

その他は、前回と同様enliveを用いて、販売者ID、販売価格、商品状態を抜き出しています。
抜き出した値は、RDBMSの取引情報テーブルに日付とともに収納しています。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)

マーケットモニタリングアプリの開発(2): 中古ランキング取得

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
最近少しずつ体重が減少してきた、たなけんです。
本エントリでは、アマゾンマーケットプレイスに出品されている本の、ランキングの取得について記載します。

ブラウザからアスセス

プログラムからアクセスする前に、まずはブラウザからアクセスしてurlを見てみました。
アマゾンのトップ画面から”カテゴリー > 本”を選択し、メニューの詳細をクリック後、条件を入れずに検索すると、左下に状態を選択するリンクが出るので、それをクリックします。さらに右上の並べ替えで『人気度』を選択すると、アマゾンマーケットプレイスに出品されている本のランキングが取得出来ます。さらに下部のリンクから次のページへと移動すると、urlは以下のようなものでした。
http://www.amazon.co.jp/s/ref=sr_pg_2?rh=n%3A465392%2Cp_47%3A2020%2Cp_45%3A0%2Cp_46%3Abefore%2Cp_n_condition-type%3A680579011&page=2&bbn=465392&sort=salesrank&unfiltered=1&ie=UTF8&qid=1349846898
このurlをデコードすると、下記のようになります。
http://www.amazon.co.jp/s/ref=sr_pg_2?rh=n:465392,p_47:2020,p_45:0,p_46:before,p_n_condition-type:680579011&page=2&bbn=465392&sort=salesrank&unfiltered=1&ie=UTF8&qid=1349846898
このurlからrh=以降のパラメータは検索条件、pageはページ番号、sortは並べ替え順であることが推測できます。
pageパラメータの値を3にしたところ、推測通り3ページ目を読み込むことができました。

プログラムからスクレイピング

上記urlのページを変えてアクセスすることで、1ページから100ページまでプログラムからアクセスすることができることが分かりました。各ページ12冊の本が表示されるため、最大で1200位までの本の取引をモニタすることになります。
それでは、ランキングのページからISBNを抽出してみましょう。
ランキングのページのhtmlの構造を解析したところ、div要素の、id=順位 - 1のタグに含まれる事が分かりました。
そこで、スクリプト用ライブラリのenliveを用いて、各ページから順位とISBNを取得する関数を下記のように定義しました。


  • net.cgrand.enlive-html/html-resource関数: 引数のurlをhtmlとして読み込む
  • clj-http.client/get関数: 引数のurlを読み込む。オプション引数は文字コード
  • clj-time.coerce/to-sql-date関数: java.sql.Date型に変換
  • clj-time.core/now関数: 現在時刻を取得
  • net.cgrand.enlive-html/select関数: 指定したタグの値を取得

上記関数で取得したISBNをRDBMSのUSED_RANKテーブル(日付、ISBN、ランキング)に保存し、まずはモニタリング対象となる本を登録することができました。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)

マーケットモニタリングアプリの開発(1): 概要

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
しばらくマーケットモニタリングアプリの開発に没頭していました、たなけんです。
本エントリでは、マーケットモニタリングアプリの概要について記載します。

事の発端

クラスメイトとの雑談で、古本の流通について話題となりました。そこで私は、日本では個人がアマゾンに本を出品できることを紹介しました。すると友人は、『どんな本が、どれくらいの値段で売れるのか、自動的にデータを取れないかな? データが取れるとどんな本をいくらで出品するのが良いか分かるね。』とアイデアを提案してくれました。
そこで、Clojureでプログラムを作成し、アマゾンマーケットプレイスでどのような本が売れているのかのデータを取る事にしました。

処理の流れ

売れ筋の本の方が、中古本であっても回転が早いだろうと仮定し、まずはベストセラーランキングから本のISBNを取得し、その後、そのISBNをキーに取引情報(sellerIdとisbnで一意に識別)を取得します。
取引情報を継続して取得し、公開されている取引情報が消えた時点で、その取引が成立したと見なし、成立取引一覧に取引情報を移します。
成立取引一覧のISBNから本の属性(ジャンル、出版日)や値引率などを分析し、どんな本がどれくらい売れるのかを求めます。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間15分)

2012年9月13日木曜日

第3イテレーションの振り返り

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
肩甲骨のストレッチの効果か、姿勢が良くなったと最近言われた、たなけんです。
本エントリでは、第3イテレーションを振り返ります。

Datomicおよび各種ライブラリを利用した所感

長所

Clojureで書かれている製品である為、クエリにそのままClojureの式(自作の関数も含む)を使う事が出来る

Clojureで書かれている製品である為、Clojureのデータをそのまま収納する事が出来る

原理的にはスケールアウトが可能
クエリおよびデータの追加、変更がほぼClojureのS式である(Clojureネイティブである)点が唯一にして最大の長所だと思います。RDBMSを利用していると、例えばSELECT文ではSQLの書式に従い、SQLの関数を利用して結果を得て、そこからClojureのデータに束縛し直す必要があります。しかし、Datomicではfindの条件にそのままClojureの関数が使えるため、SQLとClojureのデータを行き来するような処理は必要なく、手早く開発することができました。

短所


  • 無料版ではfreeおよびmemプロトコルのみであるため、スケールアウト性能を検証することができない
  • BIツールのように複数のテーブルを結合するなど、様々な角度からデータを解析する方法が確立されていない
  • 集約系の関数など、自力で実装しなくてはならない

RDBMSであればスタースキーマなど、分析対象のデータを多次元的に扱う手法が確立されています。Datomicの柔軟なクエリ構築力を考慮すると、恐らく良い実装方法があるのだろうと、ぼんやりとそのポテンシャルは感じたのですが、今の時点では具体的な方法までは見えていません。

短所としてBIツールの様な多次元表の利用を挙げましたが、「プログラマブルなクエリが書ける、マクロも書ける」というDatomicの潜在能力を引き出せば、SQLを使うよりもスマートにこれらのソフトウェアを実装することができると(根拠は薄弱ですが)直観しています。

Webアプリケーションを一通り書いてみて気付いたこと(およびClojure愛)

これまで、主なClojureの使い道はツール作成でした。しかし、今回はプレゼンテーション層からパーシステント層までClojureを用いて、小さいながらもWebアプリケーションを完成させることができました。そこで気付いたことを振り返りたいと思います。

自転車あるいは糊

Clojureは私にとって最も手に馴染んだプログラミング言語です。そのしっくり来る感じを例えると「自転車」です。気軽に、どこへでも、最短距離で移動できる乗り物です。
他のプログラミング言語を同様に例えるとすれば、Cは飛行機、Javaは鉄道、Pythonはバスでしょうか。それぞれに利点はありますが、家の裏の公園に行く為に、飛行場を作ったり、線路を引くのは、得たい結果に対して労力が釣り合わない気がします。その点Clojureは行きたい場所へ、そこが車さえも入り込めない路地であっても、最短経路でたどり着くことができます。
また、目的地が遠ければ、鉄道や飛行機を乗り継いで行けばいいのです。駅と飛行場の間は自転車で移動し、最後のバス停から終着地点までの間だけ自転車に乗る事もできます。これは必要に応じてCやJavaで書かれたアプリケーションやライブラリをClojureから使って、目的の機能を実現している時の、僕の頭の中にあるイメージです。
実際、ブログでも紹介したTesseractやImagemagickをClojureから操作し、H2 Database Engineへデータを格納後、帳票を出力するツールの実装は、この乗り継ぎの比喩の良い実例と言えるでしょう。そしてWebアプリケーションに関しても、一から書いたコードは少なく、殆どはライブラリが提供する機能をつなぎ合わせたものでした。
多くの人はこう言うでしょう。「それは自転車ではなくて糊だよ」と

マクロ

自転車の例えはまだ続きます。車のエンジンをバラしてまた組み挙げられる人はどれくらい居るでしょうか、またそれに掛かる時間は?工具は?
バラして組み直す事、これはすなわち言語そのもののハックのしやすさの比喩といえます。
Clojureはシンプルです。特殊形式とマクロと関数しかルールが無いと言っても良いでしょう。構造が簡潔であり、なおかつユーザが手を加える余地を十分に残しています。マクロは、簡単に言えば言語の構文を規定し直す機能です。私は多用はしませんが、「いざとなればマクロでなんとでもできる」という信頼感があります。メカニズムを把握していて、そこに手を入れることができる感覚、それは自転車いじりに似ています。自動車のエンジンや、電車のモーターは、固そうですし、私には複雑過ぎます。
マクロの存在がClojureをシンプルかつ柔軟にしており、マクロがあるため僕はClojureを信頼して使い込む事ができています。この感覚が、やはり私にとって自転車なのです。

万人の自転車へ

Clojureが私にとって自転車である事、それは多くの人にとってどうでも良い話だと思います。しかし、Clojureは他の人にとっても自転車となり得る言語だとしたら?
私はJavaのアプリケーションやライブラリを鉄道に例えました。同様にClojureのライブラリは地下鉄や高速道路網と例えても良いかもしれません。多くの人が利用する点から点への移動には、より効率よく移動するための道が敷かれるからです。そして、それら全ての乗り物に、だれでも自転車を携えて乗ることができます。
このブログを読まれた方が、「Clojure使ってみようかな」と思ってもらえるように、これからもClojureの魅力を伝えていきたいと思います。

私に足りないもの

自転車は簡単に乗れますが、奥が深い乗り物です。フォームの善し悪しで、疲労度が大きく変わります。
私はこれまで、全くの我流でコードを書散らしてきました。自転車で言えばがむしゃらに漕いでいる状態です。
Webアプリを設計、開発する中で何度も「どう書くのが関数型言語の特性を活かしているのか?」と自問しつつも、まず動く物を優先して、ここまで漕ぎ進めて来ました。
当初の目標であったプレゼンテーション層からパーシステント層まで実装を終えた今、次に何をすべきかと考えました、私には何が足りないのだろうか?と。
そこで考え至った結論が、フォームの改善です。プログラミングの基礎です。

年内の目標

コンピュータ書の古典"SICP(計算機プログラムの構造と解釈)"の原著が本家サイトから無料で読む事ができます。関数型プログラミングのエッセンスを掴むべく、このSICPの原著を年末までに読み切りたいと考えています。
学習記録をブログに綴る事で、読者の皆様にも関数型言語でのプログラミングの公理のようなものをお伝えできればと考えています。

運用フェーズに向けて

Webアプリの開発フェーズはほぼ終了しましたが、まだこのプロジェクトは終わっていません。そうです、Herokuにデプロイしてサービスを公開、運用ノウハウを蓄積するというタスクが残っています。また、運用しながらメンテナンス性を高める為にリファクタリングしたり、ログ解析ツールそして機能追加など、改修のアイデアはまだまだあります。
SICPリーディングと平行して、Webアプリプロジェクトも継続していきます。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間1時間)


Datomicの利用(3)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
テストコードを書く時、気持ちの昂りを抑えきれない、たなけんです。
本エントリでは、Datomicを利用したClojureアプリケーションのテストについて記述します。

本体の改修

テストコードを実行した際、想定した通りにデータの改廃がされていなかったため、本体コードを改修しました。
元のソースでは、定数connの宣言部で一度だけt/connect関数を呼び、その接続を他の関数内で利用していました。しかし、この場合、データベースが削除されても接続(peer)のキャッシュにデータが乗っているため、検索が可能な状態でした。
テストコードでは、各テストの前にデータベースを削除し、全てのデータを初期化する必要があったため、find-all関数などに含まれている接続オブジェクトも更新(具体的にはt/connect関数の呼び直し)が必要となりました。
そこで、接続オブジェクトを各関数の引数とし、接続オブジェクトの更新が必要無い本体コードでは、一度だけ宣言したconnを、テストコードでは毎回呼び直したオブジェクトを利用する様変更しました。


単体テスト

事前条件として、peerのGC、データベースの削除、追加、スキーマの作成を行っています。その後データ挿入、検索のテスト。再度条件を初期化し、利用制限確認関数の境界値テストを実施するようにしました。


結合テスト

手動でテストを実施しました。
データベースを初期化、限界件数を1にした状態で、画面を操作し、1度目の検索は正常に実行され、2度目の検索でsorryメッセージが表示されることを確認しました。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間30分)

Datomicの利用(2)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
西川きよし師匠の「小さなことからこつこつと」に、とても共感している、たなけんです。
本エントリでは、ClojureアプリケーションでのDatomicの利用について記載します。

仕様

今回のWebアプリケーションでは、利用制限のある外部APIを使用します。そのため、一日の間に、一定回数を超えるアクセスがあった場合、外部APIへの利用を止める処理が必要となります。
そこで、アプリケーションから外部APIへ問い合わせた内容を永続化しておき、次のアクセスの前に、その日のAPIコール回数を(データベース/Datomic)確認し、利用制限を超えている場合は、その旨をユーザに伝えることとします。
APIへの問い合わせ内容として、まずは検索した単語と検索した日時を記録します。
また、調べられている単語や、アクセスされている日時の傾向を把握する為に、入力された全ての履歴を表示する画面も追加します。

実装

実装の大部分は、thearthurさんのgithubのコードを参考にさせて頂きました。

プロジェクトファイル


Datomicのクライアント(Datomic用語でpeer)であるcom.datomic/datomic-freeおよび、時間計算に便利な(Joda Time LibraryのClojureラッパ)ライブラリであるclj-timeを追加しました。

ns マクロ


プロジェクトファイル同様Datomicおよびclj-timeライブラリの利用を宣言します。

  • use節: datomic.apiのうちdbとqは名前空間を付けずに呼び出せ、他の関数は名前空間のエイリアスにdを仕様
  • require節: clj-time.coreおよびclj.time.coerceの名前空間のエイリアスを設定


データベースおよびスキーマの作成(DDL)


データベース及びスキーマを定義します。無料版のDatomicではメモリにデータを保存するmemプロトコルと、H2 Database Engineを内部で利用し、ファイルにデータを保存するfreeプロトコルを利用することができます。
Datomicのスキーマ定義はRDBMSとはやや異なり、属性毎に個別に定義を宣言することでエンティティ全体を組み立てる形式となります。
具体的には、上記ソースでは、エンティティがworkで、wordとtimeがworkの属性として宣言されています。(それぞれ型はstringとinstant(日時))
RDBMSでの定義を(単純化して)考えると、テーブル名がworkとなり、wordとtimeはテーブルworkの中の列となります。
RDBMSのようにトップダウンでスキーマを定義する訳ではなく、逆にボトムアップでスキーマを定義して行きます。
実際、列の型を変えるなど、プログラミングしながら、属性を追加したり、削除したのですが、スキーマ変更に伴い、わざわざ既存のデータを変更(エクスポート&インポート)しなくても良かった点には驚きました。(RDBMSを利用している場合は、スキーマを変更した場合は、データのインポートが必須となるので)
データモデルを固める前に、いろいろと試すことができる、柔軟であるといった意味では、開発時に余計な作業でプログラマの時間を奪わない工夫がされていると感じました。
その一方、データ型が不揃いであることから、検索時の性能劣化、柔軟すぎて不整合が発生しないだろうかなど、運用時に考慮すべき課題も目につきました。

  • d/create-database関数: 引数のurlをアドレスとするデータベースを作成(データベースを作成していないと、コネクション作成時に例外が発生する点に注意が必要)
  • d/connection関数: 引数のurlで指定されたデータベースへの接続を確立する
  • d/transact関数: 引数の式をトランザクションとして実行する


データの追加および検索(DML)


スキーマの定義が管理用領域への(メタ)データの書き込みであるのに対し、データの追加はユーザ領域へのデータの書き込みとなります。(どちらも "d/transact conn データ" と書かれているのはその為です。)
add-a-work関数では、引数に単語と日時を取り、workエンティティを追加します。
find-all関数では、登録されている全てのworkエンティティを取得します。q関数の引数となっているクォートされたベクタがSQLで言う所のSELECT文に相当します。
:findに続く?n ?tは、SQLのSELECTに続く列名の様なものです。しかし、SQLとは異なり属性定義(スキーマ)に紐付いている訳ではなく、任意の文字列が利用可能です(?nameなど)。
?nおよび?tが何を表わしているのかは、続くwhere節で定義されます。
”[?e :work/word ?n]”は「任意のエンティティ?eの属性:work/wordの値は?nである」ということを宣言しています。言い換えると、任意のエンティティ?eは、属性に:work/wordを持ってることになります。つまり「?nは属性に:work/wordをもっているとあるエンティティの:work/wordの値である」ということを表わしています。
"[?e :work/time ?t]"も同様に、「?tは属性に:work/timeをもっているとあるエンティティの:work/timeの値である」となります。
では複数ある:work/wordの値と:work/timeの値が、それぞれ同一エンティティに紐付いていることはどのように示されているのでしょうか?(SQLでテーブルを結合する際に、結合する基準となる列を指定するようなイメージ)
実はDatomicでは特にキーを指定する必要がありません。なぜなら前の式”[?e :work/word ?n]”の?eと、後の式"[?e :work/time ?t]"の?eは、任意ではあるが同一のエンティティと見なすからです。Datomicのクエリで使用される名前(?nなど)は、同じ名前であれば同じオブジェクトを指していると見なされます。この結果、find-all関数の結果として、属性に:work/wordと:work/timeを持っているエンティティの、それぞれの値の集合が返されます。この仕組みをDatomicでは論理プログラミング(Logic programming)と呼んでいます。

  • time/now関数: 現在日時を取得
  • time/within?: 引数のintervalの中に引数の日時が含まれて入ればtrueを返す
  • time-coerce/to-date: Jodaのdatetime型からjava.util.Date型へ変換
  • time-coerce/from-date: java.utils.Date型からJodaのdatetime型へ変換


クライアントからのアクセスのコントロール


外部APIにアクセスする前に、その日のアクセス総数を取得し、制限を超える場合は、検索をせずにsorryメッセージを返すよう、limit?関数を追加、call-api関数を変更しました。

全履歴を取得する管理画面


httpクライアントからfind-allを呼ぶインターフェースを追加しました。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間2時間)

Datomicの利用(1)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
日本語であるにも関わらず、ロシアからのアクセスが最も多いブログを書いている、たなけんです。
本エントリではClojureアプリケーションでのDatomic利用方法(インストールまで)を記載します。

Datomicとは

Datomicとは、私が愛用しているClojureの作者である、Rich Hickey氏が開発している、新しいタイプのDBMSです。
現在では、これまで主に利用されてきたRDBMSだけではなく、KVSなどもごく普通に利用されるようになってきましたが、それらのデータベースと異なる点は何か、少し見てみましょう。

リードに重点を置いたデータ分散システム

データが更新されたタイミングで、クライアント側に持たせているキャッシュが同期されます。そのため、ノードは分散されていますが、検索前に必要なデータに関連するキャッシュを更新し検索するため、高速にデータの読み込みが可能です。その反面、データの一貫性を保証しながら書き込むため、ライトには多少のオーバーヘッドがかかります。

クライアント側でクエリを解析

通常のRDBMSではクライアントから投げられたSQL文をサーバで解釈してから、実行するのですが、Datomicはクエリの解釈をクライアントで行います。その結果、サーバ側の負荷が通常のRDBMSよりも軽くなり、少数のサーバで多数のクライアントからのアクセスを、軽快に捌くことができます。

柔軟なクエリ

ClojureひいてはLispの根本思想である『全てのプログラムはデータであり、全てのデータはプログラムである』をDatomicは体現しています。
先述の通り、クライアント側でクエリを解釈するということもあり、クエリそのものがプログラムであることを許容しています。
プログラム可能なクエリという発想は、識者をして「Datonicは10年先のテクノロジーを先取りしている」と言わしめている理由のひとつかもしれません。

インストールとトランザクタープロセスの起動

Datomicのダウンロードページより無料版をダウンロードし、任意のディレクトリに解凍します。解凍先のディレクトリに移動し、シェルに下記を入力しトランザクタープロセスを起動します。

bin/transactor config/samples/free-transactor-template.properties

デフォルトではポート4334が接続待ち受けポートとなります。
ポートやその他設定を変更するには、config/samples/free-transactor-template.propertiesファイルを編集します。

今回の作業は以上。最後までお読み頂き、ありがとうございました。
たなけん(作業時間30分)

2012年8月12日日曜日

Clojureで帳票処理(csv読み書き、RDBMS利用、グラフ描画、PDF出力)

はじめに

おはようございます。当ブログにアクセス頂き、ありがとうございます。
授業が始まってからグログ更新が滞っていた、たなけんです。
本エントリでは、Clojureを利用した帳票処理について記載します。

事の発端

現在、大学院で会計を専攻しているのですが、任意科目でいくつかのMBA専攻のクラスを受けています。(前期までに、ほぼ会計は履修したため、今期は75%がMBAのクラス)
その履修しているMBAクラスのひとつに、企業戦略を立案するクラスを履修しています。
面白いことに、このクラスの成績は、シュミレーションゲーム上のスコアにより決定されます。(クラスのメンバーを8チームに分け、チーム間で競争することとなります。)
決定すべき項目として、製品開発(高機能戦略や低価格戦略)、マーケティング(世界を4地域に分け競合の出方を伺いながらどのエリアを攻めるか)、生産(工場の人員配置や設備投資など)、財務(株式発行、社債発行など)などがあり、毎週50項目ほどのパラメータを検討して、事業戦略を実装し、他チームと結果を競い合っています。
各チームが決定する50項目のうち、27項目は年度末(実際は毎週日曜日)に結果とともに全チームに公開され、翌年のパラメータ検討の際の参考資料とすることができます。
他チームが見る事のできるパラメータは27項目なのですが、それがチーム毎(8)、地区毎(4)、四半期毎(4)で公開されるため、結果として毎年3,456(=27*8*4*4)項目に目を通すこととなります。また、年間の比較を考えると、1年(1週間)毎にデータが3,456項目ずつ増えることになりますので、数値だけを見て比較するのは困難であると考えられました。
そこで、数値の変化を、各社、各地域で比較出来るようグラフを作成することとなりました。

仕様

入力: 会社、地域ごとに1csvファイル。行は項目、列は四半期ごとの数値が記載されている。
出力:1項目1ページ、1ページに各地域のグラフを縦に配置、1グラフに8社と平均値を表示、横軸は時間、縦軸は値。

出力例
製品販売価格



数値をグラフにすることにより、各チームの意思決定が比較しやすくなっているのが分かると思います。例えば、EA市場ではほとんどのチームが価格を他の地域より高めに設定していること、また、year7に突然ピンクチームがAP、LA、NA市場で価格を高く設定したことなどがこのグラフから読み取れます。

実装

全ソースはtana-kenのGithubにて公開しています。
興味を持たれた方は是非ご覧になって下さい。
以下、ポイントを絞って、実装内容を紹介します。

nsマクロ

https://gist.github.com/3331553
ライブラリとしてclojure.java.io、clojure.data.csv、clojure.java.jdbc、incanter.core、incanter.chartsを利用します。

csvファイル読み書き


ファイルサイズが十分に小さいため、遅延シーケンスとして処理をせず、doallにより全データをメモリ上に読み込んでいます。

行列入れ替え


元ファイルは、列方向にデータが追加される仕様であったため、行方向にデータが追加されるよう、行と列を入れ替える処理を実装しました。

RDBMS利用


組み込みRDBMSとしてH2 Database Engineを採用しました。
csvファイル読み込み同様、想定される取得データが十分小さいため、doallにより全データをメモリ上に読み込んでいます。
また、今回はテーブルを結合する必要がないため、H2 Database Engineのcsvファイル読み込み機能を利用しました。(csvファイル読み込み -> 整形 -> 1ファイルに結合 -> H2 Database Engineにてテーブルとして利用)

グラフ描画


incanterを通じてjfreechartオブジェクトを作成しています。
RDBMSからグラフ描画に必要なデータセットを取り出し、グラフを描画します。

nsマクロ


incanterで利用しているjarと依存関係で不整合があったため、プロジェクトを分けました。ライブラリにはclj-pdfを利用しています。

内容作成


タグ付けされたベクタにて要素を構成しています。
sort-by関数により、ページを制御しています。

PDF描画


pdfマクロにて、与えられた内容をpdfファイルとして出力します。

今回の作業は以上、最後までお読み頂きありがとうございました。
たなけん(作業時間4時間)