ろぐれこーど

限界組み込みエンジニアの学習記録とちょっぴりポエム

MongoDBのcollection基本操作をpythonで(pymongo)

pymongoによるMongoDBのcollectionに対する操作をしょっちゅう忘れるのでメモします。バージョンは以下を想定しています。基本的にはMongoDBでのshellコマンドがそのままpymongoで使用できます。

  • MongoDB == 4.4.1
  • pymongo == 3.10.1

検索

基本

検索時はfind()を使用し、以下のように条件を指定します。(MongoDBのshellでも同様です)

db.collection.find({条件})

pymongoでは、条件はdict形式で指定します。namehogeのドキュメントを検索するには、以下を条件に指定します。

{"name": "hoge"}

演算子の指定

mongoDBがサポートする演算子を使用すれば、複雑なクエリを実現できます。主な演算子は以下のとおりです。

演算子 type 概要 mongo shellでの例
$lt Comparison < {age: $lt: 20}}
$lte Comparison <= {age: {$lte: 20}}
$gt Comparison > {age: {$gt: 20}}
$gte Comparison >= {age: {$gte: 20}}
$ne Comparison != {age: {$ne: 20}}
$in Comparison 配列指定した値のいずれかにマッチする {tags: {$in: [, ]}}
$nin Comparison 配列指定した値のいずれにもマッチしない {tags: {$nin: [, ]}}
$and Logical 配列指定した条件のANDにマッチする {$and: [{cond1}, {cond2} ]}
$or Logical 配列指定した条件のORにマッチする {$or: [ {cond1}, {cond2} ]}
$exist Element 特定のフィールドを持つドキュメントにマッチする {name: {$exist:true}}
$regex Evaluation 指定した正規表現にマッチする {name: {$regex: /hoge/}}

クエリに関する他の演算子は以下の公式ドキュメントで確認できます。

docs.mongodb.com

上記の演算子をpymongoで使用する時は、演算子全体を文字列として指定します。例えば

AND ┳ age > 20
    ┣ languageに"English"または"Japanese"を含む
    ┣ TOEFL というフィールドを持つ
    ┗ name に Tanaka を含む

のような条件で検索したいときは、.find()の条件に以下を指定します。

# and条件のリスト
cond_l = [
  # age > 20
  {"age": {"$gt": 20} },
  # languageにEnglishかJapaneseを含む
  {"language": {"$in": ["English", "Japanese"]} },
  # TOEFL のフィールドを持つ
  {"TOEFL": {"$exist": True} },
  # nameにTanakaを含む('/'を使わない)
  {"name": {"$regex": "Tanaka"} }
]

# 条件のANDを取る
cond = {"$and": cond_l}

db.collection.find(cond)

注意点として、pymongoで正規表現を使用する際は/を使いません。pythonから操作する際は気を付けましょう。

更新

基本

shellでは以下が基本操作です。

db.collection.update({条件}, {更新演算子: {更新内容}})

更新演算子には多くの場合$setが使われ、「条件」に合致するドキュメントを「更新内容」で更新します。namehogeのドキュメントのage25に更新するとき、pymongoでは

update({"name": "hoge"}, {"$set": {"age": 25}}) 

のように記述します。更新するフィールドが複数ある場合は、「更新内容」に複数条件を並列して記述できます↓

{"$set": {"name": "Suzuki", "age": 25} }

更新演算子は必ず指定してください。以下のように書いてしまうと、該当するドキュメントを「更新内容」で上書きしてしまいます。

db.collection.update({条件}, {更新内容})

主な更新演算子は以下です。

演算子 type 概要 mongo shellでの例
$set Fields 指定したフィールドに値をセットする(なければ追加する) {$set: {age: 25}}
$unset Fields 指定したフィールドを削除する {$unset: {name: ""}}
$pop Array 指定したフィールドの配列の先頭または末尾を一つ削除する {$pop: {tags: -1}}
$push Array 指定したフィールドの配列に値を追加する {$push: {tags: "test"}}

更新演算子の一覧は以下のページで確認できます。Arrayの操作に関する演算子は使いこなせば色々なことができそうです。

docs.mongodb.com

複数ドキュメントの更新

shellによる操作では、update()ヒットした最初のドキュメントのみ更新します。これはpymongoでも同様です。複数更新するには、以下のようにoptionにmulti:trueを指定する必要があります。

db.collection.update({条件}, {$set: {更新内容}, {multi:true}}

pymongoでは以下のようにオプションを記述します。

db.collection.update({"field":"value"}, multi=True)

ただし、pymongoではupdate()は非推奨となっています。更新ドキュメント対象の意図を明確にするために、update_one()またはupdate_many()の使用を推奨されています。複数更新する場合はupdate_many()を使用しましょう。(mongoDBのshellにもupdateOne, updateManyがあるので、そちらを使うのが無難かもしれません)

Updateメソッドに関するMongoDBのドキュメントは以下で見ることができます。

docs.mongodb.com

削除

基本

以下のコマンドで、条件にマッチするドキュメントの削除ができます。

db.collection.remove({条件})

namehogeのドキュメントを削除する際のpymongoでのコマンドは以下になります。

db.collection.remove({"name": "hoge"})

複数ドキュメントの削除

remove()デフォルトで複数ドキュメントを削除するように動作します。条件にマッチした最初の一件のみ削除したい場合は、オプションとして{justOne: true}を指定できます。

db.collection.remove({条件}, {justOne:true})

pymongoではオプションの引数はmultiで指定します。

db.collection.remove({"field":"value"}, multi=False)

これも、削除したい件数の意図を明確にするためにdelete_one(), delete_many()が用意されています。(対応するmongo shellコマンドはdeleteOne(), deleteMany()です)特に理由がなければremoveは使わないようにしたほうが無難かもしれません。

その他使いそうなコマンド

ドキュメント追加

collectionにドキュメントを追加します。追加したいドキュメントはdict形式で指定します。

db.collection.insert({追加したいドキュメント})

件数取得

条件にマッチするドキュメントの件数を取得できます。

db.collection.find({条件}).count()

collection削除

指定したcollectionを削除します。

db.collection.drop()

collectionに対する他のshell コマンドは以下で確認できます。

docs.mongodb.com

pymongoのdocumentationも以下サイトで検索すると大体出てきます(めんどくさくなってきた)

pymongo.readthedocs.io

まとめ

主なmongo shellコマンドとpymongoでの使用法を調べました。MongoDBの公式ドキュメントは見やすくて助かります。NoSQLから入ってしまったのでいずれはRDBMSも学びたいところです。

参考

pymongoを使った様々な検索条件(AND/OR/部分一致/範囲検索) - Qiita

こんな時どうする? MongoDBクエリ逆引きリファレンス - Qiita

MongoDB超入門 - Qiita