MongoKitを試す

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")

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