#当記事の記載範囲
この記事ではPythonでmongodbに接続してから、update(SQLで言ってもupdate)の使い方について記載します。
内容としては以下になります。
- update_one
- update_many
- replace_one
- find_one_and_update
- find_one_and_replace
mongodbの起動やpymongoのインストール方法については以下の記事をご覧いただければ幸いです。
https://qiita.com/bc_yuuuuuki/items/2b92598434f6cc320112
#準備データ
mongodbの準備データは以下のとおりです。
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> show collections
employee
log
salary
> db.salary.find()
{ "_id" : ObjectId("5d4acf84de925ae437e2c123"), "name" : "山田", "salary" : 300000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c124"), "name" : "佐藤", "salary" : 400000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000 }
{ "_id" : ObjectId("5d4b81a4de925ae437e2c126"), "name" : "山田", "salary" : 500000 }
#Pythonでupdateを使ってみる
まずはupdate_oneから使ってみます。
これから紹介する内容は基本的には同じ内容になっています。
第一引数のfileterに更新条件を設定し、第二引数のupdateやreplaceに更新する内容を設定します。
##update_oneの使い方
from pymongo import MongoClient
class MongoUpdateSample(object):
def __init__(self, dbName, collectionName):
self.client = MongoClient()
self.db = self.client[dbName]
self.collection = self.db.get_collection(collectionName)
def find(self, projection=None,filter=None, sort=None):
return self.collection.find(projection=projection,filter=filter,sort=sort)
def update_one(self, filter, update):
return self.collection.update_one(filter,update)
def update_many(self, filter, update):
return self.collection.update_many(filter,update)
def replace_one(self, filter, replacement):
return self.collection.replace_one(filter, replacement)
def find_one_and_replace(self, filter, replacement):
return self.collection.find_one_and_replace(filter, replacement)
mongo = MongoUpdateSample('test', 'salary')
find = mongo.find()
for doc in find:
print(doc)
update = mongo.update_one({'name':'山田'},{'$set':{'salary':600000}})
print('更新件数:' + str(update.matched_count))
find = mongo.find()
for doc in find:
print(doc)
やっている内容としては更新前のデータを表示し、nameフィールドが'山田'の給料を600000に更新する。
更新完了後に更新件数と更新後のデータを表示するというものです。
実行結果
--------------------更新前--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}
更新件数:1
--------------------更新後--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 600000}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}
はい。今回使ったのはupdate_oneなので'name'フィールドが'山田'となっているデータ2件のうち、1件が更新されています。
正直、今のところあまり利用場面が思い浮かんでいません。。
気になるのは'salary'フィールドの値ですね。
今回用意したデータはmongodbのコンソールから登録を行いました。
その際、'salary'フィールドには整数で値を設定しているのですが、pymongoのfindでデータを取得するとfloatになっていることが分かります。
また、pymongoのupdate_oneで更新した整数の値は、findで取得するとint型になっています。
このあたり、キャストなど注意する必要がありそうです。
ちなみに更新後のデータをmongodbのコンソールで確認すると全て整数で表示されています。
> db.salary.find()
{ "_id" : ObjectId("5d4acf84de925ae437e2c123"), "name" : "山田", "salary" : 600000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c124"), "name" : "佐藤", "salary" : 400000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000 }
{ "_id" : ObjectId("5d4b81a4de925ae437e2c126"), "name" : "山田", "salary" : 500000 }
##update_manyの使い方
update_manyの使い方はほとんどupdate_oneと同じです。
update_oneを呼び出している部分をupdate_manyに変更し、更新するパラメーターも変更しました。
mongo = MongoUpdateSample('test', 'salary')
find = mongo.find()
print('--------------------更新前--------------------')
for doc in find:
print(doc)
update = mongo.update_many({'name':'山田'},{'$set':{'salary':7777777}})
print('更新件数:' + str(update.matched_count))
find = mongo.find()
print('--------------------更新後--------------------')
for doc in find:
print(doc)
実行結果
--------------------更新前--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 600000}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}
更新件数:2
--------------------更新後--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 7777777}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 7777777}
'name'フィールドが'山田'と一致する全てのデータの'salary'が更新されました。
##replace_oneの使い方
これはドキュメント(RDBで言うところのレコード)を丸々入れ替えるという内容になります。
mongodbにより一意に採番される「_id(主キー)」以外のフィールドを新しいフィールドに入れ替えることができます。
SQLには無い構文ですね。早速やってみましょう。
mongo = MongoUpdateSample('test', 'salary')
find = mongo.find()
print('--------------------更新前--------------------')
for doc in find:
print(doc)
update = mongo.replace_one({'name':'山田'},{'fullname':'山田 太郎','rank':5,'profession':'Engineer','position':'Manager'})
print('更新件数:' + str(update.matched_count))
find = mongo.find()
print('--------------------更新後--------------------')
for doc in find:
print(doc)
実行結果
--------------------更新前--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 7777777}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 7777777}
更新件数:1
--------------------更新後--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'fullname': '山田\u3000太郎', 'rank': 5, 'profession': 'Engineer', 'position': 'Manager'}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 7777777}
全角スペースが文字コードとして表示されたのが解せないですが、'_id'が'5d4acf84de925ae437e2c123'のデータが設定した値に置き換わっていることを確認できました。
##find_one_and_updateの使い方
これは名前のとおりfind_oneをしてupdateを行うというものです。
動きとしては関数の戻り値として、更新前のデータが取得できます。
mongo = MongoUpdateSample('test', 'salary')
find = mongo.find()
print('--------------------更新前--------------------')
for doc in find:
print(doc)
update = mongo.find_one_and_update({'name':'山田'},{'$set':{'salary':800000}})
print(type(update))
print(update)
find = mongo.find()
print('--------------------更新後--------------------')
for doc in find:
print(doc)
実行結果
--------------------更新前--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000}
<class 'dict'>
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
--------------------更新後--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 800000}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000}
動きとしては、find_oneで見つかったデータに対してupdateを行うようなので、更新件数は一件だけとなるようです。
##find_one_and_replaceの使い方
これも名前のとおり、find_oneをして、replaceを行うというものです。
find_one_and_updateと同じく、更新前のデータを取得できます。
mongo = MongoUpdateSample('test', 'salary')
find = mongo.find()
print('--------------------更新前--------------------')
for doc in find:
print(doc)
update = mongo.find_one_and_replace({'name':'山田'},{'fullname':'山田 太郎','rank':5,'profession':'Engineer','position':'Manager'})
print(type(update))
print(update)
find = mongo.find()
print('--------------------更新後--------------------')
for doc in find:
print(doc)
実行結果
--------------------更新前--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 800000}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000}
<class 'dict'>
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 800000}
--------------------更新後--------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'fullname': '山田\u3000太郎', 'rank': 5, 'profession': 'Engineer', 'position': 'Manager'}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000}
replaceの前の情報を取得することが出来ました。
#感想
更新のやり方が普通のSQLにはないreplaceなどのがあり、新鮮でした。
更新のやり方は完全にmongodbのコマンドとパラメーターの渡し方が同じで分かり易かったです。
#関連記事