迷亭さんの思うとこ

仕事の話とかゲームとか

GAEについて

おはようございます。
昨日はいつの間にか寝てしまって、早く起きすぎてしまったのでブログでも書きます。


この前は書ききれなかったのですが、GAE(Google App Engine)の大変なところ。
っていうと結構ありがちなんですが、他の人が書いてなさそうな事も。
最初の難関は、DBがRDBMSじゃないことですね。
もちろん、フレームワークSlim3とか使えば、ある程度誰でも?直感的に書けると思いますが、制約が半端無い。
詳細はSlim3のサイトを見てもらえばいいのですが、

  1. 1クエリー内の不等式(<, <=, >=, >) は1つのプロパティにしか使えない。

 プロパティはエンティティ内の項目です。
 因みに、Slim3のサイトには書いてありませんが、startsWith(前方一致)も不等式に含まれますw

  1. 不等式を使ったら、ソート順の先頭にそのプロパティを指定する必要がある。

 これはそんなに困らなかった。

  1. 部分一致が使えない。

 これは参りました。部分一致というと、SQLでいうところの

 項目名 LIKE '%文字列%' 

って言う書き方です。
色々と調べまくったのですが、今のところ楽に組む方法は無さそう。。
一応、slim3にてcontaints(文字列)ってメソッドは用意されているんですが、inmemoryなので検索した結果に対してフィルタが掛かります。
つまり、検索文字列に該当するレコードが検索数の上限を超えた位置にあるとアウトです。
また、該当する1件を検索するために全件取得するのも効率が悪いです。
色々悩んだ末、組んだほうが早くね?って思えてきたので、結局、全文検索(N-gram)を自分で実装しました。
仕組み自体は簡単で、まぁググってもらえば分かるんですが、検索させたい情報のインデックスをあらかじめ作っておきます。
私はここのサイト見て作りました。mixi engineer blog
インデックスのサイズは大きくなりますが、遅すぎることもないです。
ただ、注意として、インデックスを作るときは文字数によっては処理を分割したほうがよいです。
300件の登録とかだと、30秒ルール(処理は30秒以内に終わらせないとエラー、細かくは10秒ルールもあるらしい・・)に引っ掛かったので、処理を分割してQueueを利用したほうがよいです。(削除も同じ)

あとは、はまりどころとか。
開発環境のリソースをそのままUPしても動かない。
もちろん、開発環境ではちゃんと動作するんですが、開発環境だとインデックスをあんまり意識することはない。(正確には意識しなくても出来るw)
が、きちんとインデックスを書いてあげないと検索走った瞬間に落ちます。
因みにインデックスは、開発環境に勝手に作ってくれていますので、名前変えてデプロイするだけ。
WEB-INF\appengine-generated\datastore-indexes-auto.xml → WEB-INF\datastore-indexes.xml
ただし、デプロイしてもインデックスの作成が完了するまでは数十分から1時間近く掛かるので、早めに作成しておくこと。

エンティティの親子関係は結構はまる
個人的には、あんまり親子関係にするメリットが感じられません。
他のエンティティへのキーを持たせておいて必要なときにデータを持ってくるのがシンプルで良いかと。

開発環境で動いたのに動かないVer2
以下、複数のキーで検索する例なのですが、これは本番環境では動きませんでした。

List list = Datastore.query(entityMeta).filter(entityMeta.key.in(keys)).asList();

正しい例。

List list = Datastore.get(entityMeta, keys);

しかもこれ、com.google.appengine.api.datastore.DatastoreFailureException: internal error. って出るんで、理由が良くわかんないw
内部サーバエラーって曖昧すぎる・・Orz

と言うことで色々書いたのですが、書ききれないのでとりあえず今日はこれまでww

結論、多少のお金に余裕がある(月数千円程度払える)人は、Amazon EC2とかにしたほうが楽かも。(でも苦労して作ると愛着はあるw)
ちなみにAmazon EC2は、最近シンガポールのデータセンターが出来て、近々、日本にも出来るらしい。