MongoDB完全ガイド
MongoDB完全ガイド
Section titled “MongoDB完全ガイド”MongoDBの実践的な使い方を、実務で使える実装例とベストプラクティスとともに詳しく解説します。
1. MongoDBとは
Section titled “1. MongoDBとは”MongoDBの特徴
Section titled “MongoDBの特徴”MongoDBは、NoSQLドキュメントデータベースです。JSONライクなドキュメント形式でデータを保存します。
MongoDBの特徴 ├─ スキーマレス(柔軟なデータ構造) ├─ 水平スケーリングが容易 ├─ 高速な読み書き ├─ 豊富なクエリ機能 └─ 集約パイプラインによる複雑な処理なぜMongoDBを選ぶのか
Section titled “なぜMongoDBを選ぶのか”MongoDBを選ぶべき場合:
- スキーマが頻繁に変更される
- 水平スケーリングが必要
- 高速な読み書きが必要
- 複雑な集約処理が必要
MongoDBを選ばないべき場合:
- トランザクションの整合性が重要(リレーショナルDBの方が適している)
- 複雑なJOINが必要(リレーショナルDBの方が適している)
2. MongoDBのインストールとセットアップ
Section titled “2. MongoDBのインストールとセットアップ”macOSでのインストール
Section titled “macOSでのインストール”# Homebrewを使用brew tap mongodb/brewbrew install mongodb-community
# サービスを開始brew services start mongodb-community
# MongoDBに接続mongoshLinuxでのインストール
Section titled “Linuxでのインストール”# Ubuntu/Debianwget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | sudo apt-key add -echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.listsudo apt-get updatesudo apt-get install -y mongodb-org
# サービスを開始sudo systemctl start mongodsudo systemctl enable mongod
# MongoDBに接続mongoshWindowsでのインストール
Section titled “Windowsでのインストール”- MongoDB公式サイトからインストーラーをダウンロード
- インストーラーを実行し、指示に従ってインストール
- MongoDB Compassまたはmongoshから接続
// データベースの作成と選択use myapp
// ユーザーの作成db.createUser({ user: "myuser", pwd: "mypassword", roles: [ { role: "readWrite", db: "myapp" } ]})
// 認証db.auth("myuser", "mypassword")3. 基本的な操作
Section titled “3. 基本的な操作”ドキュメントの挿入
Section titled “ドキュメントの挿入”// 単一ドキュメントの挿入db.users.insertOne({ name: "Alice", email: "alice@example.com", age: 30, tags: ["developer", "designer"], address: { city: "Tokyo", country: "Japan" }, created_at: new Date()})
// 複数ドキュメントの挿入db.users.insertMany([ { name: "Bob", email: "bob@example.com", age: 25 }, { name: "Charlie", email: "charlie@example.com", age: 35 }])ドキュメントの検索
Section titled “ドキュメントの検索”// すべてのドキュメントを取得db.users.find()
// 条件付き検索db.users.find({ age: { $gt: 25 } })
// プロジェクション(特定のフィールドのみ取得)db.users.find({}, { name: 1, email: 1 })
// ソートdb.users.find().sort({ age: -1 })
// リミットdb.users.find().limit(10)
// スキップdb.users.find().skip(10).limit(10)ドキュメントの更新
Section titled “ドキュメントの更新”// 単一ドキュメントの更新db.users.updateOne( { email: "alice@example.com" }, { $set: { age: 31 } })
// 複数ドキュメントの更新db.users.updateMany( { age: { $lt: 30 } }, { $set: { status: "junior" } })
// 置き換えdb.users.replaceOne( { email: "alice@example.com" }, { name: "Alice Smith", email: "alice@example.com", age: 31 })
// インクリメントdb.users.updateOne( { email: "alice@example.com" }, { $inc: { age: 1 } })
// 配列への追加db.users.updateOne( { email: "alice@example.com" }, { $push: { tags: "senior" } })ドキュメントの削除
Section titled “ドキュメントの削除”// 単一ドキュメントの削除db.users.deleteOne({ email: "alice@example.com" })
// 複数ドキュメントの削除db.users.deleteMany({ age: { $lt: 18 } })
// すべてのドキュメントの削除db.users.deleteMany({})4. インデックス
Section titled “4. インデックス”基本的なインデックス
Section titled “基本的なインデックス”// 単一フィールドインデックスdb.users.createIndex({ email: 1 })
// 複合インデックスdb.users.createIndex({ name: 1, age: -1 })
// ユニークインデックスdb.users.createIndex({ email: 1 }, { unique: true })
// テキストインデックス(全文検索)db.articles.createIndex({ title: "text", content: "text" })
// インデックスの確認db.users.getIndexes()
// インデックスの削除db.users.dropIndex({ email: 1 })インデックスの最適化
Section titled “インデックスの最適化”// クエリプランの確認db.users.find({ email: "alice@example.com" }).explain("executionStats")
// インデックスの使用状況を確認db.users.aggregate([ { $indexStats: {} }])5. 集約パイプライン
Section titled “5. 集約パイプライン”基本的な集約操作
Section titled “基本的な集約操作”// グループ化と集計db.orders.aggregate([ { $group: { _id: "$user_id", total_amount: { $sum: "$amount" }, order_count: { $count: {} }, avg_amount: { $avg: "$amount" } } }, { $sort: { total_amount: -1 } }])
// 結合($lookup)db.orders.aggregate([ { $lookup: { from: "users", localField: "user_id", foreignField: "_id", as: "user" } }, { $unwind: "$user" }, { $project: { order_id: "$_id", user_name: "$user.name", amount: 1 } }])
// フィルタリングdb.orders.aggregate([ { $match: { amount: { $gt: 100 }, status: "completed" } }, { $group: { _id: "$user_id", total: { $sum: "$amount" } } }])高度な集約操作
Section titled “高度な集約操作”// ウィンドウ関数($setWindowFields)db.sales.aggregate([ { $setWindowFields: { partitionBy: "$product_id", sortBy: { date: 1 }, output: { running_total: { $sum: "$amount", window: { documents: ["unboundedPreceding", "current"] } } } } }])
// ファセット検索db.products.aggregate([ { $facet: { "by_category": [ { $group: { _id: "$category", count: { $sum: 1 } } } ], "by_price": [ { $bucket: { groupBy: "$price", boundaries: [0, 100, 500, 1000, Infinity], default: "other" } } ] } }])6. シャーディング
Section titled “6. シャーディング”シャーディングの設定
Section titled “シャーディングの設定”// 設定サーバーの起動(mongod --configsvr)
// ルーターサーバーの起動(mongos --configdb config1:27019,config2:27019,config3:27019)
// シャードキーの設定sh.enableSharding("myapp")
// コレクションのシャーディングsh.shardCollection("myapp.orders", { user_id: 1, order_date: 1 })
// シャードの状態確認sh.status()シャーディング戦略
Section titled “シャーディング戦略”// 範囲シャーディング// - データが均等に分散されない可能性がある// - 範囲クエリが効率的
// ハッシュシャーディングsh.shardCollection("myapp.users", { _id: "hashed" })// - データが均等に分散される// - 範囲クエリが非効率的7. レプリカセット
Section titled “7. レプリカセット”レプリカセットの設定
Section titled “レプリカセットの設定”// プライマリサーバーの設定rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "mongodb1:27017" }, { _id: 1, host: "mongodb2:27017" }, { _id: 2, host: "mongodb3:27017" } ]})
// レプリカセットの状態確認rs.status()
// セカンダリサーバーからの読み取りdb.getMongo().setReadPreference("secondary")レプリカセットの選挙
Section titled “レプリカセットの選挙”// プライマリサーバーの確認rs.isMaster()
// 手動でのフェイルオーバー(テスト環境のみ)rs.stepDown()8. トランザクション
Section titled “8. トランザクション”トランザクションの使用
Section titled “トランザクションの使用”// セッションの開始const session = db.getMongo().startSession()
// トランザクションの開始session.startTransaction()
try { // 操作1 session.getDatabase("myapp").users.insertOne({ name: "Alice", email: "alice@example.com" }, { session })
// 操作2 session.getDatabase("myapp").orders.insertOne({ user_id: user_id, amount: 100 }, { session })
// コミット session.commitTransaction()} catch (error) { // ロールバック session.abortTransaction()} finally { session.endSession()}9. パフォーマンス最適化
Section titled “9. パフォーマンス最適化”クエリの最適化
Section titled “クエリの最適化”// インデックスの使用を確認db.users.find({ email: "alice@example.com" }).explain("executionStats")
// プロジェクションの使用(必要なフィールドのみ取得)db.users.find({}, { name: 1, email: 1 })
// バッチサイズの調整db.users.find().batchSize(100)// 接続文字列での設定mongodb://localhost:27017/myapp?maxPoolSize=10&minPoolSize=5
// 接続プールの監視db.serverStatus().connections10. セキュリティ
Section titled “10. セキュリティ”// ユーザーの作成db.createUser({ user: "admin", pwd: "admin_password", roles: [ { role: "userAdminAnyDatabase", db: "admin" }, { role: "readWriteAnyDatabase", db: "admin" } ]})
// ロールの作成db.createRole({ role: "appUser", privileges: [ { resource: { db: "myapp", collection: "" }, actions: ["find", "insert", "update", "remove"] } ], roles: []})// 暗号化の有効化(mongod.conf)security: encryption: keyFile: /path/to/keyfile
// TLS/SSL接続mongodb://localhost:27017/myapp?ssl=true&sslCAFile=/path/to/ca.pem11. バックアップとリストア
Section titled “11. バックアップとリストア”mongodumpによるバックアップ
Section titled “mongodumpによるバックアップ”# データベース全体のバックアップmongodump --host localhost:27017 --db myapp --out /backup
# 特定のコレクションのみのバックアップmongodump --host localhost:27017 --db myapp --collection users --out /backup
# 認証付きバックアップmongodump --host localhost:27017 --db myapp --username myuser --password mypassword --out /backupmongorestoreによるリストア
Section titled “mongorestoreによるリストア”# データベースのリストアmongorestore --host localhost:27017 --db myapp /backup/myapp
# 特定のコレクションのみのリストアmongorestore --host localhost:27017 --db myapp --collection users /backup/myapp/users.bson継続的バックアップ(Oplog)
Section titled “継続的バックアップ(Oplog)”// Oplogの確認db.oplog.rs.find().sort({ ts: -1 }).limit(1)
// ポイントインタイムリカバリmongorestore --oplogReplay /backup12. 実践的なベストプラクティス
Section titled “12. 実践的なベストプラクティス”スキーマ設計
Section titled “スキーマ設計”// 埋め込み vs 参照の選択
// 埋め込み(1対1、1対少)// - 頻繁に一緒にアクセスされるデータdb.users.insertOne({ name: "Alice", profile: { bio: "Developer", avatar: "avatar.jpg" }})
// 参照(1対多、多対多)// - 独立してアクセスされるデータdb.users.insertOne({ name: "Alice", order_ids: [ObjectId("..."), ObjectId("...")]})// データベース名: 小文字、スネークケースuse my_app
// コレクション名: 複数形、スネークケースdb.user_profiles.insertOne({...})
// フィールド名: スネークケース{ first_name: "Alice", created_at: new Date()}// サーバー統計の確認db.serverStatus()
// データベース統計の確認db.stats()
// コレクション統計の確認db.users.stats()
// スロークエリの確認db.setProfilingLevel(1, { slowms: 100 })db.system.profile.find().sort({ ts: -1 }).limit(10)13. よくある問題と解決方法
Section titled “13. よくある問題と解決方法”問題1: メモリ使用量が高い
Section titled “問題1: メモリ使用量が高い”// インデックスの確認db.users.getIndexes()
// 不要なインデックスの削除db.users.dropIndex({ unused_field: 1 })
// ワーキングセットの確認db.serverStatus().wiredTiger.cache問題2: クエリが遅い
Section titled “問題2: クエリが遅い”// クエリプランの確認db.users.find({ email: "alice@example.com" }).explain("executionStats")
// インデックスの作成db.users.createIndex({ email: 1 })
// プロジェクションの使用db.users.find({}, { name: 1, email: 1 })問題3: ディスク容量不足
Section titled “問題3: ディスク容量不足”// データベースサイズの確認db.stats()
// 不要なデータの削除db.old_logs.deleteMany({ created_at: { $lt: new Date("2023-01-01") } })
// コレクションの圧縮db.runCommand({ compact: "old_logs" })MongoDB完全ガイドのポイント:
- スキーマレス: 柔軟なデータ構造
- 集約パイプライン: 複雑なデータ処理
- インデックス: パフォーマンスの向上
- シャーディング: 水平スケーリング
- レプリカセット: 高可用性
- トランザクション: データ整合性
- セキュリティ: 認証と認可
- バックアップ: データ保護
適切なMongoDBの使用により、スケーラブルで柔軟なアプリケーションを構築できます。