接続
接続文字列
mongosh "mongodb://localhost:27017" mongosh "mongodb://user:pass@host:27017/mydb" mongosh "mongodb+srv://user:[email protected]/mydb"
ドライバー接続(Node.js)
const { MongoClient } = require('mongodb'); const client = new MongoClient(uri); await client.connect(); const db = client.db('mydb');
データベースとコレクション
データベース操作
show dbs use mydb db.dropDatabase()
コレクション操作
db.createCollection("users") show collections db.users.drop()
上限付きコレクション
db.createCollection("logs", { capped: true, size: 10485760, max: 5000 })
CRUD 操作
挿入
db.users.insertOne({ name: "Alice", age: 30 }) db.users.insertMany([ { name: "Bob", age: 25 }, { name: "Carol", age: 28 } ])
検索
db.users.findOne({ name: "Alice" }) db.users.find({ age: { $gte: 25 } }) db.users.find({}, { name: 1, _id: 0 }) db.users.find().sort({ age: -1 }).limit(10)
更新
db.users.updateOne( { name: "Alice" }, { $set: { age: 31, city: "Boston" } } ) db.users.updateMany( { active: false }, { $set: { archived: true } } )
削除
db.users.deleteOne({ name: "Alice" }) db.users.deleteMany({ active: false })
置換と upsert
db.users.replaceOne( { name: "Alice" }, { name: "Alice", age: 32, city: "NYC" } ) db.users.updateOne( { email: "[email protected]" }, { $set: { name: "Alice" } }, { upsert: true } )
クエリ演算子
比較
$eq / $ne等価 / 非等価
$gt / $gteより大きい / 以上
$lt / $lteより小さい / 以下
$in / $nin配列内 / 配列外
論理
$andすべての条件が一致
$or少なくとも1つの条件が一致
$not条件を否定
$existsフィールドが存在する(true/false)
$regex正規表現でマッチ
更新演算子
$setフィールド値を設定
$unsetフィールドを削除
$inc数値をインクリメント
$push / $pull配列要素を追加 / 削除
$addToSet存在しない場合のみ配列に追加
$renameフィールドの名前を変更
集計
パイプラインステージ
$matchドキュメントをフィルター(WHERE に相当)
$groupグループ化と集計
$projectドキュメントを整形(SELECT に相当)
$sort結果をソート
$limit / $skipページネーション
$lookup別コレクションへの左外部結合
$unwind配列をドキュメントに展開
集計の例
db.orders.aggregate([ { $match: { status: "completed" } }, { $group: { _id: "$customer_id", total: { $sum: "$amount" }, count: { $sum: 1 } }}, { $sort: { total: -1 } }, { $limit: 10 } ])
インデックス
作成と削除
db.users.createIndex({ email: 1 }, { unique: true }) db.users.createIndex({ name: 1, age: -1 }) db.users.createIndex({ location: "2dsphere" }) db.users.dropIndex("email_1")
インデックス種類
Single field単一フィールドのインデックス({ name: 1 })
Compound複数フィールド({ a: 1, b: -1 })
Text全文検索({ field: 'text' })
2dsphere地理空間クエリ
TTL一定時間後にドキュメントを自動期限切れ
インデックス情報
db.users.getIndexes() db.users.find({ name: "Alice" }).explain()
スキーマ設計
埋め込み vs 参照
Embed1:1 または 1:少数、一緒に読まれるデータ
Reference1:多数、独立してアクセスされるデータ
Embedサブドキュメントが 16 MB を超えることがほぼない
Reference多対多の関係
スキーマバリデーション
db.createCollection("users", { validator: { $jsonSchema: { bsonType: "object", required: ["name", "email"], properties: { name: { bsonType: "string" }, email: { bsonType: "string" } }}}})
レプリケーション
レプリカセットの概念
Primaryすべての書き込みを受け付ける
Secondaryプライマリからレプリケート、読み取りを提供できる
Arbiter選挙で投票するが、データを保持しない
レプリカセットコマンド
rs.initiate() rs.add("mongo2:27017") rs.addArb("mongo3:27017") rs.status() rs.conf()
よく使うパターン
トランザクション
const session = client.startSession(); session.startTransaction(); await db.collection("accounts").updateOne( { _id: 1 }, { $inc: { bal: -100 } }, { session }); await db.collection("accounts").updateOne( { _id: 2 }, { $inc: { bal: 100 } }, { session }); await session.commitTransaction();
バルク書き込み
db.users.bulkWrite([ { insertOne: { document: { name: "Dan" } } }, { updateOne: { filter: { name: "Alice" }, update: { $set: { age: 31 } } }}, { deleteOne: { filter: { name: "old" } } } ])
チェンジストリーム
const stream = db.collection("orders") .watch([{ $match: { "fullDocument.status": "new" } }]); stream.on("change", (change) => { console.log(change.fullDocument); });
mongosh コマンド
シェルヘルパー
show dbsデータベースを一覧表示
show collections現在の DB のコレクションを一覧表示
db.stats()データベース統計
db.collection.stats()コレクション統計
db.collection.countDocuments({})ドキュメント数をカウント
db.collection.distinct('field')フィールドの一意な値
エクスポートとインポート
mongoexport --db=mydb --collection=users \ --out=users.json mongoimport --db=mydb --collection=users \ --file=users.json mongodump --db=mydb --out=/backup/ mongorestore --db=mydb /backup/mydb/