スキップしてメイン コンテンツに移動

pymongoとMongoDBでNo SQLが楽しくなる!

はじめに

Python + pymongoでMongoDBにアクセスする方法を解説します。MongoDBは世界的に人気のNoSQL DBで、DBMSをランキングしているDB-Enginesでは、Oracle、MySQLなどに次いで、5位になっています。

この記事を書くにあたって使用した環境は、以下の通りです。

Python 3.7
pymongo-3.10.1
MongoDB 4.2

前提データ

users.insert_one({ "id": 1, "name": "山田 太郎", "age": 20 })
users.insert_one({ "id": 2, "name": "山田 次郎", "age": 25 })
users.insert_one({ "id": 3, "name": "山田 三郎", "age": 40 })
users.insert_one({ "id": 4, "name": "鈴木 一郎", "age": 40 })
users.insert_one({ "id": 5, "name": "鈴木 次郎", "age": 60 })
id name age
1 山田 太郎 20
2 山田 次郎 25
3 山田 三郎 40
4 鈴木 一郎 40
5 鈴木 次郎 60

接続

pymongoでMongoDBには、次のように記述します。

from pymongo import MongoClient

client = MongoClient("mongodb://user:password@localhost:27017")

# DB接続(存在しない場合は作成)
db = client["testdb"]

# コレクションに接続(存在しない場合は作成)
users = db["users"]

検索条件を指定

条件指定はfind関数の引数で指定する

コレクションから条件指定でデータを抽出する場合は、次のように書きます。RDBで言うWHERE句の部分です。

results = users.find({ 'age': 40 })

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }

AND条件で複数条件を指定する

複数のAND条件を指定する場合は、次のように$andの中に条件をリストで渡します。

results = users.find(filter={'$and': [ {'name':'ユーザ3'}, {'age':40} ] })

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }

OR条件で複数条件を指定する

OR条件もANDと同じように、$orの中に条件をリストで渡します。

results = users.find(filter={'$or': [ {'name':'ユーザ1'}, {'age':40} ] })

▪️ 実行結果

{ id: 1, name: 山田 太郎, age: 20 }
{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }

AND・OR条件が混在するパターン

ANDとOR条件が混在するようなケースも、次のように記述して検索できます。

results = users.find(filter={'$or': [ 
    { '$and': [ {'name': "ユーザ1"}, {'age': 20} ] },
    { '$and': [ {'name': "ユーザ5"}, {'age': 60} ] },
  ]})

▪️ 実行結果

{ id: 1, name: 山田 太郎, age: 20 }
{ id: 5, name: 鈴木 次郎, age: 60 }

あまり条件が複雑になると可読性や性能に影響するので、効率的なデータアクセスができるモデル設計を心がけましょう!

部分一致で検索する

部分一致は、正規表現で書きます。正規表現で検索できるので、複雑な文字列検索もシンプルに書けそうです。

results = users.find(filter={'name':{'$regex':'鈴木|次郎'}})

▪️ 実行結果

{ id: 2, name: 山田 次郎, age: 25 }
{ id: 4, name: 鈴木 一郎, age: 40 }
{ id: 5, name: 鈴木 次郎, age: 60 }

範囲検索「○○以上($gte)」

範囲検索はそれぞれ以下のように書きます。MongoDBでの範囲指定の書き方は、残念ながらRDBのSQLに比べ少し見にくいです。

次のように書くと「年齢 ≧ 40」のような条件で検索できる。

results = users.find(filter={'age':{'$gte': 40}})

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }
{ id: 5, name: 鈴木 次郎, age: 60 }

範囲検索「○○以下($lte)」

「年齢 ≦ 40」のように検索する場合は、次の通り。

results = users.find(filter={'age':{'$lte': 40}})

▪️ 実行結果

{ id: 1, name: 山田 太郎, age: 20 }
{ id: 2, name: 山田 次郎, age: 25 }
{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }

範囲検索「○○より上($gt)」

「年齢 > 40」の場合。

{ id: 5, name: 鈴木 次郎, age: 60 }

▪️ 実行結果

{ id: 1, name: 山田 太郎, age: 20 }
{ id: 2, name: 山田 次郎, age: 25 }

範囲検索「○○より下($lt)」

「年齢 < 40」の場合。

results = users.find(filter={'age':{'$lt': 40}})

▪️ 実行結果

{ id: 1, name: 山田 太郎, age: 20 }
{ id: 2, name: 山田 次郎, age: 25 }

sort (ソート・並び替え)

並び替えは、そのままsort関数を使う。第1引数にはソートを行う項目名、第2には、昇順pymongo.ASCENDING、降順pymongo.DESCENDINGのどちらかを指定する。第2引数を省略した場合は昇順ソートになる。

results = users.\
  find().\
  sort("id", pymongo.DESCENDING)

▪️ 出力結果

{ id: 5, name: ユーザ5, age: 60 }
{ id: 4, name: ユーザ4, age: 40 }
{ id: 3, name: ユーザ3, age: 40 }
{ id: 2, name: ユーザ2, age: 25 }
{ id: 1, name: ユーザ1, age: 20 }

データの登録

MongoDBにデータを登録する時は、insert_oneまたはinsert_manyを使用します。

1件データを登録 (insert_one)

insert_oneは、データを1件を登録する関数です。

users.insert_one({ "id": 1, "name": "山田 太郎", "age": 20 })

複数件のデータを一括登録 (insert_many)

insert_manyは、リストで登録するデータを指定できます。複数件のデータをまとめて登録したい場合は、こちらの関数を使用します。

users.insert_many([
  { "id": 1, "name": "鈴木 一郎", "age": 60 },
  { "id": 2, "name": "鈴木 次郎", "age": 40 },
  { "id": 3, "name": "鈴木 三郎", "age": 30 }
])

データの更新

データの更新は、update_oneまたはupdate_manyを使用します。

1件データを更新 (update_one)

条件に一致する先頭1件のデータを更新する場合は、update_oneを使用します。次のサンプルコードは、年齢を40→50歳に更新する例です。

users.update_one({"age": 40}, { "$set": { "age": 50 }})

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }
↓ 更新後 ↓ 
{ id: 3, name: 山田 三郎, age: 50 }
{ id: 4, name: 鈴木 一郎, age: 40 }

上の結果から見て取れるように、条件に一致するデータが複数件あっても、update_one関数は見つかった先頭1件目のデータしか更新しません。

複数のデータを更新 (update_many)

条件に一致するデータを全て更新する場合は、update_manyを使用します。

users.update_many({"age": 40}, { "$set": { "age": 50 }})

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }
↓ 更新後 ↓ 
{ id: 3, name: 山田 三郎, age: 50 }
{ id: 4, name: 鈴木 一郎, age: 50 }

上記以外に、update関数を使用する方法もあります。

データの削除

データの更新は、delete_oneまたはdelete_manyを使用します。

1件データを削除 (delete_one)

条件に一致する先頭1件のデータを削除する時は、delete_oneを使用します。

users.delete_one({"age": 40})

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }
↓ 削除後 ↓ 
{ id: 4, name: 鈴木 一郎, age: 40 }

複数件のデータを削除 (delete_many)

条件に一致するデータを全て削除する時は、delete_manyを使用します。

users.delete_many({"age": 40})

▪️ 実行結果

{ id: 3, name: 山田 三郎, age: 40 }
{ id: 4, name: 鈴木 一郎, age: 40 }
↓ 削除後 ↓ 
なし

全てのドキュメントを削除 (drop)

コレクション内のすべてのドキュメントを削除する時は、dropを使用します。

users.drop()

まとめ

No SQLのMongoDBは、テーブル(コレクション)の構造が後から拡張できて、パッと使えて便利です。

コメント

このブログの人気の投稿

axiosの使い方まとめ (GET/POST/例外処理)

axiosの使い方まとめ (GET/POST/例外処理)最近何かとよく使うJavaScriptでAJAX通信を行うaxiosについて、簡単に使い方をまとめました。GETリクエストをaxiosで送るまずはGETリクエストをaxiosで送る方法です。const res =await axios.get('/users') console.log(res.data)分割代入の記法を使うと、以下のようにも書けますconst{data}=await axios.get('/users') console.log(data)クエリパラメータ (URLパラメータ)を指定クエリパラメータを指定する方法は2つあります。1つ目は、axios.getに指定するURLに直接記述する方法です。axios.get('/user?id=123')2つめは、axios.getの第2引数に、オプション指定する方法です。axios.get('/user',{ params:{ id:123}})POSTリクエストをaxiosで送る次はPOSTリクエストをaxiosで送る方法です。JSON形式でPOSTするJSON形式でPOSTする場合は、axios.postの第2引数に、送信するデータをJavaScriptオブジェクトで指定します。const res =await axios.post('/user',{ id:123, name:'Yamada Tarou'})application/x-www-form-urlencoded形式でPOSTするapplication/x-www-form-urlencoded形式でPOSTする場合は、URLSearchParamsを使います。var params =newURLSearchParams() params.append('id',123) params.append('name','Yamada Tarou')const res =await axios.post('/user', params)スポンサーリンク axios でファイルをアップロードする画像などのファイルを、…

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決する

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決するタイトルの通りですが、Windows 8 以降では Windows Form アプリケーションで、コントロールの ImeMode に Katakana や KatakanaHalf を設定しても、カタカナになってくれません。なぜ ImeMode が効かないのか?Windows 8 以降、IME Mode の切り替えは、ユーザー単位で切り替わるようになった為、アプリから IME Mode 制御が出来ないようになりました。
(IME をON にした場合、常に ひらがな モードになます)※ Windows 7までは、IME Modeの切り替えはアプリ単位で行われていた為、問題なくアプリから IME制御が行えました。スポンサーリンク 対処方法Windows 8 以降、IMEの制御は、InputScope クラスの利用が推奨されています。
しかし、InputScope クラスは、WPF、Windows ストアアプリでしか使えない為、Windows Formアプリでは使用できません。
(Windows Form はもう使うな!という事でしょうか (涙) )結論としては、コントールパネルの設定で、IMEの制御をユーザ単位から アプリ単位に変更する事ができます。
これで、Windows Formアプリでも 従来通りIMEの制御を行う事が出来ます。おわりにこの方法だと、アプリをインストールする端末すべてに設定が必要となり、とっても面倒です。。。
しかし、今の所これしか方法がない状態です。
これからは Windows Formではなく、WPFや Windows ストアアプリで作れという事ですかね (^^;)

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]MailKitを使ってメールを送るサンプルコードです。(C#)UTF8/iso-2022-jpのエンコーディング指定、GMail/YahooのSMTPサーバで送るなど、4つのサンプルコードでMailKitの使い方を紹介します。MailKitって何?2017年に.NET標準のSystem.Net.Mail.SmtpClientが廃止予定となり、Microsoftより今後はオープンソースライブラリである、MailKitに置き換えるとアナウンスがありました。既にSmtpClientは非推奨になっており、今後は廃止されていきます。現在、SmtpClientを使用したソースコードには、Visual StudioからMailKitを使うよう警告が出るようになっています。さっそく、MailKitを使ってメールを送信するサンプルコードを作っていきます。UTF8でメールを送信文字エンコーディングを、UTF8でメールを送信するサンプルコードです。
MailKitは、デフォルトの文字エンコーディングがUTF8なっている為、シンプルなコードでメールを送信する事ができます。var host ="<smtp server name>"; var port =25;// or 587using(var smtp =new MailKit.Net.Smtp.SmtpClient()){//SMTPサーバに接続する smtp.Connect(host, port, MailKit.Security.SecureSocketOptions.Auto);//認証が必要な場合は、以下のコメントを解除//smtp.Authenticate("<id>", "<password>");//送信するメールを作成する var mail =new MimeKit.MimeMessage(); var builder =new MimeKit.BodyBuilder(); mail.From.Add(new MimeKit.MailboxAddress("",&quo…