thirose’s blog

openstackやpythonなどなど

MongoDBを使う時に使うODM

mongoDBでデータを管理する

MongoDBとは

スキーマを定義しなくても使用できるドキュメント指向データベースである。 MySQLなどと違い、スキーマを定義しなくても使えるということ。でもそれってwebアプリケーションを作るとき 危なくないのかなーという思いもあり、今まで使ってこなかった。 なおかつ、過去に一回みたことあるコードで本当に定義されてなく、これがwebサービスだったら怖いなーと思ったりもした。 どんなデータが入っているのか未知数。そういったコードに限ってドキュメントが整備されてなかったりもする。

MySQLとの違いは

普段使ってるMySQLとの違いは当然あるので、簡単に MongoDBの情報をMySQLとの比較をまとめる。

  • メリット
    • 高パフォーマンスかつスケービリティを保持してること
    • 比較的簡単に使えること
  • デメリット
    • トランザクションやリレーショナルな機能をサポートしていない
    • データtypeがバラバラになる可能性がある
    • bsonというフォーマット(バイナリ型JSON)
      • 最初扱い方がわからなかった

ざっくりまとめたが、トランザクションについては今後サポートされる見込み。 2018年の夏にリリースされる4.0に組み込まれる予定である。 参照元: https://techcrunch.com/2018/02/15/mongodb-gets-support-for-multi-document-acid-transactions/

意味するものは同じでも言葉が違っているので、それも覚えておいた方が良いかもしれない。

MongoDB MySQL
Database Database
Collection Table
Document Raw
Field Column

実際に使う

検索してみると、MongoEngineというODM(Object Document Mapper)がよく使われてるようだけど、
今回はFlask-MongoAlchemyを使って、なるべく普段使ってるFlask-SQLAlchemyと同じように使えるようにしてみた。
https://pythonhosted.org/Flask-MongoAlchemy/
MongoEngineを使ってもさほど使い方は変わらないし、一般的に使われてるのはMongoEngineっぽい。
MongoEngineは機能が豊富でとても便利そうだということもわかったけど、とりあえずSQLAlchemyをずっと使っていたというだけで、 mongoalchemyを選択した。

mongoengineとmongoalchemyの検索件数の比較: mongoengine, mongoalchemy - Google トレンド

webアプリケーションを作る

その前に整合性を求められるようなシステムならそもそも使うなよって話ではあるけど。
このように型の整合性やvaldationを使いながら使えばデータの不備は回避できるんじゃないかなーと思ったり。
bsonで返ってくるからresponseを返すときは、from bson.json_util import dumps を使って、dumpすると良い感じに 結果を返却できる。

$ curl -X POST  http://127.0.0.1:5000/api/user -d '{"name":"hoge", "age":30, "address": {"prefecture":"hogehoge", "city":"shizuoka"}}' -H 'Content-Type:application/json'
"registered"
$ curl http://127.0.0.1:5000/api/user
{
    "data": [
        {
            "name": "hoge",
            "age": 30,
            "address": {
                "prefecture": "hogehoge",
                "city": "shizuoka"
            },
        }
    ]
}

テストで作ったコード。 https://github.com/hirosetakahito/mongodb-sample
実際作ってみると、Flask-SQLAlchemy つかうのとそんなに変わらない感じで使えるのでとても使いやすい。
また、MongoEngineもMongoAlchemyと使い勝手は変わらないからどちらか気に入ってるほうを使えばいいんじゃないかな。
Flask-MongoEngine — Flask-MongoEngine 0.9.5 documentation