Mongoose入门

1,677 阅读5分钟

本文为学习记录。不随官网更新!

深入了解请前往mongoose官方文档

相关文章MongoDB 基础操作集

一、mongoose 介绍

  • Mongoose 是在 nodeJs 异步环境下对 mongodb 进行便捷操作的对象模型工具。
  • MongooseNodeJS 的驱动,不能作为其他语言的驱动。
  • Mongoose 有两个特点
    • 1、通过关系型数据库的思想来设计非关系型数据库
    • 2、基于 mongodb 驱动,简化操作

二、mongoose 的安装以及使用

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");
// 引入userModel
var 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(不建议使用)在实例获取数据的时候对数据进行格式化。

// Demo
var 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 关键字获取当前的model
    this.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需要引入用到的model
var 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)