MongoDB 集成与 ORM 使用
MongoDB 集成
MongoDB 是一种流行的 NoSQL 数据库,以其灵活性和可扩展性著称。在 Koa2 中集成 MongoDB 通常通过官方驱动 mongodb
或更高级的 ODM(如 mongoose
)实现。以下是两种方式的详细对比和实现步骤。
使用原生 MongoDB 驱动
原生驱动提供了最直接的 MongoDB 操作接口,适合需要精细控制查询的场景。首先安装依赖:
npm install mongodb
连接数据库的典型代码如下:
const { MongoClient } = require('mongodb');
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
async function connectDB() {
try {
await client.connect();
console.log('Connected to MongoDB');
return client.db('mydatabase');
} catch (err) {
console.error('Connection error:', err);
process.exit(1);
}
}
// 在Koa中间件中使用
app.use(async (ctx, next) => {
ctx.db = await connectDB();
await next();
});
基本 CRUD 操作示例:
// 插入文档
await ctx.db.collection('users').insertOne({
name: 'Alice',
age: 28,
tags: ['developer', 'designer']
});
// 查询文档
const user = await ctx.db.collection('users')
.findOne({ name: 'Alice' });
// 更新文档
await ctx.db.collection('users')
.updateOne(
{ name: 'Alice' },
{ $set: { age: 29 } }
);
使用 Mongoose ODM
Mongoose 提供了 Schema 定义、数据验证等高级功能。安装方式:
npm install mongoose
典型连接和模型定义:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mydatabase');
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
age: { type: Number, min: 18 },
createdAt: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
在 Koa 中的使用示例:
app.use(async ctx => {
// 创建文档
const newUser = await User.create({
name: 'Bob',
age: 25
});
// 查询带条件
const users = await User
.find({ age: { $gt: 20 } })
.sort('-createdAt')
.limit(10);
});
ORM 高级技巧
事务处理
MongoDB 4.0+ 支持多文档事务,这在需要原子性操作的场景中非常关键:
const session = await mongoose.startSession();
session.startTransaction();
try {
await User.create([{
name: 'Charlie',
age: 30
}], { session });
await Account.create([{
userId: '...',
balance: 1000
}], { session });
await session.commitTransaction();
} catch (err) {
await session.abortTransaction();
throw err;
} finally {
session.endSession();
}
聚合管道
复杂数据分析时,聚合管道比简单查询更强大:
const result = await User.aggregate([
{ $match: { age: { $gte: 21 } } },
{ $group: {
_id: '$name',
total: { $sum: 1 }
}}
]);
性能优化
- 索引优化:
userSchema.index({ name: 1, age: -1 });
- 查询选择性:
// 避免全表扫描
User.find().where('age').gt(20).select('name');
- 批量操作:
// 批量插入比单条循环快10倍以上
User.insertMany([
{ name: 'User1' },
{ name: 'User2' }
]);
实际应用场景
用户管理系统
完整用户管理模块示例:
// 控制器方法
class UserController {
async list(ctx) {
const { page = 1, size = 10 } = ctx.query;
const users = await User.find()
.skip((page - 1) * size)
.limit(Number(size));
ctx.body = users;
}
async create(ctx) {
const user = new User(ctx.request.body);
await user.save();
ctx.status = 201;
}
}
// 路由配置
router.get('/users', UserController.list);
router.post('/users', UserController.create);
实时数据统计
结合 WebSocket 的实时报表系统:
const changeStream = User.watch();
changeStream.on('change', (change) => {
io.emit('user_change', change);
});
错误处理与调试
常见错误类型
- 连接错误:
mongoose.connection.on('error', err => {
console.error('DB connection error:', err);
});
- 验证错误:
try {
await user.save();
} catch (err) {
if (err.name === 'ValidationError') {
console.log(err.errors);
}
}
调试技巧
启用查询日志:
mongoose.set('debug', true);
性能分析:
const start = Date.now();
await User.find().explain('executionStats');
console.log(`Query took ${Date.now() - start}ms`);
扩展与集成
多数据库连接
同时连接多个 MongoDB 实例:
const conn1 = mongoose.createConnection('mongodb://localhost/db1');
const conn2 = mongoose.createConnection('mongodb://localhost/db2');
与 GraphQL 集成
创建 GraphQL 解析器:
const resolvers = {
Query: {
users: async () => await User.find()
},
Mutation: {
createUser: async (_, { input }) => {
return await User.create(input);
}
}
};
TypeScript 支持
定义 Mongoose 模型接口:
interface IUser extends mongoose.Document {
name: string;
age?: number;
}
const User = mongoose.model<IUser>('User', userSchema);
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:MySQL 数据库连接与操作
下一篇:Redis 缓存集成方案