MongoDB: データベースとコレクション:MongoDBのストレージ単位
最終更新:2026-08-26
データベースとコレクションはMongoDBの2つの最も基本的なストレージ単位です。リレーショナルデータベースの「データベース + テーブル」に相当します。
このチュートリアルでは、MongoDBのデータベースとコレクションの作成、命名規則、Capped Collectionの使い方、コレクションの制限とベストプラクティスを深く学びます。
1. 学習内容
- MongoDBデータベースとコレクションの概念
- データベースとコレクションの暗黙的作成と明示的作成
- データベースとコレクションの命名規則
- Capped Collection(固定サイズコレクション)の使い方
- コレクションの制限(サイズ、ドキュメント数、インデックス数)
- system.namespacesでのデータベースとコレクションのメタデータの確認
- データベースとコレクションの削除と管理
2. フルスタックエンジニアの実例
(1) 課題:データベースの命名規則と削除保護の欠如
Daveは新しいECプロジェクトのバックエンドエンジニアです:
「開発中、
use order-dbでデータベースを作成し、データを保存しました。しかしdb.dropDatabase()を実行した後、コマンドライン履歴から上矢印キーを押して誤って再度実行してしまい、生産データが完全に失われました。」
彼が直面した2つの問題:
| 問題 | 説明 |
|---|---|
| 命名規則の混在 | order-db(ケバブケース)、order_db(スネークケース)、orderDb(キャメルケース)が混在し、混乱 |
| 削除保護の欠如 | db.dropDatabase()は確認なしで即座に実行され、誤操作でデータ消失 |
(2) 命名規則の統一と削除保護の実装
命名規則を統一し、削除保護スクリプトを追加します。
# === 命名規則の統一:snake_case(snake_case推奨)===
# ✅ 正しい命名
use shop_db;
db.createCollection("users");
db.createCollection("order_items");
db.createCollection("product_categories");
# === 削除保護スクリプト(確認を追加)===
# scripts/drop-db-safe.sh
drop_database_safe() {
local db_name="$1"
echo "⚠️ WARNING: This will permanently delete database: $db_name"
read -p "Type the database name to confirm: " confirmation
if [ "$confirmation" == "$db_name" ]; then
mongosh --eval "use $db_name; db.dropDatabase()"
echo "✅ Database $db_name dropped."
else
echo "❌ Database name does not match. Operation cancelled."
fi
}
(3) 成果
| 項目 | 改善前 | 改善後 |
|---|---|---|
| 命名規則 | 混在(ケバブ、スネーク、キャメル) | 統一(スネークケース) |
| 削除保護 | 確認なし | 名称確認が必要 |
| 可読性 | 低い | 高い |
| チーム協業 | 理解に時間がかかる | 即座に理解 |
3. MongoDBデータベース
概念概要:MongoDBデータベースはコレクションの論理コンテナで、リレーショナルデータベースのデータベースと同様の概念です。MongoDBデータベースの特徴は「遅延作成」です — use mydbでデータベースを切り替えても、最初のドキュメントを保存するまでデータベースは実際に作成されません。これによりリソースを節約できますが、データベース名のスペルミスに気づきにくい問題も発生します。
仕組み:MongoDBの各データベースはデータディレクトリ内に独立したファイルのセット(.wt WiredTigerファイル)として保存されます。データベース名は最大64バイトです。システムデータベース(admin、local、config)は予約されており、ユーザーデータには使用できません。データベースを削除すると、そのデータベースに関連するすべてのファイルとインデックスが削除されます(ディスクスペースの回収)。
graph TB
A[MongoDBインスタンス] --> B[admin<br/>ユーザー権限管理]
A --> C[local<br/>レプリカセットメタデータ]
A --> D[config<br/>シャーディング設定]
A --> E[shop_db<br/>ユーザーデータベース]
A --> F[logs_db<br/>ユーザーデータベース]
style B fill:#f8d7da
style C fill:#f8d7da
style D fill:#f8d7da
style E fill:#d4edda
style F fill:#d4edda
| データベース | 用途 | 説明 |
|---|---|---|
| admin | 管理データベース | ユーザー権限管理 |
| local | ローカルデータベース | レプリカセットメタデータ(同期不可) |
| config | 設定データベース | シャーディング設定 |
| ユーザー作成 | ユーザーデータベース | アプリケーションデータ |
(1) データベースの概念
MongoDBデータベースはコレクションの論理コンテナです:
graph TB
A[MongoDBインスタンス] --> B[admin<br/>ユーザー権限管理]
A --> C[local<br/>レプリカセットメタデータ]
A --> D[config<br/>シャーディング設定]
A --> E[shop_db<br/>ユーザーデータベース]
A --> F[logs_db<br/>ユーザーデータベース]
style B fill:#f8d7da
style C fill:#f8d7da
style D fill:#f8d7da
style E fill:#d4edda
style F fill:#d4edda
(2) システムデータベース
| データベース | 用途 | 説明 |
|---|---|---|
| admin | 管理データベース | ユーザー権限管理 |
| local | ローカルデータベース | レプリカセットメタデータ(同期不可) |
| config | 設定データベース | シャーディング設定 |
| ユーザー作成 | ユーザーデータベース | アプリケーションデータ |
(3) データベースの作成と切り替え
ポイント解説:
- MongoDBの「遅延作成」メカニズム — データベースは最初のドキュメントが保存された時に初めて作成されます
- データベース名の大文字小文字の区別 — MongoDBはデータベース名を小文字に変換するため、
MyDBとmydbは同じになります show dbsコマンド — 空のデータベース(ドキュメントがない)は表示されません- データベースの削除 —
db.dropDatabase()は現在のデータベースを削除し、確認なしで即座に実行されます
// === データベースの切り替え(存在しない場合は暗黙的に作成)===
use shop_db
// switch to shop_db
// データベースを表示(空のデータベースは表示されない)
show dbs
// admin 0.000GB
// config 0.000GB
// local 0.000GB
// shop_dbはまだ表示されない(ドキュメントがない)
// コレクションを作成してドキュメントを挿入すると、データベースが作成される
db.products.insertOne({ sku: "PHONE-001" })
// これでshop_dbが作成される
show dbs
// admin 0.000GB
// config 0.000GB
// local 0.000GB
// shop_db 0.000GB ← 表示される
(4) データベースの命名規則
概念説明:データベース名はチーム協業と長期的なメンテナンスに重要です。MongoDBはデータベース名に次の厳格な制限を課しています:空文字列であってはならない、/\. "$*<>:|?を含められない、予約データベース名(admin、local、config)を使用できない。また、いくつかのソフトな推奨事項があります:小文字を使用する、スペースを避ける、意味のある名前を使用する、最大64バイト。
| ルール | 制限 | 例 |
|---|---|---|
| 禁止文字 | `/. "$*<>: | ?` |
| 予約語 | admin、local、config |
❌ adminはシステム用 |
| 空文字列 | 許可されない | ❌ "" |
| 大文字小文字 | 自動的に小文字に変換 | MyDB → mydb |
| 推奨 | 小文字 + アンダースコア | ✅ shop_db、logs_db |
▶ サンプル 1:データベース操作
// === データベースの切り替え ===
use shop_db
// === 現在のデータベースを確認 ===
db.getName()
// shop_db
// === データベース統計を確認 ===
db.stats()
出力:
TEXT 📖 参照専用{ db: 'shop_db', collections: 1, views: 0, objects: 100, avgObjectSize: 48, dataSize: 4800, storageSize: 16384, indexes: 1, indexSize: 16384, totalSize: 32768 }
// === データベースを削除 ===
db.dropDatabase()
// { "dropped": "shop_db", "ok": 1 }
// 確認
show dbs
// shop_dbはもう表示されない
4. MongoDBコレクション
概念概要:MongoDBコレクションはドキュメントのグループで、リレーショナルデータベースのテーブルと同様の概念です。しかし、MongoDBコレクションの最大の特徴は「動的スキーマ」です — 同じコレクション内のドキュメントは異なるフィールドを持つことができ、異なるデータ型を持つことができます。この柔軟性は開発速度を加速しますが、データ検証の責任がアプリケーション層に移ります。
仕組み:コレクションは内部的にWiredTigerストレージエンジン内で独立したファイルとして保存されます。各コレクションは独自のインデックス、データ、メタデータを持ちます。コレクション名はデータベース名とコレクション名の組み合わせで一意です(例:shop_db.products)。MongoDBはdb.createCollection()でコレクションを作成できますが、db.collection.insertOne()で最初のドキュメントを保存するとコレクションも暗黙的に作成されます。
graph TB
subgraph "shop_dbデータベース"
A[productsコレクション] --> A1[ドキュメント1<br/>{sku, price, stock}]
A --> A2[ドキュメント2<br/>{sku, price, stock, discount}]
B[usersコレクション] --> B1[ドキュメント1<br/>{name, email}]
B --> B2[ドキュメント2<br/>{name, email, phone}]
C[ordersコレクション] --> C1[ドキュメント1<br/>{user_id, items, total}]
end
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#fff3cd
| 特徴 | MongoDBコレクション | リレーショナルテーブル |
|---|---|---|
| スキーマ | 動的(異なるドキュメント構造可) | 静的(固定カラム定義) |
| 作成方法 | 暗黙的(データ挿入時) | 明示的(CREATE TABLE) |
| フィールド追加 | 自動 | ALTER TABLEが必要 |
| インデックス作成 | 自動(_id) |
手動(PRIMARY KEY) |
(1) コレクションの概念
コレクションはドキュメントのグループで、リレーショナルデータベースのテーブルに相当します:
graph TB
subgraph "shop_dbデータベース"
A[productsコレクション] --> A1[ドキュメント1<br/>{sku, price, stock}]
A --> A2[ドキュメント2<br/>{sku, price, stock, discount}]
B[usersコレクション] --> B1[ドキュメント1<br/>{name, email}]
B --> B2[ドキュメント2<br/>{name, email, phone}]
C[ordersコレクション] --> C1[ドキュメント1<br/>{user_id, items, total}]
end
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#fff3cd
(2) 動的スキーマ
概念説明:MongoDBの動的スキーマは利点でもありリスクでもあります。利点は開発速度の加速 — 新しいフィールドの追加にスキーマ変更が不要で、プロトタイピングや頻繁な反復に適しています。リスクはデータ品質の低下 — 検証ロジックがない場合、同じコレクション内に完全に異なる構造のドキュメントが存在し、クエリとメンテナンスが困難になります。Mongooseスキーマ検証はこの問題を解決します。
// 同じコレクション内に異なるフィールドを持つドキュメントが存在可能
db.products.insertOne({ sku: "PHONE-001", price: 599.99 });
db.products.insertOne({ sku: "LAPTOP-001", price: 1299.99, discount: 0.1 });
db.products.insertOne({ sku: "BOOK-001", title: "MongoDB Guide", pages: 300 });
// 3つのドキュメントはすべてproductsコレクションに存在
db.products.find()
出力:
TEXT 📖 参照専用{ _id: ..., sku: 'PHONE-001', price: 599.99 } { _id: ..., sku: 'LAPTOP-001', price: 1299.99, discount: 0.1 } { _id: ..., sku: 'BOOK-001', title: 'MongoDB Guide', pages: 300 }
(3) コレクションの作成
ポイント解説:
- 暗黙的作成(推奨)— 最初のドキュメントを保存する際にMongoDBが自動的にコレクションを作成
- 明示的作成 —
db.createCollection()でコレクションを明示的に作成し、Capped Collectionなどのオプションを指定可能 - コレクション名の命名規則 — アルファベットで始まり、
system.で始められない(予約) - コレクション名の大文字小文字の区別 — MongoDBはコレクション名を区別するため、
Usersとusersは異なるコレクション
// === 暗黙的作成(推奨)===
db.products.insertOne({ sku: "PHONE-001", price: 599.99 })
// productsコレクションが自動的に作成される
// === 明示的作成 ===
db.createCollection("users", {
capped: true, // Capped Collection(固定サイズ)
size: 5242880, // 5 MB
max: 5000 // 最大5000ドキュメント
})
// === コレクションを確認 ===
show collections
// products
// users
(4) コレクションの命名規則
| ルール | 制限 | 例 |
|---|---|---|
| 禁止文字 | $を含められない |
❌ user$info |
| 予約語 | system.で始められない |
❌ system.users |
| 空文字列 | 許可されない | ❌ "" |
| 推奨 | 小文字 + アンダースコア | ✅ order_items |
| 長さ | 最大255バイト | VeryLongName... |
▶ サンプル 2:コレクション操作
// === コレクションの一覧表示 ===
show collections
// products
// users
// orders
// === コレクションの統計を確認 ===
db.products.stats()
出力:
TEXT 📖 参照専用{ ns: 'shop_db.products', count: 100, size: 4800, avgObjSize: 48, storageSize: 16384, nindexes: 1, totalIndexSize: 16384 }
// === コレクションの削除 ===
db.products.drop()
// true
// 確認
show collections
// productsはもう表示されない
5. Capped Collection(固定サイズコレクション)
概念概要:Capped CollectionはMongoDBの特殊なコレクション型で、固定サイズを持ち、最も古いドキュメントを自動的に削除する先入れ先出し(FIFO)キーです。ログ、イベント、センサーデータなどの時間順序データの保存に非常に適しています。Capped Collectionの利点は、ストレージ使用量が予測可能で、削除操作が不要、高書き込みパフォーマンスです。欠点はドキュメントを更新または削除できないことです。
仕組み:Capped Collectionは内部的に循環バッファとして実装されています。新しいドキュメントが追加されると、末尾に書き込まれます。バッファが満杯の場合、最も古いドキュメント(先頭)が自動的に上書きされます。これによりディスクスペースが常に制限内に保たれます。通常のコレクションと異なり、Capped Collectionはupdate()やdelete()操作をサポートしません(ドキュメントサイズを変更できないため)。insert()のみをサポートします。
graph LR
A[新しいログ] --> B[Capped Collection<br/>最大5MB]
B --> C[最も古いログを自動削除]
style B fill:#d4edda
| 特徴 | 通常のコレクション | Capped Collection |
|---|---|---|
| サイズ制限 | なし | 固定サイズ |
| 自動削除 | 手動削除が必要 | 自動削除 |
| 更新 | 可能 | 不可 |
| 削除 | 可能 | 不可 |
| 用途 | 一般データ | ログ、イベント、センサーデータ |
(1) Capped Collectionとは?
Capped Collectionは固定サイズのコレクションで、最も古いドキュメントを自動的に削除します:
graph LR
A[新しいログ] --> B[Capped Collection<br/>最大5MB]
B --> C[最も古いログを自動削除]
style B fill:#d4edda
(2) Capped Collectionの作成
ポイント解説:
capped: true— Capped Collectionとして作成することを指定size— コレクションの最大サイズを指定(バイト単位、最小4096バイト)max— ドキュメントの最大数を指定(オプション)- Capped Collectionはドキュメントの更新または削除をサポートしない — 新しいドキュメントのみを追加可能
db.collection.isCapped()— コレクションがCapped Collectionかどうかを確認
// === Capped Collectionの作成 ===
db.createCollection("system_logs", {
capped: true,
size: 5242880, // 5 MB
max: 10000 // 最大10000ドキュメント
})
// === 確認 ===
db.system_logs.isCapped()
// true
// === ログの挿入 ===
db.system_logs.insertMany([
{ level: "info", message: "Server started", timestamp: new Date() },
{ level: "warn", message: "High memory usage", timestamp: new Date() },
{ level: "error", message: "Database connection failed", timestamp: new Date() }
])
// === ログの検索(挿入順序で返す)===
db.system_logs.find().sort({ $natural: -1 }) // 最新から最も古いへ
(3) Capped Collectionの用途
| 用途 | 説明 | Capped Collectionの利点 |
|---|---|---|
| ログ | アプリケーションログ、エラーログ | ストレージ使用量が予測可能 |
| イベント | ユーザー行動、システムイベント | 高書き込みパフォーマンス |
| センサーデータ | IoTデバイスデータ | 自動削除、保存容量制限 |
| キャッシュ | 一時データ、セッション | TTL(time-to-live)として使用可能 |
▶ サンプル 3:Capped Collectionでログを保存
// === Capped Collectionの作成(10MB)===
db.createCollection("app_logs", {
capped: true,
size: 10485760 // 10 MB
})
// === ログの挿入 ===
for (let i = 0; i < 1000; i++) {
db.app_logs.insertOne({
level: ["info", "warn", "error"][Math.floor(Math.random() * 3)],
message: `Log message ${i}`,
timestamp: new Date()
})
}
// === 最新の100件のログを検索 ===
db.app_logs.find().sort({ $natural: -1 }).limit(100)
// === 統計を確認 ===
db.app_logs.stats()
出力:
TEXT 📖 参照専用{ ns: 'shop_db.app_logs', count: 1000, size: 48000, capped: true, maxSize: 10485760, ... }
6. system.namespacesとメタデータ
概念概要:MongoDBはデータベースとコレクションのメタデータをsystem.namespacesシステムコレクション(MongoDB 4.4以降はsystem.namespace情報はlistCollectionsコマンドで取得)に保存します。各データベースとコレクションには一意の名前空間識別子(例:shop_db.products)があり、システムはこの識別子を使用してデータの保存場所を管理します。この概念はインデックス作成とシャーディングにとって重要です。
(1) データベースとコレクションのメタデータを確認
// === 全データベースを一覧 ===
db.adminCommand("listDatabases")
出力:
TEXT 📖 参照専用{ databases: [ { name: 'admin', sizeOnDisk: 16384, empty: false }, { name: 'config', sizeOnDisk: 16384, empty: false }, { name: 'local', sizeOnDisk: 16384, empty: false }, { name: 'shop_db', sizeOnDisk: 32768, empty: false } ], totalSize: 65536 }
// === 現在のデータベースのコレクションを一覧 ===
db.getCollectionNames()
// [ 'products', 'users', 'orders' ]
// === コレクションの詳細情報を取得 ===
db.getCollectionInfos()
出力:
TEXT 📖 参照専用[ { name: 'products', type: 'collection', options: {}, info: { readOnly: false } }, { name: 'users', type: 'collection', options: { capped: true, size: 5242880 } } ]
7. データベースとコレクションの管理
(1) データベースの管理
ポイント解説:
db.dropDatabase()— 現在のデータベースを削除、確認なしで即座に実行、注意して使用db.stats()— データベースの統計情報(サイズ、ドキュメント数、インデックスサイズ)db.getName()— 現在のデータベース名を取得db.copyDatabase()— データベースをコピー(MongoDB 4.2以降は非推奨、mongodumpとmongorestoreを使用)- データベースのバックアップ — 本番環境では
mongodumpを使用して定期バックアップを推奨
| コマンド | 説明 |
|---|---|
use <db> |
データベースを切り替え(存在しない場合は作成) |
show dbs |
全データベースを一覧 |
db.stats() |
データベースの統計を確認 |
db.dropDatabase() |
データベースを削除 |
db.getName() |
現在のデータベース名を取得 |
(2) コレクションの管理
| コマンド | 説明 |
|---|---|
show collections |
全コレクションを一覧 |
db.createCollection(name, options) |
コレクションを作成 |
db.collection.stats() |
コレクションの統計を確認 |
db.collection.drop() |
コレクションを削除 |
db.collection.renameCollection(newName) |
コレクション名を変更 |
▶ サンプル 4:データベースとコレクションの管理スクリプト
// === データベースの作成と切り替え ===
use analytics_db
// === 複数のコレクションを作成 ===
db.createCollection("page_views", { capped: true, size: 10485760 })
db.createCollection("user_events")
db.createCollection("error_logs", { capped: true, size: 5242880 })
// === 全コレクションを一覧 ===
show collections
// page_views
// user_events
// error_logs
// === コレクション名を変更 ===
db.user_events.renameCollection("events")
// { "ok": 1 }
// === コレクションを削除 ===
db.error_logs.drop()
// true
// === データベースの統計を確認 ===
db.stats()
❓ よくある質問
{ 商品情報: {...} }は有効ですが、デバッグ、ログ、サードパーティツールでのサポートが不十分で、運用上の問題が発生する可能性があります。全体で英語を使用することを推奨します。db.dropDatabase()は現在のデータベースとそのデータベース内の全コレクション、インデックス、データファイルを削除します。この操作は元に戻せません。本番環境ではバックアップを推奨します。db.collection.convertToCapped()を使用して通常のコレクションをCapped Collectionに変換できます。📖 まとめ
- MongoDBデータベースはコレクションの論理コンテナで、リレーショナルデータベースのデータベースと同様の概念
- データベースは遅延作成 — 最初のドキュメントが保存された時に作成
- MongoDBコレクションはドキュメントのグループで、リレーショナルデータベースのテーブルに相当
- 動的スキーマ — 同じコレクション内のドキュメントは異なるフィールドを持つことが可能
- データベース名は最大64バイト、コレクション名は最大255バイト
- Capped Collectionは固定サイズのコレクションで、ログ、イベント、センサーデータに適している
- データベースとコレクションの命名規則を統一し、チーム協業を容易に
📝 練習問題
-
基礎問題(⭐):mongoshで
shop_dbデータベースを作成し、products、users、ordersの3つのコレクションを作成し、それぞれにドキュメントを挿入してください。 -
基礎問題(⭐):Capped Collection
logsを作成し(最大サイズ10MB)、100件のログを自動的に挿入するスクリプトを書き、最も古いログが自動的に削除されることを確認してください。 -
応用問題(⭐⭐):
db.stats()とdb.collection.stats()を使用してデータベースとコレクションの統計情報を取得し、結果を分析してください。 -
応用問題(⭐⭐):Node.jsスクリプトを書き、Mongooseを使用して複数のコレクション(
users、products、orders)を作成し、コレクションの作成と削除の動作を確認してください。 -
チャレンジ(⭐⭐⭐):ログシステムを設計し、Capped Collectionを使用してアプリケーションログを保存し、ログレベル(info、warn、error)でフィルタリングするクエリ機能を実装してください。