「第6回 MongoDB JP 勉強会 in Tokyo」に参加しました

「第6回 MongoDB 勉強会 in Tokyo」 : ATND
20110924_「第6回 MongoDB 勉強会 in Tokyo」( #mongotokyo ) - Togetter
参加しました。

まず最初に、mongodb勉強会はだれでもWelcomeな雰囲気の良い勉強会なので、勉強会に参加したいけどちょっと難しそうだな・・・みたいな人におすすめです。

色々と面白い発表があったのですが、それは上のリンクを参考にしてもらって、@bibrostさんのDBRefをいっぺんに取ってくる話(Bulk joinでMongoDBのDBRefを2倍速くする | Fungoing LLC)について、pymongoのAutoReferenceにパッチを当てるやりかたについて書きます(AutoReference使っている人がいるのかな?)。

やりかたは、pythonだと元コードを直接変更せずにsetattrで動的にコードを書き換えられるのでそれでいきます。
autoreference_patch.py(横に長くてすまん。詳しくはukyo/pymongo-autoreference-patch - GitHub)

#coding: utf8

"""pymongoのAutoReferenceにパッチ当てるやつ

リスト内のDBRef全部にクエリを発行せずに{$in: [1,2,...,n]}する。

Example:
>>> from pymongo.son_manipulator import AutoReference, NamespaceInjector
>>> import autoreference_dbref_patch
"""

from bson.dbref import DBRef
from bson.son import SON
from pymongo.son_manipulator import AutoReference


def transform_outgoing(self, son, collection):
"""Replace DBRefs with embedded documents.
"""

def transform_value(value):
if isinstance(value, DBRef):
return self._AutoReference__database.dereference(value)
elif isinstance(value, list):
#listの先頭がDBRefだったら1クエリで取ってくるようにする
if value and isinstance(value[0], DBRef) and len(value) > 1:
return [o for o in self._AutoReference__database[value[0].collection].find({"_id": {"$in": [v.id for v in value]}})]
else:
return [transform_value(v) for v in value]
elif isinstance(value, dict):
return transform_dict(SON(value))
return value

def transform_dict(object):
for (key, value) in object.items():
object[key] = transform_value(value)
return object

return transform_dict(SON(son))


#AutoReferenceにmonkey patch
setattr(AutoReference, 'transform_outgoing', transform_outgoing)

使い方は簡単で(Exampleに書いてあるが)、AutoReferenceをimportしたあとにこれをimportするだけです。他の部分を変更する必要はありません。

というわけで、もしAutoReferenceを使っている人がいたら試してみてください。

ソースコード:
ukyo/pymongo-autoreference-patch - GitHub


posted by 右京 | Python
blog comments powered by Disqus
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。