# mongoDB + Python ## mongoDBのセットアップ **ローカルに作成する場合**(macOS) 1.install ```bash brew tap mongodb/brew brew install mongodb-community ``` 2.起動 ```bash brew services start mongodb-community ``` 3.DBへの接続 ```bash mongo ``` 4.DB作成 ```bash use DB_NAME ``` 5.コレクション追加(RDBでいうテーブル) ```bash db.createCollection("COLLECTION_NAME") ``` 6.ドキュメントの作成(RDBでいうロー) ```bash db.users.insertOne({ hoge: "hogehoge", hage: 1}) ``` ## pythonライブラリ - [pymogo](https://pypi.org/project/pymongo/)を使うのが主流っぽい 基本的な操作一覧 ```python= from pymongo import MongoClient # 接続 def test_get_database_and_collection(): with MongoClient("172.17.0.2", 27017) as client: test_db = client.test_db users = test_db.users assert users is not None # ドキュメントの登録、取得 def test_document_insert_and_find_many(): with MongoClient("172.17.0.2", 27017) as client: test_db = client.test_db users = test_db.users user = [ {"name": "taro", "age": 20, "email": "hoge@example.com"}, {"name": "hanako", "age": 36, "email": "hoge@example.com"}, {"name": "ken", "age": 23, "email": "hoge@example.com"} ] users.insert_many(user) assert users.count_documents({}) == 3 found_all_users = [user for user in users.find({}, sort = [("age", pymongo.DESCENDING)])] assert found_all_users[0]["name"] == "taro" assert len(found_all_users) == 3 ``` ## 触ってみた所感 - 操作感はかなり楽だった - JSONで吐き出すことも容易そう ## mongoDBをどこに置くのが良いか ### mongoDB on EC2 [詳細](https://dev.classmethod.jp/articles/mongodb-on-ec2/) - エンタープライズエディションとコミュニティエディションがある - エンタープライズエディションでできること - マネジメントサービスが利用できる(バックアップや監視ソリューション) - SNMPモニタリングができる - KerberosやLDAP認証が利用できる - TableauなどのBIツールと連携可能な「MongoDB Connector for BI」が使える(Ver3.2以上) - スキーマビジュアライゼーションツール「MongoDB Compass」が使える - インメモリストレージエンジンが使える(Ver3.2.6以上) ### Amazon DocumentDB - MongoDB のワークロードをサポートする、高速かつスケーラブルで可用性に優れたフルマネージド型のドキュメントデータベースサービス - JSON データの保存、クエリ、およびインデックスを容易にする ### まとめ - AWS的にはDocumentDBの方を推してそうな雰囲気 - EC2でやる方は普通にlinuxサーバーの上でmongoDB動かすのと変わらないような印象 ### その他参考リンク - https://aws.amazon.com/jp/quickstart/architecture/mongodb/ - https://docs.aws.amazon.com/ja_jp/quickstart/latest/mongodb/overview.html - https://aws.amazon.com/jp/blogs/news/12-things-you-should-know-about-amazon-documentdb-with-mongodb-compatibility/ ## ドキュメントの更新 ### 更新方法 - findの代わりにupdateコマンドを使う - 更新するドキュメントの条件を第1引数に渡して、第2引数に更新する内容を渡す ``` db.コレクション名.update({検索条件}, {更新内容}) ``` - updateコマンドの第1引数の検索条件の書き方は、findコマンドの検索条件(クエリセレクタ)と全く同じ ### 注意点 - MongoDBのupdateは、第2引数で渡した内容で上書き保存する。 例:hogeさんの性別をXに上書きするとき次のように実行すると ``` > db.user.update({name:'hoge'}, {gender:'X'}) > db.user.find({}, {name:1, gender:1, _id:0}) { "gender" : "X" } { "name" : "taro", "gender" : "m" } { "name" : "hanako", "gender" : "f" } { "name" : "ken", "gender" : "f" } ``` hogeさんのレコードが消えてしまう 上で行った処理は、hogeさんの性別を更新したのではなく、名前がhogeというドキュメントをgender:Xというドキュメントで上書きしたということになる。 - $setという修飾子を利用すれば解決する ``` > db.user.update({name:'hoge'}, {$set:{gender:'X'}}) > db.user.find({}, {name:1, gender:1, _id:0}) { "gender" : "X", , "name" : "hoge" } { "name" : "taro", "gender" : "m" } { "name" : "hanako", "gender" : "f" } { "name" : "ken", "gender" : "f" } ``` - 存在しないフィールドを指定してドキュメントをアップデートすることも可能 ## ユーザー認証 **関連リンク** https://docs.mongodb.com/v3.2/reference/built-in-roles/#superuser-roles https://qiita.com/h6591/items/68a1ec445391be451d0d https://www.infoq.com/jp/articles/Starting-With-MongoDB/ - デフォルトでは認証なしで作成されてしまう - 世の中にはたくさん認証なしで運用されてるmongoDBがあるらしい **ユーザーの作り方** - shell上でやる場合 1.ユーザー認証を有効にする ``` mongod --dbpath <directory> --auth ``` 2.作成する ``` $ mongo > use DB名 switched to db DB名 > db.createUser({user:"mongo", pwd:"18fuw63x", roles:["root"]}) Successfully added user: { "user" : "mongo", "roles" : [ "root" ] } > exit ``` - pymongoで実行する場合 ```python= import pymongo host = 'localhost' port = 27017 db = 'admin' client = pymongo.MongoClient(host, port) client[db].add_user( 'admin', 'password', roles=[ { 'role': 'userAdminAnyDatabase', 'db': db, }, ], ) ``` ## django2とdjango3の大きな違い - 現状Python 3.6、3.7、3.8のみサポートしている - ASGI(非同期Webサーバー)対応 - 現状では非同期のviewやmiddlewareの作成はまだサポートしていない - TextChoices、IntegerChoices、ChoicesをField.choicesとして列挙型が使えるようになった - 使い方は[こちら](https://docs.djangoproject.com/ja/3.0/ref/models/fields/#enumeration-types) - django3で消された機能 - django.db.backends.postgresql_psycopg2 - django.shortcuts.render_to_response() - DEFAULT_CONTENT_TYPE - HttpRequest.xreadlines() - Field.from_db_value(),Expression.convert_value() - QuerySet.earliest(),latest() - django.utils.http.cookie_date() - テンプレートタグのstaticfiles,admin_static - django.contrib.staticfiles.templatetags.staticfiles.static() ## djangoでのconnection poolについて - pymongoでサポートしていそうな雰囲気 - [公式ドキュメント](https://pymongo.readthedocs.io/en/stable/faq.html#how-does-connection-pooling-work-in-pymongo)