目次
- MongoDBとは
- インストールと設定 (Windows 11)
- 基本概念
- 基本操作 (CRUD)
- 高度なクエリ
- インデックス
- 集計フレームワーク
- トランザクション
- バックアップとリストア
- レプリケーションとシャーディング
- セキュリティ
- パフォーマンス最適化
- Atlas (クラウドサービス)
- Node.jsとの連携
- トラブルシューティング
- 参考リンク
MongoDBとは
MongoDBは、ドキュメント指向のNoSQLデータベースです。JSONライクなBSONフォーマットでデータを保存し、スケーラビリティと柔軟性に優れています。
-
特徴:
- スキーマレス設計(柔軟なデータ構造)
- 水平スケーリング
- 高可用性
- 地理空間インデックス
- アグリゲーションフレームワーク
インストールと設定 (Windows 11)
インストール手順
-
MongoDBのダウンロード:
- MongoDB公式サイトからMongoDB Community Serverをダウンロード
- 「Windows x64」版を選択
-
インストーラの実行:
- ダウンロードしたMSIファイルを実行
- 「Complete」インストールを選択
- 「Install MongoDB as a Service」オプションにチェック
- デフォルトのデータディレクトリ:
C:\Program Files\MongoDB\Server\[version]\data
- デフォルトのログディレクトリ:
C:\Program Files\MongoDB\Server\[version]\log
-
MongoDB Compassのインストール:
- MongoDBのGUIクライアント
- インストーラでチェックボックスをオンにするか、別途ダウンロード
-
環境変数の設定:
- システム環境変数のPathに以下を追加:
C:\Program Files\MongoDB\Server\[version]\bin
- システム環境変数のPathに以下を追加:
-
サービスの確認:
- サービス一覧で「MongoDB」が実行中であることを確認
- または管理者権限のコマンドプロンプトで:
net start MongoDB
MongoDB Shellの起動
MongoDB Shell (mongosh)を使用してMongoDBサーバーに接続します:
mongosh
データベースの基本コマンド
// データベース一覧表示
show dbs
// 使用するデータベースを選択/作成
use mydatabase
// 現在のデータベースを表示
db
// 現在のデータベースのコレクション一覧を表示
show collections
基本概念
ドキュメント構造
MongoDBはドキュメント(JSONライクなBSON形式)でデータを保存します:
{
"_id": ObjectId("60a6d595f462e23456789012"),
"name": "山田太郎",
"age": 30,
"email": "yamada@example.com",
"address": {
"city": "東京",
"zipcode": "123-4567"
},
"hobbies": ["読書", "旅行", "プログラミング"]
}
基本要素
- データベース: コレクションの集合
- コレクション: ドキュメントの集合(RDBのテーブルに相当)
- ドキュメント: 単一のレコード(JSONライクなBSON形式)
- フィールド: キーと値のペア(RDBの列に相当)
- _id: 各ドキュメントの一意の識別子
基本操作 (CRUD)
作成 (Create)
単一ドキュメントの挿入:
db.users.insertOne({
name: "山田太郎",
age: 30,
email: "yamada@example.com"
})
複数ドキュメントの挿入:
db.users.insertMany([
{ name: "佐藤花子", age: 25, email: "sato@example.com" },
{ name: "鈴木一郎", age: 35, email: "suzuki@example.com" }
])
読み取り (Read)
全ドキュメントの取得:
db.users.find()
整形して表示:
db.users.find().pretty()
条件付き検索:
// 等価条件
db.users.find({ age: 30 })
// 比較演算子
db.users.find({ age: { $gt: 25 } }) // 25より大きい
db.users.find({ age: { $lt: 35 } }) // 35より小さい
db.users.find({ age: { $gte: 30 } }) // 30以上
db.users.find({ age: { $lte: 30 } }) // 30以下
db.users.find({ age: { $ne: 25 } }) // 25でない
// AND条件(複数条件を指定)
db.users.find({ age: 30, name: "山田太郎" })
// OR条件
db.users.find({ $or: [{ age: 30 }, { name: "佐藤花子" }] })
// 特定フィールドのみ取得
db.users.find({}, { name: 1, email: 1, _id: 0 })
単一ドキュメントの取得:
db.users.findOne({ name: "山田太郎" })
件数制限と並べ替え:
// 上位3件を取得
db.users.find().limit(3)
// 年齢の降順で並べ替え
db.users.find().sort({ age: -1 })
// 昇順で並べ替え
db.users.find().sort({ name: 1 })
// ページネーション(スキップと制限)
db.users.find().skip(10).limit(5)
ドキュメント数のカウント:
db.users.countDocuments({ age: { $gt: 25 } })
更新 (Update)
単一ドキュメントの更新:
db.users.updateOne(
{ name: "山田太郎" },
{ $set: { age: 31, updated_at: new Date() } }
)
複数ドキュメントの更新:
db.users.updateMany(
{ age: { $lt: 30 } },
{ $set: { status: "若手" } }
)
更新演算子:
// フィールド値の増加
db.users.updateOne({ name: "山田太郎" }, { $inc: { age: 1 } })
// 配列に要素を追加
db.users.updateOne({ name: "山田太郎" }, { $push: { hobbies: "料理" } })
// 配列から要素を削除
db.users.updateOne({ name: "山田太郎" }, { $pull: { hobbies: "料理" } })
// フィールドの名前変更
db.users.updateMany({}, { $rename: { "電話番号": "phone" } })
// 条件に合致する場合のみ更新(age < 30の場合のみ更新)
db.users.updateOne(
{ name: "山田太郎", age: { $lt: 30 } },
{ $set: { status: "若手" } }
)
ドキュメントの置換:
db.users.replaceOne(
{ name: "山田太郎" },
{ name: "山田太郎", age: 31, email: "newyamada@example.com" }
)
削除 (Delete)
単一ドキュメントの削除:
db.users.deleteOne({ name: "山田太郎" })
複数ドキュメントの削除:
db.users.deleteMany({ age: { $lt: 25 } })
コレクション内の全ドキュメントを削除:
db.users.deleteMany({})
コレクションの削除:
db.users.drop()
データベースの削除:
db.dropDatabase()
高度なクエリ
論理演算子
// AND (暗黙的)
db.users.find({ age: 30, city: "東京" })
// AND (明示的)
db.users.find({ $and: [{ age: 30 }, { city: "東京" }] })
// OR
db.users.find({ $or: [{ age: 30 }, { city: "大阪" }] })
// NOT
db.users.find({ age: { $not: { $gt: 30 } } })
// NOR (どの条件にも一致しない)
db.users.find({ $nor: [{ age: 30 }, { city: "大阪" }] })
配列クエリ
// 配列に特定の要素が含まれる
db.users.find({ hobbies: "読書" })
// 配列に複数の要素がすべて含まれる(順序は問わない)
db.users.find({ hobbies: { $all: ["読書", "旅行"] } })
// 配列の長さが特定の値
db.users.find({ "hobbies": { $size: 3 } })
// 配列の要素位置を指定
db.users.find({ "hobbies.0": "読書" }) // 最初の趣味が"読書"
// $elemMatch (配列内の要素が条件セットに一致)
db.orders.find({
items: { $elemMatch: { name: "ノートPC", price: { $gt: 100000 } } }
})
正規表現検索
// "山田"で始まる名前
db.users.find({ name: /^山田/ })
// "gmail.com"で終わるメール
db.users.find({ email: /gmail\.com$/ })
// "技術"を含む趣味
db.users.find({ hobbies: /技術/ })
// 大文字小文字を区別しない検索
db.users.find({ name: /yamada/i })
ネストされたドキュメントのクエリ
// ドット表記を使用したネストフィールドの検索
db.users.find({ "address.city": "東京" })
// ネストされたドキュメント全体の検索(完全一致)
db.users.find({
address: { city: "東京", zipcode: "123-4567" }
})
存在チェック
// フィールドが存在する
db.users.find({ email: { $exists: true } })
// フィールドが存在しない
db.users.find({ phone: { $exists: false } })
// nullチェック(nullまたは存在しない)
db.users.find({ phone: null })
// 厳密なnullチェック(nullのみ)
db.users.find({ phone: { $type: 10 } })
JavaScript式を使用したクエリ
// $where演算子(パフォーマンスに注意)
db.users.find({ $where: "this.hobbies.length > 3" })
// 関数を使用
db.users.find({ $where: function() { return this.age > 30 && this.hobbies.length > 2 } })
インデックス
インデックスの作成
// 単一フィールドのインデックス
db.users.createIndex({ name: 1 }) // 1:昇順、-1:降順
// 複合インデックス
db.users.createIndex({ name: 1, age: -1 })
// ユニークインデックス
db.users.createIndex({ email: 1 }, { unique: true })
// スパースインデックス(フィールドが存在するドキュメントのみインデックス)
db.users.createIndex({ phone: 1 }, { sparse: true })
// TTLインデックス(時間制限付きインデックス)
db.sessions.createIndex(
{ created_at: 1 },
{ expireAfterSeconds: 3600 } // 1時間後に削除
)
// テキストインデックス
db.articles.createIndex({ title: "text", content: "text" })
// 地理空間インデックス
db.places.createIndex({ location: "2dsphere" })
// ハッシュインデックス(シャーディング用)
db.users.createIndex({ _id: "hashed" })
// バックグラウンドでインデックス作成
db.users.createIndex(
{ name: 1 },
{ background: true }
)
インデックスの管理
// インデックス一覧の表示
db.users.getIndexes()
// インデックスのサイズと統計情報
db.users.stats().indexSizes
// 特定のインデックスを削除
db.users.dropIndex("name_1")
// すべてのインデックスを削除(_idを除く)
db.users.dropIndexes()
// インデックスを使用しているかチェック(実行計画)
db.users.find({ name: "山田太郎" }).explain()
// 詳細な実行計画
db.users.find({ name: "山田太郎" }).explain("executionStats")
集計フレームワーク
基本的な集計
// $match: ドキュメントのフィルタリング(WHERE句に相当)
db.users.aggregate([
{ $match: { age: { $gt: 30 } } }
])
// $group: グループ化と集計(GROUP BY句に相当)
db.users.aggregate([
{ $group: { _id: "$city", count: { $sum: 1 } } }
])
// $project: フィールドの選択と変換(SELECT句に相当)
db.users.aggregate([
{ $project: { name: 1, yearOfBirth: { $subtract: [2023, "$age"] } } }
])
// $sort: 結果の並べ替え(ORDER BY句に相当)
db.users.aggregate([
{ $sort: { age: -1 } }
])
// $limit: 結果の件数制限(LIMIT句に相当)
db.users.aggregate([
{ $limit: 5 }
])
// $skip: 結果のスキップ(OFFSET句に相当)
db.users.aggregate([
{ $skip: 10 }
])
高度な集計操作
// $unwind: 配列をフラット化
db.users.aggregate([
{ $unwind: "$hobbies" },
{ $group: { _id: "$hobbies", count: { $sum: 1 } } }
])
// $lookup: 他のコレクションとの結合(JOIN句に相当)
db.orders.aggregate([
{
$lookup: {
from: "users",
localField: "user_id",
foreignField: "_id",
as: "user_info"
}
}
])
// $facet: 複数の集計パイプラインを一度に実行
db.users.aggregate([
{
$facet: {
"ageStats": [
{ $group: { _id: null, avg: { $avg: "$age" }, min: { $min: "$age" }, max: { $max: "$age" } } }
],
"cityStats": [
{ $group: { _id: "$address.city", count: { $sum: 1 } } }
]
}
}
])
// $addFields: 既存のドキュメントに新しいフィールドを追加
db.users.aggregate([
{ $addFields: { fullName: { $concat: ["$firstName", " ", "$lastName"] } } }
])
// $bucket: 値をバケット(区間)に分類
db.users.aggregate([
{
$bucket: {
groupBy: "$age",
boundaries: [20, 30, 40, 50, 60],
default: "Other",
output: { count: { $sum: 1 } }
}
}
])
集計演算子
// 算術演算子
$add, $subtract, $multiply, $divide, $mod
// 文字列演算子
$concat, $substr, $toLower, $toUpper, $trim
// 日付演算子
$dayOfMonth, $month, $year, $hour, $minute, $second
// 比較演算子
$eq, $ne, $gt, $gte, $lt, $lte
// 配列演算子
$size, $arrayElemAt, $filter, $map, $reduce
// 条件演算子
$cond, $ifNull, $switch
// 型変換演算子
$toString, $toInt, $toDecimal, $toBool, $toDate
例:年齢層ごとの平均給料
db.employees.aggregate([
{ $match: { status: "active" } },
{
$group: {
_id: {
$switch: {
branches: [
{ case: { $lt: ["$age", 30] }, then: "20代" },
{ case: { $lt: ["$age", 40] }, then: "30代" },
{ case: { $lt: ["$age", 50] }, then: "40代" }
],
default: "50代以上"
}
},
avgSalary: { $avg: "$salary" },
count: { $sum: 1 }
}
},
{ $sort: { avgSalary: -1 } }
])
トランザクション
MongoDBは4.0以降、マルチドキュメントトランザクションをサポートしています(レプリカセット環境が必要)。
トランザクションの基本構文
// セッションの開始
const session = db.getMongo().startSession();
// トランザクションの開始
session.startTransaction();
try {
// 操作1
db.accounts.updateOne(
{ _id: "account1" },
{ $inc: { balance: -100 } },
{ session }
);
// 操作2
db.accounts.updateOne(
{ _id: "account2" },
{ $inc: { balance: 100 } },
{ session }
);
// 操作3
db.transactions.insertOne(
{ from: "account1", to: "account2", amount: 100, date: new Date() },
{ session }
);
// コミット
session.commitTransaction();
} catch (error) {
// エラー時はロールバック
session.abortTransaction();
print("Transaction aborted due to error: " + error);
} finally {
// セッション終了
session.endSession();
}
トランザクションの注意点
- レプリカセットまたはシャードクラスタが必要
- タイムアウト制限がある(デフォルト60秒)
- パフォーマンスへの影響を考慮する
- ロックの競合に注意
バックアップとリストア
mongodumpによるバックアップ
// データベース全体のバックアップ
mongodump --out=C:\backup\mongodb\full
// 特定のデータベースのバックアップ
mongodump --db=mydatabase --out=C:\backup\mongodb\mydatabase
// 特定のコレクションのバックアップ
mongodump --db=mydatabase --collection=users --out=C:\backup\mongodb\users
// 圧縮バックアップ
mongodump --gzip --out=C:\backup\mongodb\compressed
// 認証が必要な場合
mongodump --username=admin --password=password --authenticationDatabase=admin --out=C:\backup\mongodb\auth
mongorestoreによるリストア
// データベース全体のリストア
mongorestore C:\backup\mongodb\full
// 特定のデータベースのリストア
mongorestore --db=mydatabase C:\backup\mongodb\mydatabase\mydatabase
// 特定のコレクションのリストア
mongorestore --db=mydatabase --collection=users C:\backup\mongodb\users\mydatabase\users.bson
// 圧縮バックアップからのリストア
mongorestore --gzip C:\backup\mongodb\compressed
// ドロップオプション(リストア前にコレクションを削除)
mongorestore --drop C:\backup\mongodb\full
mongoexport/mongoimport (JSONフォーマット)
// JSONエクスポート
mongoexport --db=mydatabase --collection=users --out=users.json
// CSVエクスポート
mongoexport --db=mydatabase --collection=users --type=csv --fields=name,email,age --out=users.csv
// JSONインポート
mongoimport --db=mydatabase --collection=users --file=users.json
// CSVインポート
mongoimport --db=mydatabase --collection=users --type=csv --headerline --file=users.csv
レプリケーションとシャーディング
レプリケーション (高可用性)
レプリカセットの設定 (mongod.conf):
replication:
replSetName: "rs0"
レプリカセットの初期化:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "server1:27017" },
{ _id: 1, host: "server2:27017" },
{ _id: 2, host: "server3:27017" }
]
})
レプリカセットの管理:
// 状態確認
rs.status()
// 設定確認
rs.conf()
// メンバー追加
rs.add("server4:27017")
// メンバー削除
rs.remove("server4:27017")
// セカンダリからの読み取り許可(注意:データの一貫性が保証されない)
db.setReadPreference("secondary")
シャーディング (水平スケーリング)
設定サーバーの起動:
mongod --configsvr --replSet configRS --dbpath /data/configdb --port 27019
シャードサーバーの起動:
mongod --shardsvr --replSet shardRS1 --dbpath /data/shard1 --port 27018
mongosルーターの起動:
mongos --configdb configRS/config1:27019,config2:27019,config3:27019 --port 27017
シャードの追加:
sh.addShard("shardRS1/shard1:27018,shard2:27018,shard3:27018")
データベースのシャーディング有効化:
sh.enableSharding("mydatabase")
コレクションのシャーディング:
// ハッシュシャーディング
sh.shardCollection("mydatabase.users", { "_id": "hashed" })
// 範囲シャーディング
sh.shardCollection("mydatabase.orders", { "order_date": 1 })
シャーディング状態の確認:
sh.status()
セキュリティ
認証と認可の有効化
mongod.confでの設定:
security:
authorization: enabled
ユーザー管理
管理者ユーザーの作成:
use admin
db.createUser({
user: "adminUser",
pwd: "securePassword",
roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
})
データベース固有のユーザー作成:
use mydatabase
db.createUser({
user: "appUser",
pwd: "appPassword",
roles: [
{ role: "readWrite", db: "mydatabase" },
{ role: "read", db: "reporting" }
]
})
ユーザー管理:
// ユーザー一覧
db.getUsers()
// ユーザー情報
db.getUser("appUser")
// パスワード変更
db.changeUserPassword("appUser", "newPassword")
// ロールの追加
db.grantRolesToUser("appUser", [{ role: "readWrite", db: "newdb" }])
// ロールの削除
db.revokeRolesFromUser("appUser", [{ role: "readWrite", db: "newdb" }])
// ユーザー削除
db.dropUser("appUser")
組み込みロール
-
データベースユーザーロール:
read
,readWrite
-
データベース管理ロール:
dbAdmin
,dbOwner
,userAdmin
-
クラスタ管理ロール:
clusterAdmin
,clusterManager
,clusterMonitor
,hostManager
-
バックアップ/リストアロール:
backup
,restore
-
全データベースロール:
readAnyDatabase
,readWriteAnyDatabase
,userAdminAnyDatabase
,dbAdminAnyDatabase
-
スーパーユーザーロール:
root
TLS/SSL設定
mongod.confでの設定:
net:
ssl:
mode: requireSSL
PEMKeyFile: /path/to/server.pem
CAFile: /path/to/ca.pem
クライアント接続:
mongosh --ssl --sslCAFile /path/to/ca.pem --sslPEMKeyFile /path/to/client.pem
ネットワークセキュリティ
アクセス制限の設定:
net:
bindIp: 127.0.0.1,192.168.1.100
ファイアウォール設定(Windowsファイアウォール):
netsh advfirewall firewall add rule name="MongoDB" dir=in action=allow protocol=TCP localport=27017
パフォーマンス最適化
インデックス最適化
// ヒント(特定のインデックスを使用するよう指示)
db.users.find({ name: "山田太郎" }).hint({ name: 1 })
// カバリングインデックス(インデックスだけで検索が完結)
db.users.find({ name: "山田太郎" }, { name: 1, age: 1, _id: 0 }).hint({ name: 1, age: 1 })
// インデックスの利用状況分析
db.users.aggregate([
{ $indexStats: {} }
])
クエリ最適化
// 不要なフィールドを除外
db.users.find({}, { huge_field: 0 })
// プロジェクション(必要なフィールドのみ取得)
db.users.find({}, { name: 1, email: 1, _id: 0 })
// ページネーション
db.users.find().skip(100).limit(20)
// 適切なソートキー(インデックスがあるフィールドでソート)
db.users.find().sort({ indexed_field: 1 })
読み取りパフォーマンス
// 読み取り設定
db.setReadPreference("secondary") // セカンダリからの読み取り
// 読み取り操作の分離
db.setReadConcern("local") // 読み取り一貫性レベル
書き込みパフォーマンス
// バルク書き込み
const bulkOp = db.users.initializeUnorderedBulkOp();
bulkOp.insert({ name: "田中一郎", age: 25 });
bulkOp.find({ name: "山田太郎" }).updateOne({ $set: { age: 32 } });
bulkOp.find({ age: { $lt: 20 } }).remove();
bulkOp.execute();
// 書き込み確認レベル
db.users.insertOne(
{ name: "新規ユーザー" },
{ writeConcern: { w: "majority", wtimeout: 5000 } }
)
システムリソース最適化
mongod.confでの設定:
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 4 # RAMの50%程度を推奨
net:
maxIncomingConnections: 500 # 同時接続数制限
operationProfiling:
slowOpThresholdMs: 100 # スロークエリのログ閾値
パフォーマンスモニタリング
// サーバーステータス
db.serverStatus()
// データベースステータス
db.stats()
// コレクションステータス
db.users.stats()
// プロファイリング有効化
db.setProfilingLevel(1, 100) // 100ms以上のクエリをログ
// プロファイルデータ確認
db.system.profile.find().sort({ ts: -1 }).limit(10)
Atlas (クラウドサービス)
MongoDB AtlasはMongoDBの公式マネージドクラウドサービスです。
主な機能
- スケーラブルなクラスタデプロイ
- 自動バックアップとポイントインタイムリカバリ
- パフォーマンスアドバイザー
- データレイク統合
- セキュリティ機能(VPC、暗号化など)
- グローバルクラスタ(低レイテンシグローバル書き込み)
接続方法
// 接続文字列の例
mongodb+srv://username:password@cluster0.mongodb.net/mydatabase
// MongoShellでの接続
mongosh "mongodb+srv://cluster0.mongodb.net/mydatabase" --username username
Node.jsとの連携
MongoDB Node.js Driver
// インストール
// npm install mongodb
// 接続とクエリの例
const { MongoClient } = require('mongodb');
// 接続URL
const url = 'mongodb://localhost:27017';
const client = new MongoClient(url);
async function main() {
try {
// 接続
await client.connect();
console.log('MongoDB に接続しました');
// データベースとコレクションの取得
const db = client.db('mydatabase');
const collection = db.collection('users');
// ドキュメントの挿入
const insertResult = await collection.insertOne({
name: '山田太郎',
age: 30,
email: 'yamada@example.com'
});
console.log('挿入されたID:', insertResult.insertedId);
// ドキュメントの検索
const findResult = await collection.find({ age: { $gt: 25 } }).toArray();
console.log('検索結果:', findResult);
// ドキュメントの更新
const updateResult = await collection.updateOne(
{ name: '山田太郎' },
{ $set: { age: 31 } }
);
console.log('更新されたドキュメント数:', updateResult.modifiedCount);
// ドキュメントの削除
const deleteResult = await collection.deleteOne({ name: '山田太郎' });
console.log('削除されたドキュメント数:', deleteResult.deletedCount);
// 集計
const aggregationResult = await collection.aggregate([
{ $match: { age: { $gt: 20 } } },
{ $group: { _id: null, averageAge: { $avg: '$age' } } }
]).toArray();
console.log('平均年齢:', aggregationResult[0]?.averageAge);
} finally {
// 接続を閉じる
await client.close();
}
}
main().catch(console.error);
Mongoose (ODM)
// インストール
// npm install mongoose
// 基本的な使用例
const mongoose = require('mongoose');
// 接続
mongoose.connect('mongodb://localhost:27017/mydatabase', {
useNewUrlParser: true,
useUnifiedTopology: true
});
// 接続イベント
mongoose.connection.on('connected', () => {
console.log('Mongoose接続完了');
});
mongoose.connection.on('error', (err) => {
console.log('Mongoose接続エラー: ' + err);
});
// スキーマ定義
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true,
lowercase: true
},
age: {
type: Number,
min: 0,
max: 120
},
createdAt: {
type: Date,
default: Date.now
},
isActive: {
type: Boolean,
default: true
},
hobbies: [String],
address: {
city: String,
zipcode: String
}
});
// メソッド追加
userSchema.methods.getFullProfile = function() {
return `${this.name} (${this.age}歳) - ${this.email}`;
};
// 静的メソッド
userSchema.statics.findByName = function(name) {
return this.find({ name: new RegExp(name, 'i') });
};
// 仮想プロパティ
userSchema.virtual('isAdult').get(function() {
return this.age >= 20;
});
// ミドルウェア(フック)
userSchema.pre('save', function(next) {
console.log(`${this.name}を保存します`);
next();
});
// モデル作成
const User = mongoose.model('User', userSchema);
// CRUD操作
async function mongooseExample() {
try {
// 作成
const user = new User({
name: '山田太郎',
email: 'yamada@example.com',
age: 30,
hobbies: ['読書', '旅行'],
address: {
city: '東京',
zipcode: '123-4567'
}
});
await user.save();
console.log('ユーザーが保存されました');
// 読み取り
const users = await User.find({ age: { $gt: 25 } })
.select('name email age')
.sort({ age: -1 })
.limit(10);
console.log('検索結果:', users);
// 特定のIDで検索
const userById = await User.findById(user._id);
console.log('ID検索結果:', userById);
// 更新
const updateResult = await User.updateOne(
{ name: '山田太郎' },
{ $set: { age: 31 } }
);
console.log('更新結果:', updateResult);
// 検索と更新を一度に
const updatedUser = await User.findOneAndUpdate(
{ name: '山田太郎' },
{ $set: { age: 32 } },
{ new: true } // 更新後のドキュメントを返す
);
console.log('更新されたユーザー:', updatedUser);
// 削除
const deleteResult = await User.deleteOne({ name: '山田太郎' });
console.log('削除結果:', deleteResult);
// 集計
const aggregateResult = await User.aggregate([
{ $match: { age: { $gt: 20 } } },
{ $group: { _id: '$address.city', count: { $sum: 1 }, avgAge: { $avg: '$age' } } },
{ $sort: { count: -1 } }
]);
console.log('集計結果:', aggregateResult);
} catch (err) {
console.error('エラー:', err);
} finally {
mongoose.connection.close();
}
}
mongooseExample();
トラブルシューティング
一般的な問題と解決策
-
接続エラー
// 接続先が正しいか確認 netstat -an | findstr 27017 // MongoDBサービスが起動しているか確認 net start | findstr MongoDB // 手動で起動 net start MongoDB
-
認証エラー
// 正しい認証データベースを指定 mongosh -u username -p password --authenticationDatabase admin // 一時的に認証を無効化して回復 // mongod.conf の security.authorization を disabled に変更
-
パフォーマンス低下
// スロークエリログを確認 db.setProfilingLevel(1, 100) // 100ms以上のクエリをログ db.system.profile.find().sort({ ts: -1 }) // インデックスの確認と作成 db.collection.getIndexes() db.collection.createIndex({ frequently_queried_field: 1 }) // メモリ使用量の確認 db.serverStatus().wiredTiger.cache
-
ディスク容量不足
// データベースサイズの確認 db.stats() // コレクションサイズの確認 db.collection.stats() // 古いデータを削除またはアーカイブ db.old_collection.drop()
-
レプリケーション問題
// レプリカセットの状態確認 rs.status() // プライマリの確認 db.isMaster() // 同期状態の確認 db.printReplicationInfo()
ログファイルの確認
Windows環境のデフォルトログの場所:
C:\Program Files\MongoDB\Server\[version]\log\mongod.log
主要なログレベル:
-
F
(Fatal) -
E
(Error) -
W
(Warning) -
I
(Informational) -
D
(Debug)
データ修復とリカバリ
// DBパスをバックアップ
xcopy C:\data\db C:\data\db_backup /E /I
// チェックと修復(非推奨:バックアップ後に実行)
mongod --dbpath C:\data\db --repair
// 破損したコレクションのリカバリ
// 1. バックアップからのリストア
// 2. コレクションをクローン
db.createCollection("users_new")
db.users.find().forEach(function(doc) {
try {
db.users_new.insertOne(doc);
} catch (e) {
print("Error inserting document: " + e);
}
})