
筆者が趣味で作成するシステムは、基本的に超小規模システムのため、サーバサイドプログラムをPythonで書き、フレームワークでFlaskやBottleを利用するパターンがほとんどです。
Webプログラムを書いていると、サーバサイドでデータを保持したい場面によく出くわします。
そんな時、簡単にJSONファイル出力しておけば読み込みも簡単で捗っていました。
ある日ふと、JSONファイルを保存するみたいに手軽にデータ保存できるデータベースってないのかなと思って調べました。それがMongoDBとの出会いでした。
データベースを利用したほうが当然、JSONファイル出力するよりも効率的かつ安全にデータ保存が可能です。それ以来、JSONファイルに保存するのはやめて、MongoDBを利用するようになりました。
PythonでMongoDBを利用するには、Pythonのモジュール「pymongo」を利用しますが、システム作成の度に使い方を忘れ、過去のプログラムを見たり、Web検索したりしていました。
本記事では、またpymongoの使い方を忘れるであろう将来の筆者と検索で来られた方のために、pymongoの使い方をまとめます。
目次
MongoDBの基本
まず、MongoDBの基本について記載しておきます。(これもよく忘れます)
例として、各地の気象データを保存する場合を考えてみます。
データベース
データベースです。後述する、コレクション、ドキュメント、フィールドが含まれます。
気象データの例として、「weather」というデータベースを作成します。
コレクション
後述するドキュメントの集まりです。複数のドキュメントが入ります。
気象データの例では、東京コレクション「tokyo」と大阪コレクション「osaka」を作成します。
ドキュメント
一つのデータです。
気象データの例では、下記のようになります。
東京コレクションの例です。下記は単一のドキュメントです。
{
"date": "2023-11-20 14:00",
“temp”: 15,
“humi”: 47
}
コレクションには、複数のドキュメントを保存できます。
{
"date": "2023-11-20 14:00",
“temp”: 15,
“humi”: 47
},
{
"date": "2023-11-20 15:00",
“temp”: 14,
“humi”: 45
}
フィールド
ドキュメントの構成要素です。
東京コレクションの例では、「date」「temp」「humi」がフィールドです。
フィールドは、複数のドキュメント間で一貫性を保つ必要はありません。
例えば、上記では、「date」「temp」「humi」を保存していますが、次のタイミングから気圧「atm」を保存してもオッケーです。
pymongoによるMongoDB接続
インストール方法
まず、pymongoモジュールを導入します。
pip install pymongo
DB、コレクション作成
DB、コレクションは、データ保存、取得するタイミングで自動的に作成されますので、DB、コレクション作成のための操作は不要です。
DB接続方法
MongoClientメソッドでDB接続し、得られたclient[“DB名”][“コレクション名”]でコレクションを得ます。
下記は、MongoDBサーバ(ホスト:mongo、ポート:27017、username:root、password:example)に接続し、データベース(weather)のコレクション(tokyo、osaka)を得る例です。
from pymongo import MongoClient
client = MongoClient('mongo', 27017, username='root', password='example')
col_tokyo = client['weather']['tokyo']
col_osaka = client['weather']['osaka']
pymongoの主要メソッド一覧
これだけ使えれば、ほぼすべての操作が可能と言える主要メソッドを記載します。
insert_one()
ドキュメントを一つ追加するためのメソッドです。
気象データを一つ追加する例です。
add_data = {"date": "2023-11-20 16:00", "temp": 13, "humi": 43}
col_tokyo.insert_one(add_data)
insert_many()
複数のドキュメントを追加するためのメソッドです。ドキュメントのリストを引数に渡します。
気象データを複数追加する例です。
add_data = [
{"date": "2023-11-20 17:00", "temp": 12, "humi": 42},
{"date": "2023-11-20 18:00", "temp": 11, "humi": 41},
{"date": "2023-11-20 19:00", "temp": 10, "humi": 40},
{"date": "2023-11-20 20:00", "temp": 9, "humi": 40},
{"date": "2023-11-20 21:00", "temp": -100, "humi": 40},
{"date": "2023-11-20 22:00", "temp": -100, "humi": 40},
{"date": "2123-11-20 23:00", "temp": 8, "humi": 40}
]
col_tokyo.insert_many(add_data)
find_one()
コレクションの中から、条件に合ったデータを一つ取得するメソッドです。
条件に合うデータが、複数ある場合でも最初に見つかった一つを返します。
気象データから、2023年11月20日 17時のデータを取得する例です。
fi = {"date": "2023-11-20 17:00"}
data_17 = col_tokyo.find_one(fi)
print(data_17)
fiは条件を指定するフィルタで、「date」が「2023-11-20 17:00」と一致するデータを取得します。
find()
コレクションの中から、条件に合ったデータを複数取得するメソッドです。find_many()ではありません。
本メソッドは、リストではなくイテレータを返すことに注意が必要です。
気象データから、気温が13度未満のデータを取得する例です。
fi = {"temp": {"$lt": 13}}
data_lt_13 = col_tokyo.find(fi)
for d in data_lt_13:
print(d)
フィルタには、「temp」が「13」度より小さいという条件を指定しています。
フィルタを空にすると全データが取得できます。
data_all = col_tokyo.find()
for d in data_all:
print(d)
補足:戻り値のイテレータをリストに変換したい場合は次のようにします。
data_all = col_tokyo.find()
data_all_list = [d for d in data_all]
update_one()
コレクションの中から、条件に合ったデータを一つ更新するメソッドです。
条件に合うデータが、複数ある場合でも最初に見つかった一つを更新します。
気象データのうち、2023年11月20日 20時の湿度を「35」に変更する例です。
fi = {"date": "2023-11-20 20:00"}
ud = {"$set": {"humi": 35}}
col_tokyo.update_one(fi, ud)
個別のフィールドを更新するために、「$set」コマンドを指定します。
次のように、一度に複数のフィールドを更新することも可能です。
fi = {"date": "2023-11-20 20:00"}
ud = {"$set": {"temp": 8, "humi": 35}}
col_tokyo.update_one(fi, ud)
update_many()
コレクションの中から、条件に合ったデータを複数更新するメソッドです。
気温が11度以上の場合、快適フラグを追加する例です。この例では、新しいフィールドを追加しています。
fi = {"temp": {"$gte": 11}}
ud = {"$set": {"comfortable": True}}
col_tokyo.update_many(fi, ud)
delete_one()
コレクションの中から、条件に合ったデータを一つ削除するメソッドです。
条件に合うデータが、複数ある場合でも最初に見つかった一つを削除します。
間違えて、100年後の2123年11月20日 23時のデータを入力してしまったので削除します。
fi = {"date": "2123-11-20 23:00"}
col_tokyo.delete_one(fi)
delete_many()
コレクションの中から、条件に合ったデータを複数削除するメソッドです。
センサーの不具合で、気温がマイナス100度になってしまったデータを削除します。
fi = {"temp": -100}
col_tokyo.delete_many(fi)
指定可能なフィルタ一覧
フィルタの条件は、以下が指定可能です。
「$lt」(less than) 未満
「$gt」(greater than) より大きい
「$lte」(less than or equal to) 以下
「$gte」(greater than or equal to) 以上
「$ne」(not equal) 一致しない
フィルタは、And条件で複数指定も可能です。
fi = {"temp": {"$lt": 13, "$gte": 11}}
data_11_13 = col_tokyo.find(fi)
for d in data_11_13:
print(d)
Or条件を利用したい場合は、下記のようにします。
fi = {"$or": [{"temp": {"$gt": 13}}, {"temp": {"$lt": 11}}]}
data_11_13 = col_tokyo.find(fi)
for d in data_11_13:
print(d)
コメント