初めましての方は初めまして.そうでない方はいつも読んでいただきありがとうございます.
研究で MongoDB を利用する事になり,その操作のために PyMongo を利用したのですが,今回の記事ではその基本操作を自分のメモ的な感じでまとめたいと思います.
項目 | バージョン | 説明 |
---|---|---|
Python |
3.10.12 |
プログラミング言語 |
PyMongo |
4.6.1 |
PythonでMongoDBを操作するためのライブラリ |
MongoDB |
7.0.5 |
データベース |
その他 | - | 私の環境ではDockerを利用していますが,他の環境でも同じ操作になると思います. |
本記事はPyMongo 4.6.1 Documentationを参考にして作成したものです.言うまでもなく公式ドキュメントの方が詳しいので,詳細が気になる方はそちらを参照されて下さい.(英語)
とりあえず動かせれば良いという方や,英語のドキュメントに抵抗のある方,そんな方に向けた記事となります.
MongoDBとのコネクション
from pymongo import MongoClient
with MongoClient(
host='host_name',
port=27017, # port番号を変更している場合はそれに合わせる
username='root', # 今回は研究のみで用い,外部からのアクセスは無いため,rootでログイン
password='root_password') as client:
# データベースの選択
database = client['database_name']
# コレクションの選択
collection = database['collection_name']
参考
データの追加
- 1件のデータを追加する場合
insert_one
collection.insert_one(*data)
- 複数件のデータを追加する場合
insert_many
collection.insert_many(*data)
参考
データの取得
- 1件のデータを取得する場合
find_one
collection.find_one()
- 複数件のデータを取得する場合
find
collection.find() # 取得したデータの確認 for item in collection.find(): print(item)
参考
その他
本章では,先述の基本操作以外で(個人的に)よく使うが,調べても(感覚として)あまり検索にヒットしなかったものをまとめておきます.
条件検索
- 例1) 条件に一致するデータを取得
find_with_query
query = { # 'id'が12345のデータを取得 'id': 12345 } response = collection.find(filter=query)
- 例2) 条件に当てはまるデータを取得
find_with_query
query = { # 'count'が20以上のデータを取得 'count': {'$gte': 20} } response = collection.find(filter=query)
- 例3) 複数の条件を組み合わせたデータの取得
find_by_multiple_query
query = { # 'id'がtarget_idsに含まれ,'count'が25以上30以下のデータを取得 'id': {'$in': target_ids}, 'count': {'$gte': 25, '$lte': 30} } response = collection.find(filter=query)
演算子は以下のものが利用できます.
演算子 | 記号 | 説明 |
---|---|---|
$eq | == |
指定した値と等しい値を照合する. |
$gt | > |
指定した値より大きい値を照合する. |
$gte | >= |
指定した値以上の値を照合する. |
$in | in |
配列で与えられた値のいずれかと一致するものを照合する. |
$lt | < |
指定した値より小さい値を照合する. |
$lte | <= |
指定した値以下の値を照合する。 |
$ne | != |
指定した値と等しくないすべての値を照合する. |
$nin | not in |
配列で指定された値のどれにも一致しないものを照合する. |
参考
取得する要素の選択
projection = { # 'id'と'key2'のみ取得
'id': True,
'key1': False,
'key2': True,
'key3': False
}
# 表示するもののみを選択することも可能
# projection = { # 'id'と'key2'のみ取得
# 'id': True,
# 'key2': True
# }
# ただし,Falseも明示的に指定する場合は全てのキーについて記述する必要あり
# 以下のような指定ではエラーが発生する
# projection = { # 'id'と'key2'のみ取得
# 'id': True,
# 'key2': True,
# 'key3': False
# }
collection.find(projection=projection)
使い方を調べる中で部分的にFalse
を指定すること(コードブロック内の注意書きのような指定方法)も可能であるという記事も見かけましたが,少なくとも既述の私の環境では確認できませんでした.また,公式ドキュメント内でも
a list of field names that should be returned in the result set or a dict specifying the fields to include or exclude. If projection is a list “_id” will always be returned. Use a dict to exclude fields from the result (e.g. projection={‘_id’: False}).
というように述べられており,部分的に指定できるという点は疑わしいと考えています.(指定できるという方がいらっしゃれば,環境を教えて頂きたいです.)
参考
取得する件数の指定
# 100件を上限としてデータを取得
response = collection.find().limit(100)
参考
ユニークな値を取得
# 指定したkeyのユニークなvalueを取得
response = collection.find().distinct(key)
参考
最後に
ここまでお読みいただいてありがとうございました.
MongoDBを使用し始めて1週間も経たずに書いている記事で,私自身まだまだ学ぶべきことは多いと感じています.同じような方の助けになれば幸いです.
MongoDBを使いこなしている方は本記事の内容に誤りやもっとこうすべきという部分があれば,是非ご教示頂けますと幸いです.
おまけ
PyMongoとは若干外れますが,WebAPIでJsonファイル形式で取得したデータを格納するときに作成した関数を貼っておきます.
私の知識不足なのかもしれませんが,入れ子構造をもつJson形式のデータを入れ子構造を持たないJson形式のデータに変換する(?)ライブラリが見当たらず,そのままではMongoDBに格納できないので自作した関数です.(もしライブラリをご存知の方がいらっしゃればご教示頂きたいです.)
# 以下のような変換をおこなう
{
`id`: 12345,
`key1`: value_1,
`key2`: {
'sub_key1': sub_value_1,
'sub_key2': [
{'sub_sub_key1': sub_sub_value1},
{'sub_sub_key2': sub_sub_value2}
],
'sub_key3': sub_value_3
}
}
==> {
`id`: 12345,
`key1`: value_1,
`key2_sub_key1`: sub_value_1,
`key2_sub_key2_sub_sub_key1`:sub_sub_value1,
`key2_sub_key2_sub_sub_key2`:sub_sub_value2,
`key2_sub_key3`: sub_value_3
}
def flatten_json(data, parent_key: str='', sep: str='_'):
'''
Jsonデータをフラットにする関数
Args:
data: Jsonデータ
parent_key (str): 上位のキー
sep (str): キーを分割する記号
Returns:
dict: 入れ子構造を持たない辞書型データ
'''
items = {}
if isinstance(data, dict):
for key, value in data.items():
new_key = parent_key + sep + key if parent_key else key
items.update(flatten_json(value, new_key, sep=sep))
elif isinstance(data, list):
for i, value in enumerate(data):
new_key = parent_key + sep
items.update(flatten_json(value, new_key, sep=sep))
else:
items[parent_key] = data
return items
上記のコードは動作を保証するものではありません.コードを良く理解した上で,ご自身の責任で利用されてください.