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 };
}
});
クエリパラメータに基づいて動的に検索条件を構築しています。