Node.js 蚕食计划(七)—— Koa + GraphQL + MongoDB + Vue 初体验
首先需要搭建一个简单的应用
前端部分不多赘述,如果确实没接触过 Vue 项目,可以参考我的《Vue 爬坑之路》系列
后端服务可以参考之前的文章《Node.js 蚕食计划(六)—— MongoDB + Koa 入门》
完整的项目地址:https://github.com/wisewrong/Test-GraphQL-App,结合项目食用本文更香哦~
一、Mongoose
在上一篇文章《Node.js 蚕食计划(六)》里,直接使用了 mongodb 中间件来连接数据库,并尝试着操作数据库
但我们一般不会直接用 MongoDB 的原生函数来操作数据库,Mongoose 就是一套操作 MongoDB 数据库的接口
1. Schema 与 Model
Schema 是 Mongoose 的基础,用来定义集合的数据模型,也就是传统意义上的表结构
const mongoose = require('mongoose'); const Schema = mongoose.Schema; // 影片信息 const MovieSchema = new Schema({ name: String, // 影片名称 years: Number, // 上映年代 director: String, // 导演 category: [String], // 影片类型 comments: [ // 影评 { author: String, createdAt: { type: Date, default: Date.now(), }, updatedAt: { type: Date, default: Date.now() } } ], }); module.exports = mongoose.model('Movie', MovieSchema);
上面的最后一行代码,是基于定义好的 Schema 生成 Model,我们可以通过 Model 来操作数据库
mongoose.model('ModelName', SchemaObj)
这里的 model() 方法可以接收两个参数,第二个参数是创建好的 Schema 实例
第一个参数 ModelName 是数据库中集合 (collection) 名称的单数形式,Mongoose 会查找名称为 ModelName 复数形式的集合
对于上例,Movie 这个 model 就对应数据库中 movies 这个 collection,如果数据库没有对应的集合会自动创建
2. Model 的增删改查
在 mongoose 中是通过操作 Model 来实现数据库的增删改查
< 新增 >
Model.create(data, callback)
< 查询 >
// 返回所有符合查询条件 conditions 的数据 Model.find(conditions, callback); // 返回找到的第一个文档 Model.findOne(conditions, callback); // 只针对主键 _id 查询 Model.findById('_id', callback);
< 修改 >
// 批量修改符合条件 conditions 的数据 Model.updateMany(conditions, update, options, callback) // 修改指定 id 的数据 Model.findByIdAndUpdate(id, update, options , callback) // 修改第一个符合查询条件的数据 Model.updateOne(conditions, update, options , callback) // 替换第一个符合查询条件的数据 Model.replaceOne(conditions, update, options , callback)
< 删除 >
// 删除符合条件的所有数据 Model.remove(conditions, callback); // 删除指定 id 的数据 Model.findByIdAndRemove(id, options, callback);
比如封装一个插入数据的方法:
const Movie = require('../mongodb/models/movie'); // 新建电影 const createMovie = (req) => { return Movie.create(req); } // 更新电影信息 const updateMovie = (req) => { return Movie.findByIdAndUpdate(req._id, req, { new: true, }); } // 保存电影 const saveMovie = async (ctx, next) => { const req = ctx.request.body; // 校验必填 if (!req.name) { return { message: '影片名称不能为空' } } const data = req._id ? await updateMovie(req) : await createMovie(req); return { data }; }; module.exports = { saveMovie, };
mongoose 也有更规范的查询条件,可以参考官网的 Query 配置
3. 连接数据库
使用 mongoose.connect 连接数据库,可以在 connect 方法中传入第二个参数作为回调
也可以通过 mongoose.connection.on 来监听相应的事件
/* /mongodb/index.js */ const mongoose = require("mongoose"); const { dbUrl } = require("../config"); // const dbUrl = 'mongodb://127.0.0.1:27017/Movie'; // 数据库地址 const connect = () => { // mongoose.set('debug', true) mongoose.connect(dbUrl); mongoose.connection.on("disconnected", () => { mongoose.connect(dbUrl); }); mongoose.connection.on("error", (err) => { console.error('Connect Failed: ', err); }); mongoose.connection.on("open", async () => { console.log('