🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 简介 Mongoose 库简而言之就是在 Node.js 环境中操作 MongoDB 数据库的一种便捷的封装,一种对象模型工具,Mongoose 将数据库中的数据转换为 JavaScript 对象以供你在应用中使用。(即可以通过 JavaScript 代码在 Node.js 环境下去操作 MongoDB 数据库)。 # 连接数据库 * 新建项目目录 mongoose-demo,打开命令行跳转这个项目目录路径执行以下命令: ~~~ npm init -y npm install mongoose ~~~ * 编写 01.db.js,文件位置 mongoose-demo/01.db.js,内容如下: ~~~ const mongoose = require('mongoose'); const DB_URL = 'mongodb://localhost/test'; ​ // 连接 mongoose.connect(DB_URL); ​ // 给事件 connected 绑定处理函数,当连接成功时执行 mongoose.connection.on('connected', () => {        console.log('Mongoose connection open to ' + DB_URL);   });     // 给事件 error 绑定处理函数,当连接错误时执行 mongoose.connection.on('error', (err) => {        console.log('Mongoose connection error: ' + err);   });     // 给事件 disconnected 绑定处理函数,当连接断开时执行 mongoose.connection.on('disconnected', () => {        console.log('Mongoose connection disconnected');   }); ~~~ 注意: * 上面代码执行完之后,相当于在程序与数据库之间架起一座桥梁,只有这桥梁架设好了,才能使用代码完成对数据库的操作,且这桥梁的只需架设一次就好了。 * 上述只最简单的连接形式,当然还有其它形式,比如:设置连接密码等,更多参考([https://mongoosejs.com/docs/api.html#index-js](https://mongoosejs.com/docs/api.html#index-js))。 # Mongoose 中的术语 * Schema:Mongoose 中的所有内容都以 Schema 开头。每个 Schema 都映射到 MongoDB 集合,并定义该集合中文档的结构。 * Model:由 Schema 生成的模型,其实例称为 Document。**一般用来负责从 MongoDB 查询文档,修改文档,删除文档**。 * Document:Mongoose 中 Document 与存储在 MongoDB中 的文档的一对一映射。每个文档都是其模型的一个实例。**一般用来负责向 MongoDB 保存文档**。 Schema 类型: * String * Number * Date * Boolean * Array * ObjectId * Buffer * Mixed * Decimal128 * Map ~~~ // 编写 StudentModel.js,文件位置 mongoose-demo/02.StudentModel.js,内容如下: require('./01.db.js'); const mongoose = require('mongoose'); ​ // 定义 Schema const StudentSchema = new mongoose.Schema({    name: String,    age: Number,    score: Number }); ​ // 根据 Schema 编译 Model // 第一个参数是 MongoDB 中集合的名字,可以不加 "s",默认找的时候会加上的 // 第二个参数是 Schema // 若后面保存发现数据库没有对应 students 集合会自动创建 const StudentModel = mongoose.model('student', StudentSchema); // 导出,因为模型在项目会多个地方使用,而定义的话就需一次就可以了,避免定义重复 module.exports = StudentModel; ~~~ # 常用操作 操作之前,须建立数据库连接,及创建对应的模型。 ## 新增文档 ### 方法 * Document.save(\[fn\]):新增文档 ### 代码实现 ~~~ // 编写 save.js,文件位置 mongoose-demo,内容如下: const StudentModel = require("./02.StudentModel.js"); ​ function save() {    // 根据 Model 创建文档    let student = new StudentModel({        name : 'Jerry',                        age: 17,                                    score: 78   });    // 向数据库插入文档,若有错,err 有值,若没有 res 是插入的返回结果    student.save((err, res) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log("Res:" + res);   }); } save(); ~~~ ## 修改文档 常见需求是根据 id 对文档进行修改。 ### 方法 * Model.findByIdAndUpdate(id, \[update\], \[options\], \[callback\]) * Model.update(conditions, update, \[options\], \[callback\]) ### 代码实现 ~~~ // 在 student.js 中以下内容: function update(){    let conditions = {name : 'jerry'};    let update = {score : 99};    let options = { multi: false}; // 默认只改一条,若改成 true,则可改多条    // 更多选项参考,https://mongoosejs.com/docs/api.html#model_Model.update    StudentModel.update(conditions, update, options, (err, res) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log("Res:" + res);   }); } update(); ​ function updateById(){    let id = '5c73af7ed0ccdb347c899f38';    var update = {name : 'Tom'};    // 修改文档,修改的话,res 是修改前文档数据,若该 id 值对应的文档不存在的话,res 是 null    StudentModel.findByIdAndUpdate(id, update, (err, res) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log("Res:" + res);   }); } updateById(); ~~~ ## 删除文档 常见需求是根据 id 删除文档。 ### 方法 * Model.findByIdAndRemove(id, \[options\], \[callback\]) * Model.remove(conditions, \[callback\]) * Model.findOneAndRemove(conditions, \[options\], \[callback\]) ### 代码实现 ~~~ function deleteById(){    let id = '5c73af7ed0ccdb347c899f38';    // 删除文档,若删除成功,res 是被删除的文档数据,若根据 id 没查询到,res 是 null    StudentModel.findByIdAndRemove(id, (err, res) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log("Res:" + res);   }); } deleteById(); ~~~ ## 查询文档 常见需求是根据 id 查询,根据单个条件查询,也可以多个条件,也有查询数据、查询数量,即完成高级查询和分页查询。 ### 方法 * Model.findById(id, \[fields\], \[options\], \[callback\]) * Model.count(conditions, \[callback\]) * Model.find(conditions, \[fields\], \[options\], \[callback\]) ### 代码实现 ~~~ // 根据 id 查询出文档 function getById(){    let id = '5c73ae519d85483d4ce0836e';    let fields = {"name" : 1, "_id" : 0} // 表示要查询的字段,1 表示要查询,0 表示不要查询    // 若查询到 data 是文档数据,若没查询 data 是 null    StudentModel.findById(id, fields, (err, data) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log(data);   }); } getById(); ~~~ ~~~ // 查询出所有文档 function selectAll(){    StudentModel.find({}, (err, data) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log(data);   });    /* 链式操作   StudentModel.find({}).exec((err, data) => {       if (err) {           console.log("Error:" + err);           return;       }       console.log(data);   });*/ } selectAll(); ~~~ ~~~ function query() {    // 根据分数范围查询文档    let conditions1 = {score : {$gte : 18 , $lte : 20}};    StudentModel.find(conditions1).exec((err, data) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log(data);   }); ​    // 根据名字模糊查询    let conditions2 = {$or : [{name : {$regex : /r/i}}]}; // i 表示不区分大小写    StudentModel.find(conditions2, (err, data) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log(data);   });    // 正则表达式后面 i 是表示忽略大小写    let conditions3 = {score : {$gte : 18 , $lte : 20}, $or : [{name : {$regex : /x/i}}]};    StudentModel.find(conditions3, (err, data) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log(data);   }); } query(); ~~~ ~~~ // 分页查询查询文档 function page(){    let currentPage = 1;                        // 当前第几页    let pageSize = 5;                           // 一页多少条    let sort = {score : -1};                    // 1 表示升序,-1 表示降序    let condition = {};                         // 条件    let skip = (currentPage - 1) * pageSize;    //跳过数 ​    StudentModel.find(condition).skip(skip).limit(pageSize).sort(sort).exec((err, data) => {        if (err) {            console.log("Error:" + err);            return;       }        console.log(data);   }); } page(); ~~~ # 总结 Web 应用启动之后不会断了数据库连接的,连接只要创建一次,Model 也在项目只要创建一次就够了。