MongoDB

2026.04.10

公式ドキュメント

この記事の要点

insertOne/find/updateOne/deleteOneがCRUDの基本4操作
aggregateパイプラインで$match→$group→$sortの集計が強力
• インデックス設計とexplain()による実行計画確認が性能の鍵

概要

MongoDB は BSON 形式でドキュメントを格納する代表的なドキュメント指向データベースです。本チートシートでは mongosh (MongoDB Shell) から実行するコマンドを中心に、実務で頻出する CRUD・クエリ・集計・インデックス操作を整理します。コマンドは MongoDB 7.x / 8.x の公式マニュアルに基づいています。

接続と基本

コマンド説明
mongoshローカルの MongoDB に接続
mongosh "mongodb://host:27017"任意ホストに接続
mongosh "mongodb+srv://user:pass@cluster/db"Atlas SRV 接続
show dbsデータベース一覧
use mydbデータベースを選択(存在しなければ作成予約)
db現在のデータベース名
show collectionsコレクション一覧
db.stats()DB 統計
db.version()バージョン確認

データベース・コレクション管理

コマンド説明
db.createCollection("users")コレクション作成
db.users.drop()コレクション削除
db.dropDatabase()現在の DB を削除
db.users.renameCollection("members")リネーム
db.users.countDocuments({})件数(正確)
db.users.estimatedDocumentCount()メタ情報からの概算件数

CRUD 操作

挿入

コマンド説明
db.users.insertOne({name: "Ada"})1 件挿入
db.users.insertMany([{...}, {...}])複数挿入
db.users.insertMany(docs, {ordered: false})失敗時も継続

ポイント: insertMany{ordered: false}を指定すると、途中でエラーが発生しても残りのドキュメントの挿入を継続します。大量データ投入時に便利です。

検索

コマンド説明
db.users.find()全件取得
db.users.find({age: {$gte: 18}})条件付き取得
db.users.findOne({_id: id})1 件取得
db.users.find({}, {name: 1, _id: 0})射影(projection)
db.users.find().sort({age: -1})降順ソート
db.users.find().limit(10).skip(20)ページング
db.users.distinct("country")値の一覧

更新

コマンド説明
db.users.updateOne({_id}, {$set: {age: 30}})1 件更新
db.users.updateMany({active: true}, {$inc: {points: 1}})複数更新
db.users.replaceOne({_id}, newDoc)置換
db.users.updateOne(filter, update, {upsert: true})無ければ挿入
db.users.findOneAndUpdate(filter, update, {returnDocument: "after"})更新後ドキュメントを返却

削除

コマンド説明
db.users.deleteOne({_id})1 件削除
db.users.deleteMany({active: false})複数削除
db.users.findOneAndDelete(filter)削除したドキュメントを返却

実践メモ: findOneAndUpdate{returnDocument: "after"}を付けると、更新後のドキュメントが返されます。アトミックな更新+取得に最適です。

クエリ演算子

比較

演算子説明
$eq等しい
$ne等しくない
$gt / $gteより大きい / 以上
$lt / $lteより小さい / 以下
$inいずれかに一致
$ninいずれにも一致しない

論理

演算子説明
$andすべて満たす
$orいずれかを満たす
$norどれも満たさない
$not否定

要素

演算子説明
$existsフィールドの有無
$typeBSON 型で絞り込み

配列

演算子説明
$all指定値をすべて含む
$elemMatch要素ごとの複合条件
$size配列長で絞り込み

注意: $setreplaceOneは異なります。$setは指定フィールドのみ更新、replaceOneはドキュメント全体を置換します。意図しないフィールド消失に注意しましょう。

更新演算子

演算子説明
$setフィールドを設定
$unsetフィールドを削除
$inc数値を加算
$mul数値を乗算
$min / $max最小/最大で更新
$renameフィールドをリネーム
$push配列に追加
$addToSet重複しないよう追加
$pull条件に合う要素を削除
$pop末尾/先頭を削除
$currentDate現在日時を設定

実用スニペット集

1. 部分一致(正規表現)

db.users.find({ name: /^Ada/i });

2. 複合条件

db.orders.find({
  status: "paid",
  total: { $gte: 1000 },
  createdAt: { $gte: new Date("2026-01-01") }
});

3. OR 条件

db.users.find({
  $or: [{ role: "admin" }, { plan: "premium" }]
});

4. 配列要素の複合条件

db.products.find({
  tags: { $elemMatch: { $in: ["sale", "new"] } }
});

5. Upsert

db.counters.updateOne(
  { _id: "visits" },
  { $inc: { value: 1 } },
  { upsert: true }
);

6. 集計:グループ集計

db.orders.aggregate([
  { $match: { status: "paid" } },
  { $group: { _id: "$userId", total: { $sum: "$amount" }, count: { $sum: 1 } } },
  { $sort: { total: -1 } },
  { $limit: 10 }
]);

7. 集計:JOIN($lookup)

db.orders.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "user"
    }
  },
  { $unwind: "$user" }
]);

8. 集計:フィールド追加

db.users.aggregate([
  {
    $addFields: {
      fullName: { $concat: ["$firstName", " ", "$lastName"] }
    }
  }
]);

9. 集計:日別集計

db.events.aggregate([
  {
    $group: {
      _id: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt" } },
      count: { $sum: 1 }
    }
  },
  { $sort: { _id: 1 } }
]);

10. インデックス作成

db.users.createIndex({ email: 1 }, { unique: true });
db.orders.createIndex({ userId: 1, createdAt: -1 });
db.posts.createIndex({ title: "text", body: "text" });

11. テキスト検索

db.posts.find({ $text: { $search: "mongodb index" } });

12. インデックス一覧・削除

db.users.getIndexes();
db.users.dropIndex("email_1");

13. 実行計画の確認

db.users.find({ email: "a@b.co" }).explain("executionStats");

14. Bulk Write

db.users.bulkWrite([
  { insertOne: { document: { name: "A" } } },
  { updateOne: { filter: { name: "A" }, update: { $set: { active: true } } } },
  { deleteOne: { filter: { name: "old" } } }
]);

15. トランザクション(レプリカセット必須)

const session = db.getMongo().startSession();
session.startTransaction();
try {
  session.getDatabase("shop").orders.insertOne({...}, { session });
  session.getDatabase("shop").stock.updateOne({...}, { $inc: { qty: -1 } }, { session });
  session.commitTransaction();
} catch (e) {
  session.abortTransaction();
  throw e;
} finally {
  session.endSession();
}

16. エクスポート / インポート(シェル外)

コマンド説明
mongoexport --uri="mongodb://localhost/shop" --collection=users --out=users.jsonJSON エクスポート
mongoimport --uri="mongodb://localhost/shop" --collection=users --file=users.jsonJSON インポート
mongodump --uri="mongodb://localhost" --out=backup/バイナリダンプ
mongorestore --uri="mongodb://localhost" backup/バイナリリストア

ポイント: 集計パイプラインでは$matchをパイプラインの先頭に配置し、インデックスを効かせることが性能最適化の基本です。

集計ステージ早見表

ステージ説明
$match条件で絞り込み
$projectフィールド整形
$groupグループ化・集計
$sortソート
$limit / $skip件数制御
$lookup結合
$unwind配列を展開
$addFieldsフィールド追加
$set$addFields のエイリアス
$unsetフィールド削除
$count件数を返す
$facet複数パイプラインを並列実行
$bucketバケット集計
$merge結果を別コレクションに書き込み
$out結果を完全置換で書き込み

集計演算子(式)早見表

演算子説明
$sum / $avg / $min / $max合計/平均/最小/最大
$first / $last先頭/末尾
$push / $addToSet配列化
$concat文字列連結
$toUpper / $toLower大文字/小文字
$dateToString日付を文字列化
$condif 式
$ifNullnull 時のデフォルト

注意: COLLSCAN(コレクションスキャン)がexplain()で表示されたら、インデックスが効いていない証拠。適切なインデックスを追加しましょう。

実践メモ: TTLインデックスを使えば、セッションやログなどの一時データを自動削除できます。expireAfterSecondsで有効期限を指定します。

トラブルシューティング

状況原因 / 対処
E11000 duplicate keyユニークインデックス違反。既存値を確認
クエリが遅いexplain("executionStats")COLLSCAN を確認し、インデックス追加
$lookup が遅いlocalField / foreignField にインデックスを張る
トランザクション不可スタンドアロンではなくレプリカセット/シャードが必要
_id を変更したい不可。新ドキュメント挿入 + 旧削除で対応
日付比較が効かない文字列ではなく ISODate / new Date() を使用

Tips

  • 本番ではユニーク制約や必須フィールドに必ずインデックスを張る。
  • find() は Cursor を返す。大量データは for (const doc of cursor) で反復。
  • $match はパイプラインの先頭に置き、インデックスを効かせる。
  • ObjectId は生成時刻を含むので、_id で時系列ソートが概ね可能。
  • スキーマ検証には $jsonSchema バリデータを使う。
  • Atlas を使う場合はネットワーク IP 許可リストの設定を忘れない。

代表的なドライバ(Node.js 例)

import { MongoClient, ObjectId } from "mongodb";

const client = new MongoClient(process.env.MONGO_URL);
await client.connect();
const db = client.db("shop");
const users = db.collection("users");

// 挿入
const r = await users.insertOne({ name: "Ada", createdAt: new Date() });

// 取得
const u = await users.findOne({ _id: new ObjectId(id) });

// 一覧
const list = await users
  .find({ active: true })
  .project({ name: 1 })
  .sort({ createdAt: -1 })
  .limit(20)
  .toArray();

// 更新
await users.updateOne({ _id: r.insertedId }, { $set: { active: true } });

// 削除
await users.deleteOne({ _id: r.insertedId });

await client.close();

代表的なドライバ(Python 例 / PyMongo)

from pymongo import MongoClient, ASCENDING
from bson import ObjectId

client = MongoClient("mongodb://localhost:27017")
db = client["shop"]

db.users.insert_one({"name": "Ada"})
doc = db.users.find_one({"_id": ObjectId(id_str)})
for u in db.users.find({"active": True}).sort("createdAt", -1).limit(10):
    print(u)

db.users.create_index([("email", ASCENDING)], unique=True)

ユーザ・ロール管理

コマンド説明
db.createUser({user, pwd, roles})ユーザ作成
db.updateUser(user, {roles})ロール更新
db.dropUser(user)ユーザ削除
db.grantRolesToUser(user, roles)ロール付与
db.revokeRolesFromUser(user, roles)ロール取消
db.getUsers()ユーザ一覧
db.auth(user, pwd)認証

代表的な組込ロール: read, readWrite, dbAdmin, userAdmin, clusterAdmin, root

バックアップとリストア

# 全体バックアップ
mongodump --uri="mongodb://localhost" --out=backup/$(date +%F)

# 特定 DB のみ
mongodump --uri="mongodb://localhost" --db=shop --out=backup/

# リストア(新しい DB 名に)
mongorestore --uri="mongodb://localhost" --nsFrom='shop.*' --nsTo='shop_restored.*' backup/

よくある設計パターン

パターン説明
埋め込み(Embedding)親ドキュメントに子を配列で持つ。1:1 や少数の 1:N に向く
参照(Referencing)子ドキュメントに親の _id を持つ。多対多や大きな子に向く
Bucket時系列を時間単位でまとめて 1 ドキュメントに
Computed集計結果をあらかじめフィールドに保持
Schema VersioningschemaVersion で段階的に移行

インデックスの種類

種類説明
単一フィールド{field: 1} の基本形
複合{a: 1, b: -1} 前方プレフィクスが効く
マルチキー配列フィールドに自動で作成される
テキスト{field: "text"}$text 検索で利用
2dsphereGeoJSON 地理空間検索
ハッシュシャーディング用
ワイルドカード{"$**": 1} 未知のキーに対応
TTL{createdAt: 1} + expireAfterSeconds で自動削除
部分partialFilterExpression で対象を絞る
一意{unique: true} で重複禁止

スキーマ検証($jsonSchema)

db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["email", "createdAt"],
      properties: {
        email: { bsonType: "string", pattern: "^.+@.+$" },
        age: { bsonType: "int", minimum: 0, maximum: 150 },
        createdAt: { bsonType: "date" }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
});

Change Streams(変更通知)

const cs = db.orders.watch([
  { $match: { operationType: { $in: ["insert", "update"] } } }
]);
while (!cs.isClosed()) {
  if (cs.hasNext()) printjson(cs.next());
}

参考リソース

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る