読者です 読者をやめる 読者になる 読者になる

MongoKitを試す

Python MongoDB

MongoKitはMongoDBをより容易に扱うためのPythonライブラリ。

MongoKit framework try to keep its simplicity when you manage mongodb in python. MongoKit was developed to be fast and light with KISS and DRY in mind.

http://bitbucket.org/namlook/mongokit/

MongoDBはスキーマレスDBなわけだが、スキーマがないからといって不正なデータをDBに突っ込んでいては面倒なことになる。MongoKitを使うとデータ・ドキュメントの妥当性を検証するのが楽になる。

基本的な使い方

MongoDocumentを継承してドキュメントを定義する。各プロパティの意味は一目瞭然。

import datetime
from mongokit import *

class BlogPost(MongoDocument):
    db_name = 'mongokit_test'
    collection_name = 'mongokit_tutorial'
    structure = {
        'title' : unicode,
        'body'  : unicode,
        'author': unicode,
        'created_at': datetime.datetime,
        }
    required_fields = [ 'title', 'author', 'created_at' ]
    default_values = { 'created_at': datetime.datetime.utcnow }

ドキュメントを検証する

上で定義したドキュメントを使って、

post = BlogPost()
post["title"] = u"test"
post.validate()

のような操作を行うと、required_fieldsに指定したプロパティが未定義のため、"mongokit.mongo_exceptions.RequireFieldError"という例外が発生する。

ドキュメントを保存する

ドキュメントのインスタンスに対してsave()メソッドを呼ぶ。save()は内部でvalidate()メソッドを呼ぶので、validate(), save()を繰り返す必要はない。

post = BlogPost()
post["title"] = u"test"
post["author"] = u"perezvon"
post["body"] = u"test"
post.save()

新規追加ではなく更新の時には、取得したインスタンスのフィールドを変更して、save()メソッドを呼ぶ。

obj = BlogPost.one({ 'author': u'perezvon' })
obj["title"] = u"Hello World"
obj.save()

ドキュメントを取得する

ドキュメントクラスのクラスメソッドとしてall()が定義されているので、これを使う。すべてのオブジェクトを取得するならば、

for obj in BlogPost.all():
  print obj

MySQLのLIMIT, OFFSET句のようなことをするならば、

for obj in BlogPost.all(skip=10, limit=10):
  print obj

条件を指定するならば、

for obj in BlogPost.all({'author': u'perezvon'}):
    print obj

ドキュメントを削除する

remove()クラスメソッドを使う。

BlogPost.remove({ 'title': u'test' })

条件を指定しないと例外が発生する。親切心・・・なのだろうか?

# 動かない!
BlogPost.remove()

# これも動かない!
obj = BlogPost.one({ 'author': u'perezvon' })
obj.remove()

継承

c.f.

今日は試さなかったが、おそらく継承を使うようなケースがスキーマレスDBの真骨頂なんだろう。

MongoKitへの不満

よりPythonオブジェクト的に書きたいので、次のように書きたいところだが・・・

# -*- coding: utf-8 -*-
obj = BlogPost()
# ドット記法でアクセスしたいのだが・・・
obj.title = u"test"

MongoDocumentがdictを継承するだけの潔い実装になっているので、このような使い方はできない。

また、

obj = BlogPost(title=u"test", author="perezvon", body="test")

のような書き方もできない。これらはいずれも、実装を簡潔にするための制限だと思われる。