Egg配合MongoDB日常开发和注意事项
Mercer-Lee的空间 2019-11-03
Egg
JS
MongoDB
Node
# 连接 MongoDB
这里我们先安装 ORM:
$ npm install egg-mongoose
然后分别在插件文件和配置文件声明:
// config/config.default.js
"use strict";
module.exports = appInfo => {
// 数据库配置
config.mongoose = {
url: "mongodb://localhost:27017/demo",
options: {
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false // 可以关闭findOneAndUpdate()、findOneAndDelete()这些弃用API的警告
}
};
return {
...config
};
};
// config/plugin.js
"use strict";
exports.mongoose = {
enable: true,
package: "egg-mongoose"
};
# 创建 Schema
在 app 目录下建立 model 目录,然后添加 user.js 文件
// app/model/user.js
module.exports = app => {
const mongoose = app.mongoose;
const { Schema } = mongoose;
const userSchema = new Schema({
username: { type: String, required: true, minlength: 3 },
password: { type: String, required: true },
avatar: { type: String, default: "" },
email: { type: String, default: "" }
});
userSchema.index({ username: 1 }, { unique: true });
userSchema.index({ email: 1 }, { unique: true });
return mongoose.model("User", userSchema);
};
# 操作数据库
然后我们在 service 下试着写一下对于 MongoDB 的操作:
// app/service/user.js
"use strict";
const Service = require("egg").Service;
class UserService extends Service {
async addUser(userData) {
return new this.ctx.model.User(userData).save();
}
async getUserOne(conditions) {
return this.ctx.model.User.findOne(conditions);
}
}
module.exports = UserService;
接着在 controller 写注册用户的逻辑:
"use strict";
const Controller = require("egg").Controller;
class UserController extends Controller {
constructor(ctx) {
super(ctx);
this.userValidate = {
email: { type: "email" },
password: { tpe: "password", required: true, min: 5 },
username: { type: "string", required: true, min: 3 }
};
}
/**
* @description 注册
*/
async register() {
const { ctx, service } = this;
ctx.validate(this.userValidate, ctx.request.body);
const { username, password, email } = ctx.request.body;
password = ctx.genHash(password);
const user = await service.user.getUser({ $or: [{ username }, { email }] });
if (!user) {
await service.user.addUser({
username,
password,
email
});
ctx.helper.success({ ctx });
} else {
ctx.throw(422, "用户已经存在");
}
}
}
module.exports = UserController;
最后在 router 挂载对应的 controller:
"use strict";
module.exports = app => {
const { router, controller } = app;
router.post("/user/loginRegister/register", controller.user.register);
};
# 注意事项
如果是以前有过 express 开发经验的朋友,肯定有一些很喜欢在 mongoose 的操作里面写回调函数,但是在 egg 或其他基于 koa 的框架中是不建议这么做的。因为 koa 抛弃了传统的 callback,而拥抱了 async,所以日常的开发中我们需要抛弃掉 express 的开发思想,调用异步 service 的时候 async 和 await 的组合更有效且安全。如果是同时调用几个异步 service,那么 Promise.all()是一个很好的解决方案。比如:
/**
* @description 获取用户发表过的文章
*/
async getUserArticle() {
const { ctx, service } = this;
const { _id: userId } = await service.user.veriifyToken({ required: true });
const { articleId } = ctx.query;
const { numberOfPage } = ctx.params;
const article = service.article.getArticleListTimeLine({ author: userId }, articleId, Number(numberOfPage));
const articleLength = service.article.getArticleListCount({ author: userId });
await Promise.all([article, articleLength]).then(res => {
const [article, articleLength] = res;
ctx.helper.success({ ctx, data: { article, articleLength } })
})
}