mcpField
M
mongodb

mongodb

github.com/bagelholeデータ・データベース1.2k342 回インストール23 週間前に更新
リポジトリ

mongodb について

開発・本番環境での MongoDB の管理を支援するスキルです。セットアップ、セキュリティ、性能調整、トラブルシューティングを扱い、ドキュメントデータベースを運用するエンジニア向けです。

主な機能

  1. 01インストールと初期設定
  2. 02ユーザー認証とセキュリティ設定
  3. 03インデックスと集計の最適化
  4. 04レプリカセットの構成
  5. 05バックアップ、復元、監視
  6. 06一般的な問題のトラブルシューティング

活用シーン

  1. 01MongoDB データベースの構築
  2. 02アプリケーションユーザーと認証の設定
  3. 03クエリと集計の性能調整
  4. 04データベースのバックアップとサーバー状態の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill mongodb

インストール後、Claude Code で/mongodbを入力して読み込まれたか確認します。

詳細

MongoDB

開発環境および本番環境で、MongoDB の NoSQL データベースを管理、最適化し、安全に保ちます。

使用する場面

  • 柔軟なスキーマを持つドキュメント指向データベースが必要な場合。
  • 半構造化データ、または深くネストされたデータ(JSON のようなドキュメント)を扱う場合。
  • シャーディングによる水平スケーリングが必要な場合。
  • 高度なクエリ機能や集約パイプラインがアプリケーションに役立つ場合。

前提条件

  • Linux サーバー(Debian/Ubuntu または RHEL ベース)または Docker。
  • パッケージのインストールに必要な root または sudo アクセス。
  • 本番環境では MongoDB 7.x を推奨します(6.x も引き続きサポートされています)。

インストールとセットアップ

# Debian / Ubuntu — MongoDB 7
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
  sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] \
  https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
  sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
sudo apt update
sudo apt install -y mongodb-org

# Start and enable
sudo systemctl enable --now mongod

# Verify
mongosh --eval "db.version()"

初期ユーザーのセットアップ

// Connect without auth first
// mongosh

use admin

// Create admin user
db.createUser({
  user: "admin",
  pwd: "strong_admin_password",
  roles: [
    { role: "userAdminAnyDatabase", db: "admin" },
    { role: "readWriteAnyDatabase", db: "admin" },
    { role: "clusterAdmin", db: "admin" }
  ]
})

// Create an application-scoped user
use mydb
db.createUser({
  user: "myapp",
  pwd: "strong_app_password",
  roles: [{ role: "readWrite", db: "mydb" }]
})

/etc/mongod.conf で認証を有効にします。

security:
  authorization: enabled
sudo systemctl restart mongod
# Now connect with credentials
mongosh -u myapp -p strong_app_password --authenticationDatabase mydb

mongosh コマンドのリファレンス

// Show databases and collections
show dbs
use mydb
show collections

// Insert documents
db.users.insertOne({ name: "Alice", email: "[email protected]", age: 30 })
db.users.insertMany([
  { name: "Bob", email: "[email protected]", age: 25 },
  { name: "Carol", email: "[email protected]", age: 35 }
])

// Query documents
db.users.find({ age: { $gte: 25 } }).sort({ name: 1 }).limit(10)
db.users.findOne({ email: "[email protected]" })
db.users.countDocuments({ age: { $gte: 30 } })

// Update
db.users.updateOne(
  { email: "[email protected]" },
  { $set: { age: 31 }, $currentDate: { updatedAt: true } }
)
db.users.updateMany(
  { age: { $lt: 30 } },
  { $set: { tier: "junior" } }
)

// Delete
db.users.deleteOne({ email: "[email protected]" })
db.users.deleteMany({ tier: "junior" })

インデックス作成

// Single-field index
db.users.createIndex({ email: 1 }, { unique: true })

// Compound index
db.orders.createIndex({ userId: 1, createdAt: -1 })

// Text index for search
db.articles.createIndex({ title: "text", body: "text" })
db.articles.find({ $text: { $search: "mongodb scaling" } })

// TTL index — auto-delete documents after 30 days
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 2592000 })

// List indexes
db.users.getIndexes()

// Drop an index
db.users.dropIndex("email_1")

// Explain a query to verify index usage
db.orders.find({ userId: 42 }).explain("executionStats")

集約パイプラインの例

// Revenue per status
db.orders.aggregate([
  { $group: {
      _id: "$status",
      totalRevenue: { $sum: "$total" },
      count: { $sum: 1 }
  }},
  { $sort: { totalRevenue: -1 } }
])

// Top 5 customers by order value (with a join)
db.orders.aggregate([
  { $group: {
      _id: "$userId",
      spent: { $sum: "$total" },
      orderCount: { $sum: 1 }
  }},
  { $sort: { spent: -1 } },
  { $limit: 5 },
  { $lookup: {
      from: "users",
      localField: "_id",
      foreignField: "_id",
      as: "user"
  }},
  { $unwind: "$user" },
  { $project: {
      _id: 0,
      name: "$user.name",
      email: "$user.email",
      spent: 1,
      orderCount: 1
  }}
])

// Daily signup trend
db.users.aggregate([
  { $group: {
      _id: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt" } },
      signups: { $sum: 1 }
  }},
  { $sort: { _id: 1 } },
  { $limit: 30 }
])

レプリカセットのセットアップ

レプリカセットには、最低 3 つのメンバー(またはデータを保持する 2 つのノードとアービター)が必要です。

各メンバーの設定ファイル
# /etc/mongod.conf (adjust port and dbPath per member)
storage:
  dbPath: /var/lib/mongodb
net:
  port: 27017
  bindIp: 0.0.0.0
replication:
  replSetName: rs0
security:
  authorization: enabled
  keyFile: /etc/mongodb-keyfile
# Generate a shared keyfile for internal auth
openssl rand -base64 756 > /etc/mongodb-keyfile
chmod 400 /etc/mongodb-keyfile
chown mongodb:mongodb /etc/mongodb-keyfile
# Copy this file to all replica set members
レプリカセットの初期化
// Connect to the first member
// mongosh --port 27017

rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongo1:27017", priority: 2 },
    { _id: 1, host: "mongo2:27017", priority: 1 },
    { _id: 2, host: "mongo3:27017", priority: 1 }
  ]
})

// Check status
rs.status()

// View replication lag per member
rs.printReplicationInfo()
rs.printSecondaryReplicationInfo()

バックアップと復元

# Full dump of all databases
mongodump --uri="mongodb://admin:secret@localhost:27017" --out=/backups/full_$(date +%F)

# Single database
mongodump --uri="mongodb://myapp:secret@localhost:27017/mydb" --out=/backups/mydb_$(date +%F)

# Compressed dump
mongodump --uri="mongodb://admin:secret@localhost:27017" --gzip --out=/backups/gz_$(date +%F)

# Restore all databases
mongorestore --uri="mongodb://admin:secret@localhost:27017" /backups/full_2025-01-15/

# Restore a single database, dropping existing data first
mongorestore --uri="mongodb://admin:secret@localhost:27017" \
  --drop --db mydb /backups/mydb_2025-01-15/mydb/

# Restore compressed dump
mongorestore --uri="mongodb://admin:secret@localhost:27017" --gzip /backups/gz_2025-01-15/

Docker Compose のセットアップ

# docker-compose.yml
version: "3.9"

services:
  mongo1:
    image: mongo:7
    restart: unless-stopped
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: secret
    volumes:
      - mongo1_data:/data/db
      - ./mongo-keyfile:/etc/mongodb-keyfile:ro
    command: >
      mongod
        --replSet rs0
        --keyFile /etc/mongodb-keyfile
        --bind_ip_all
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      timeout: 5s
      retries: 5

  mongo2:
    image: mongo:7
    restart: unless-stopped
    volumes:
      - mongo2_data:/data/db
      - ./mongo-keyfile:/etc/mongodb-keyfile:ro
    command: >
      mongod
        --replSet rs0
        --keyFile /etc/mongodb-keyfile
        --bind_ip_all

  mongo3:
    image: mongo:7
    restart: unless-stopped
    volumes:
      - mongo3_data:/data/db
      - ./mongo-keyfile:/etc/mongodb-keyfile:ro
    command: >
      mongod
        --replSet rs0
        --keyFile /etc/mongodb-keyfile
        --bind_ip_all

  mongo-init:
    image: mongo:7
    restart: "no"
    depends_on:
      mongo1:
        condition: service_healthy
    entrypoint: >
      mongosh --host mongo1 -u admin -p secret --authenticationDatabase admin --eval '
        rs.initiate({
          _id: "rs0",
          members: [
            { _id: 0, host: "mongo1:27017", priority: 2 },
            { _id: 1, host: "mongo2:27017", priority: 1 },
            { _id: 2, host: "mongo3:27017", priority: 1 }
          ]
        })
      '

volumes:
  mongo1_data:
  mongo2_data:
  mongo3_data:
# Generate keyfile before starting
openssl rand -base64 756 > mongo-keyfile
chmod 400 mongo-keyfile

docker compose up -d

# Connect
mongosh "mongodb://admin:[email protected]:27017/?replicaSet=rs0&authSource=admin"

監視クエリ

// Server status summary
db.serverStatus().connections
db.serverStatus().opcounters

// Current operations (look for long-running queries)
db.currentOp({ secs_running: { $gte: 5 } })

// Collection stats
db.orders.stats()

// Index sizes
db.orders.stats().indexSizes

// Profiler — log slow queries (> 100ms)
db.setProfilingLevel(1, { slowms: 100 })
db.system.profile.find().sort({ ts: -1 }).limit(5)

// Replica set lag
rs.printSecondaryReplicationInfo()

設定のチューニング

# /etc/mongod.conf — production recommendations
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 4          # ~50% of RAM, leave rest for OS cache
    collectionConfig:
      blockCompressor: snappy
net:
  port: 27017
  bindIp: 0.0.0.0
  maxIncomingConnections: 500
operationProfiling:
  mode: slowOp
  slowOpThresholdMs: 100

トラブルシューティング

症状考えられる原因解決方法
explain の出力に COLLSCAN があるクエリ対象のフィールドにインデックスがない適切なインデックスを作成する
レプリカメンバーが RECOVERING のまま停止しているoplog のウィンドウを超過したデータを削除してメンバーを再起動し、再同期する
too many open filesOS のファイルディスクリプターの上限が低すぎるサービスファイルで ulimit -n 65535 を設定する
メモリ使用量が多いWiredTiger のキャッシュが大きすぎる設定で cacheSizeGB を減らす
集約パイプラインが遅い$match ステージのフィールドにインデックスがないインデックスを追加し、パイプラインのできるだけ早い段階に $match を配置する
認証に失敗するauthenticationDatabase が誤っている管理者ユーザーには --authenticationDatabase admin を指定する

関連スキル

  • redis - MongoDB の前段に配置するキャッシュ層
  • database-backups - 自動バックアップ戦略
  • postgresql - 代替のリレーショナルデータベース

コメント