一、mongoose 介绍
- Mongoose 是在 nodeJs 异步环境下对 mongodb 进行便捷操作的对象模型工具。
- Mongoose 是 NodeJS 的驱动,不能作为其他语言的驱动。
- Mongoose 有两个特点
- 1、通过关系型数据库的思想来设计非关系型数据库
- 2、基于 mongodb 驱动,简化操作
1. 安装
npm i mongoose --save复制代码
2、引入 mongoose 并连接数据库
const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/test'); 如果有账户密码需要采用下面的连接方式: mongoose.connect('mongodb://eggadmin:123456@localhost:27017/eggcms'); 复制代码
3、定义 Schema
数据库中的 Schema,为数据库对象的集合。schema 是 mongoose 里会用到的一种数据模式, 可以理解为表结构的定义;每个 schema 会映射到 mongodb 中的一个 collection,它不具备 操作数据库的能力
var UserSchema=mongoose.Schema({ name: String, age:Number, status:'number' })复制代码
4、创建数据模型
定义好了 Schema,接下就是生成 Model。model 是由 schema 生成的模型,可以对数据库的 操作。
注意:
- mongoose.model 里面可以传入两个参数也可以传入三个参数
- mongoose.model(参数 1:模型名称(首字母大写),参数 2:Schema)
- mongoose.model(参数 1:模型名称(首字母大写),参数 2:Schema,参数 3:数据库集合名称)
- 如果传入 2 个参数的话,这个模型会和模型名称相同的复数的数据库建立连接:如通过下面 方法创建模型,那么这个模型将会操作 users 这个集合。
var UserModel=mongoose.model('User', UserSchema); 复制代码
- 如果传入 3 个参数的话:模型默认操作第三个参数定义的集合名称
var UserModel=mongoose.model('User', UserSchema, 'users'); 复制代码
5、查找数据
UserModel.find({}, function(err, docs) { if (err) {console.log(err);return; } console.log(docs); });复制代码
6、增加数据
//实例化模型 传入增加的数据var u = new UserModel({ name: "lisi2222", age: 20, status: true}); u.save();复制代码
7、修改数据
UserModel.updateOne({ name: "lisi2222" }, { name: "哈哈哈" }, function(err, res) { if (err) {console.log(err);return; } console.log("成功"); });复制代码
8、删除数据
UserModel.deleteOne({ _id: "5b72ada84e284f0acc8d318a" }, function(err) { if (err) {console.log(err);return; } //只会删除一条 console.log("成功"); });复制代码
9、保存成功后查找
var u = new UserModel({ name: "lisi2222333", age: 20, status: true //类型转换}); u.save(function(err, docs) { if (err) {console.log(err);return; } //console.log(docs); UserModel.find({}, function(err, docs) {if (err) { console.log(err); return; }console.log(docs); }); });复制代码三、mongoose 模块化
由于所有数据库操作都是基于schema生成的模型(Model),为了免去所有用到的地方都生成Model的麻烦,将其封装,在使用到的地方引入即可。
1、封装
项目目录创建models目录
/* models/db.js 连接数据库 */var mongoose = require("mongoose");//useNewUrlParser这个属性会在url里识别验证用户所需的db,未升级前是不需要指定的,升级到一定要指定。mongoose.connect( "mongodb://usersDB_readwrite:123456@localhost:27017/newsDB", { useNewUrlParser: true, useUnifiedTopology: true }, function (err) {if (err) { console.log(err); return; }console.log("数据库连接成功"); } );module.exports = mongoose;复制代码
/* models/userModel.js 用户表model */var mongoose = require("./db.js");var UserSchema = mongoose.Schema( {account: { type: String, trim: true }, // 账号password: { type: String, trim: true }, // 密码username: { type: String, trim: true }, // 名称email: String, // 邮箱avatar: String, // 头像profile: String, // 简介 }, { versionKey: false } );var userModel = mongoose.model("User", UserSchema, "users");module.exports = userModel;复制代码
2、使用
/* routes/user.js 此处演示express中使用,其它框架一样。 1、引入 2、调用 */var express = require("express");// 引入userModelvar UserModel = require("../models/userModel");var Result = require("../common/Result");var router = express.Router();// 注册接口router.post("/regist", function (req, res, next) { //用接收到的注册参数实例化模型 let newUser = new UserModel(req.body); //调用save保存 newUser.save(function (err) {if (err) { console.log(err); return; } res.json(200, new Result({ msg: "新用户保存成功" })); }); });复制代码四、Mongoose 修饰符
1、预定义模式修饰符
mongoose 提供的预定义模式修饰符,可以对我们增加的数据进行一些格式化。
var UserSchema = mongoose.Schema({ name: { type: String, trim: true }, age: Number, status: { type: Number, default: 1 } });复制代码
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
- Decimal128
1、自定义修饰符(get & set)
除了 mongoose 内置的修饰符以外,我们还可以通过 set(建议使用) 修饰符在增加数据的 时候对数据进行格式化。也可以通过 get(不建议使用)在实例获取数据的时候对数据进行格式化。
// Demovar NewsSchema = mongoose.Schema({ title: "string", author: String, pic: String, redirect: {type: String,set: function(url) { if (!url) return url; // 写入时前缀补全 (会改变数据) if (url.indexOf("http://") != 0 && url.indexOf("https://") != 0) { url = "http://" + url; } return url; },get: function(url) { if (!url) return url; // 读取时前缀补全 (不会改变数据) if (url.indexOf("http://") != 0 && url.indexOf("https://") != 0) { url = "http://" + url; } return url; } }, content: String, status: { type: Number, default: 1 } });复制代码五、Mongoose 索引
索引是对数据库表中一列或多列的值进行排序的一种结构,可以让我们查询数据库变得更 快。MongoDB 的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的查询 优化技巧。
var DeviceSchema = new mongoose.Schema({ sn: {type: Number, // 唯一索引unique: true }, name: {type: String, // 普通索引index: true } });复制代码六、Mongoose CURD
1、 内置CURD
- Model.deleteMany()
- Model.deleteOne()
- Model.find()
- Model.findById()
- Model.findByIdAndDelete()
- Model.findByIdAndRemove()
- Model.findByIdAndUpdate()
- Model.findOne()
- Model.findOneAndDelete()
- Model.findOneAndRemove()
- Model.findOneAndUpdate()
- Model.replaceOne()
- Model.updateMany()
- Model.updateOne()
2、 拓展CURD
var UserSchema=mongoose.Schema({name:{type:String },sn:{type:String,index:true},age:Number, status:{type:Number,default:1} })//静态方法 UserSchema.statics.findBySn=function(sn,callback){//通过 find方法获取 sn的数据 this 关键字获取当前的modelthis.find({"sn":sn},function(err,docs){ callback(err,docs) }) }// 实例方法 (基本不用)UserSchema.methods.print=function(){console.log('我是一个实例方法')console.log(this.name) }复制代码
// 自定义静态方法UserModel.findBySn('123456782',function(err,docs){if(err){console.log(err);return; }console.log(docs) })var user = new UserModel({name: '赵六',sn:'123456781',age: 29});//自定义的实例方法user.print();复制代码七、多表关联查询
1、aggregate
mongoDB aggregate 聚合管道
var mongoose = require("./db.js");var OrderSchema = mongoose.Schema({ order_id: String, uid: Number, trade_no: String, all_price: Number, all_num: Number});var OrderModel = mongoose.model("Order", OrderSchema, "order"); OrderModel.aggregate( [ { $lookup: {from: "order_item",localField: "order_id",foreignField: "order_id",as: "item" } } ], function(err, docs) {// order表关联order_itm表,将order_item的数据赋值给item一并返回console.log(docs); } );复制代码
三个表关联查询
ArticleModel.aggregate([ {$lookup: { from: "articlecate", localField: "cid", foreignField: "_id", as: "cate"} }, {$lookup: { from: "user", localField: "author_id", foreignField: "_id", as: "user"} } ],function(err,docs){ console.log(JSON.stringify(docs)); })复制代码
2、populate 关联查询
var mongoose=require('./db.js');var ArticleSchema = mongoose.Schema({title:{ type: String, unique: true },cid : { type: Schema.Types.ObjectId, ref:"ArticleCate" //cid和 文章分类建立关系。(model名称) }, /*分类 id*/author_id:{ type: Schema.Types.ObjectId ,ref:"User" //author_id和 用户表建立关系。(model名称)}, /*用户的id*/author_name:{ type:String },descripton:String, content : String});module.exports=mongoose.model('Article',ArticleSchema,'article');复制代码
//注意使用 populate需要引入用到的modelvar ArticleCateModel=require('./model/articlecate.js');var ArticleModel=require('./model/article.js');var UserModel=require('./model/user.js');//文章表和 分类表的关联ArticleModel.find({}).populate('cid').exec(function(err,docs){ console.log(docs); })//三个表关联ArticleModel.find({}).populate('cid').populate('author_id').exec(function(err,docs){ console.log(docs); })复制代码
建议使用管道方式关联查询(aggregate)