MongoDBモデル操作のためのMongoose入門

Mongooseとは何か

Mongooseは、Node.js環境においてMongoDBを扱いやすくするためのオブジェクトデータモデリング(ODM)ライブラリです。データベースのドキュメントに対する作成、読み取り、更新、削除などの操作を、JavaScriptオブジェクトを通じて直感的に行えるように抽象化しています。

基本的な導入と接続方法

KoaやExpressなどのフレームワークと組み合わせて使用する場合、まずnpmでインストールします。

npm install mongoose --save

--save-devではなく--saveを使用するのが一般的です。実行時にも必要なため、開発依存ではなく通常の依存として登録します。

モジュールを読み込みます。

const mongoose = require('mongoose');

ローカルのMongoDBインスタンスに接続します。デフォルトポートは27017です。

mongoose.connect('mongodb://localhost:27017/myapp', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

接続オプションは最新バージョンで必須となっています。

接続状態の監視

接続結果や状態変化をイベントリスナーで監視できます。

mongoose.connection.on('connected', () => {
  console.log('MongoDBへの接続が確立されました');
});

mongoose.connection.on('error', (err) => {
  console.error('接続エラー:', err);
});

mongoose.connection.on('disconnected', () => {
  console.log('MongoDBとの接続が切断されました');
});

process.on('SIGINT', async () => {
  await mongoose.connection.close();
  process.exit(0);
});

スキーマ設計:データ構造の定義

すべてのモデルはSchemaから始まります。これはコレクション内のドキュメント構造を定義するもので、型やバリデーション、デフォルト値などを指定可能です。

const userSchema = new mongoose.Schema({
  username: { type: String, required: true, trim: true },
  age: { type: Number, min: 0, max: 120 },
  email: { type: String, lowercase: true },
  isActive: { type: Boolean, default: true },
  createdAt: { type: Date, default: Date.now },
  tags: [String],
  location: {
    type: { type: String, enum: ['Point'], default: 'Point' },
    coordinates: { type: [Number], default: [0, 0] }
  }
});

GeoJSON形式での位置情報もネイティブサポートされています。

モデルの生成と使用

定義したスキーマからモデルを作成します。このモデルを使って実際にデータベース操作を行います。

const User = mongoose.model('User', userSchema);

第一引数はMongoDB上でのコレクション名(複数形に自動変換)です。

データ挿入(Create)

新しいドキュメントを作成して保存します。

const createUser = async () => {
  const newUser = new User({
    username: 'tanaka',
    age: 28,
    email: 'tanaka@example.com',
    tags: ['developer', 'js']
  });

  try {
    const savedUser = await newUser.save();
    console.log('保存成功:', savedUser);
  } catch (err) {
    console.error('保存失敗:', err.message);
  }
};

データ検索(Read)

find()メソッドを使用して条件に合致するドキュメントを取得します。

const fetchUsers = async () => {
  try {
    const users = await User.find({ isActive: true })
                           .select('username age email')
                           .limit(10)
                           .sort({ createdAt: -1 });

    console.log(users);
  } catch (err) {
    console.error(err);
  }
};

select()で返却フィールドを制限し、sort()limit()で整形できます。

条件検索の高度な使い方

MongoDBのクエリ演算子を使い、柔軟な検索が可能です。

// 年齢が18以上かつ35以下
User.find({ age: { $gte: 18, $lte: 35 } });

// 複数条件のいずれかに一致(OR)
User.find({ $or: [{ age: { $lt: 20 } }, { username: 'admin' }] });

// 正規表現による部分一致
User.find({ username: { $regex: /tarou/, $options: 'i' } });

// 配列内に特定の値が含まれる
User.find({ tags: { $in: ['premium', 'vip'] } });

// フィールドの存在確認
User.find({ email: { $exists: true } });

// 地理空間クエリ(半径5km以内)
User.find({
  location: {
    $near: {
      $geometry: { type: 'Point', coordinates: [139.76, 35.68] },
      $maxDistance: 5000
    }
  }
});

動的クエリの例(Koaルーター応用)

router.get('/users', async (ctx) => {
  const { q, minAge, maxAge, limit = 20 } = ctx.query;
  const filter = {};

  if (q) filter.$text = { $search: q };
  if (minAge) filter.age = { ...filter.age, $gte: Number(minAge) };
  if (maxAge) filter.age = { ...filter.age, $lte: Number(maxAge) };

  try {
    const results = await User.find(filter).limit(parseInt(limit));
    ctx.body = { code: 0, data: results, message: '取得成功' };
  } catch (err) {
    ctx.body = { code: 1, data: [], message: '取得失敗: ' + err.message };
  }
});

クエリパラメータに基づいて動的に検索条件を構築しています。

タグ: Mongoose MongoDB Node.js odm express

7月29日 20:26 投稿