GoogleAppEngineでWassr検索作った。色々つまずいた点のまとめ
とりあえづ、必要っぽい機能を最低限盛り込んめた気がする。wassr検索(http://a2c.appspot.com/wassrhub)を作る時に、ひっかかった所と対処をリストアップする。
epocタイムを,datetime型にする方法
- wassrのjsonAPIで返ってくるデータは、epoc timeでなんかでっかいintみたいなのが返ってくる。大昔からの秒数らしいが、そんな型は、appengineにないので,Datetimeにキャストしなくてはならない。datetimeは、epocを渡しても駄目だった。epocの文字列を渡すとDatetimeのオブジェクトが返ってくる関数を作って対処した。内容は、文字列をtimeに渡しisoフォーマットに変換して、文字列としてdatetiemeに渡してあげる事で、DataStoreに格納することが出来た。
def epoc2datetime(epocSTR): sDt = time.gmtime(epocSTR) return datetime.datetime(sDt[0],sDt[1],sDt[2],sDt[3],sDt[4],sDt[5],sDt[6])
appspot.comのtzのデータを簡単にjstにする方法
- 上記、epocのdatetime変換が出来るようになったがtzがずれている感じ(gmt?)だったので、jstで取り出す必要があった。サンプルは、シンプルなdatateimeのフィールドが有ると言う事にする。
created = db.DateTimeProperty(auto_now_add=True)
- こんなフィールドから、日本時間で表示する為にモデルメソッドを追加した。これは、テンプレートからも使えるので大変便利
class Feed(db.Model): created = db.DateTimeProperty(auto_now_add=True) def get_jst(self): return self.created + datetime.timedelta(hours=9)
個人的なモジュールをimportsする方法
- これがなかなか出来なくて困った。後述のTinySegmenterを使う必要にがあったのだが、importが全然上手く行かなかった。正しいかどうか不明だが、__init__.pyというファイルを作りルートからのpathを.(ドット)で繋いでやる事でインポートすることが出来た。
同じディレクトリ(app_id/wassrhub/.)にmain.py TinySegmenter.py __init__.py(中身は空っぽ)を配置する。
from wassrhub.TinySegmenter import TinySegmenter
文章から単語で検索する方法
- 全文検索とか簡単とか思ってたら大間違いでめっちゃメンドクサイと言う事がわかった。wassrhubでは、分かち書きした単語をStringListPropertyに突っ込みそれにフィルターをかける事で、なんとなくそれっポイ動きになったのでよしとした。分ち書きには、mecapiとtinySegmenterの二種類の関数を作った。mecapiの方が正しく分けてくれている感じがするが、StringListPropertyになぜか保存出来なかったので、現状はtinySegmenterのみを使用している。
モデルの定義部分(関係ある所だけ抜き出し)
class Feed(db.Model): # オリジナルのヒトコトが格納されるProperty html = db.StringProperty() # htmlを分ちた単語が格納されるProperty index_text = db.StringListProperty() # instanceにリストを渡して保存するメソッド def set_strList(self, str_list): self.index_text=str_list self.put()
検索の際に、screen_nameとヒトコト本文のどちらからも検索出来るようにしたかったので、index_textにscreen_nameも追加するようにした。本来であれば、screen_nameとヒトコトとそれぞれにfilterして、マージした物にorderをかけたかったが、filter後のqueryオブジェクトのjoin方法が判らなかったので、この方法にした。以下、保存部分。
# jsonに含まれる情報を元にインスタンス作る feed_ins = Feed(link = i['link'], epoch = epoc2datetime(i['epoch']), html = i['html'][:500]) # tempなarrayにhtml 分かち書きした物を代入 tmp_index_list = TinySegmenter().segment(i['html']) # tmp_index_list = mecap_interface(i['html']) # tempなarrayに、screen_nameを追記する tmp_index_list.append(i['user']['screen_name']) # tempなarrayに user_login_id を追記する tmp_index_list.append(i['user_login_id']) # 全部入りのtmpなarrayをモデルメソッドに渡して書き込んでもらう feed_ins.set_strList(tmp_index_list)
iには、wassrJsonAPIの一人分のデータが入っています。
感想
作り始めてから、3日くらいで非プログラマな自分でも作ることが出来てとても楽しかった。GAEは、やらなくちゃ行けない事とやりたい事がとても近い気がする。やりたい事だけやってても、いつの間にか完成してしまう。今後は、areacodeやらphoto_thumbnail_urlなど、現在使用されていないフィールドに、wassrからデータが流れてくるようになったら、対応して行きたい。
後悔
Djangoフレームワークを使わなかったので、Pagenatorが未だに実装されていない。最大でも1000件までしかfilterで抜けないのでブラウザが応答不能になるほどでかいテーブルを返す事は無いと思うが、20個区切りくらいでどんどんさかのぼれるように作れなかった事が、心残り。