mongoose 简介

Mongoos 的安装

yarn add mongoose

定义数据结构(Schema定义数据的数据结构)

const mongoose = require('mongoose')
const ProductSchema = mongoose.Schema({
    id: {
        type: String,
        default: uuid.v1,
        required:  true
    },
    comments: [{ body: String, date: Date }],
    name: String,
    price: Number,
    url: String
});

Schema只是定义了数据结构,而对数据的处理需要model去实现

const Product = mongoose.model('Product', ProductSchema);
module.exports = Product;

Mongoose 的 SchemaTypes(模式类型)

const egSchema = new mongoose.Schema( SchemaTypes )

1、SchemaTypes(模式类型的Type属性)

  • StringNumberDateBufferBooleanMixedObjectId(要指定类型为 ObjectId,在声明中使用 Schema.Types.ObjectId) 、ArrayDecimal128

2、required 布尔值或函数 如果值为真,为此属性添加 required 验证器。

3、default: 任何值或函数 设置此路径默认值。如果是函数,函数返回值为默认值。

4、select: 布尔值 指定 query 的默认 projections。

5、validate: 函数 adds a validator function for this property。

6、get: 函数 使用 Object.defineProperty() 定义自定义 getter。

7、set: 函数 使用 Object.defineProperty() 定义自定义 setter。

8、alias: 字符串 仅mongoose >= 4.10.0。 为该字段路径定义虚拟值 gets/sets。

索引相关

9、index: 布尔值 是否对这个属性创建索引。

10、unique: 布尔值 是否对这个属性创建唯一索引。

11、sparse: 布尔值 是否对这个属性创建稀疏索引。

connection 链接数据库 mongoose.connect(uri, options);

在db.js里面

moudle.exports = app => {
  const mongoose =  require('mongoose');
  const dbUrl = 'mongodb://username:password@hostname:port/databasename'
  mongoose.connect(dbUrl,{
       useNewUrlParse: true
  });
  const db = mongoose.connection;
  db.on('error', console.error.bind(console, 'connection error:'));
}

在app.js里面

const express = require('express')
const app = express()
require('../database/db.js')(app)

连接池 connection

无论是使用 mongoose.connect 或是 mongoose.createConnection 创建的连接, 都被纳入默认最大为 5 的连接池,可以通过 poolSize 选项调整:


mongoose.createConnection(uri, { poolSize: 4 });
const uri = 'mongodb://localhost/test?poolSize=4';
mongoose.createConnection(uri);

模型 models

Models 是从 Schema 编译来的构造函数。 它们的实例就代表着可以从数据库保存和读取的 documents。 从数据库创建和读取 document 的所有操作都是通过 model 进行的。

主表blog

const mongoose = require('mongoose')

const blogSchema = new mongoose.Schema({
    title: {type: String}, //博客题目
    abstract: {type: String}, //摘要
    content: {type: String}, //文章内容
    click: {type: Number},//点击量
    createtime: {type: String} //消费时间
})
module.exports = mongoose.model('Blog', blogSchema)

子表label

const mongoose = require('mongoose')
const labelSchema = new mongoose.Schema({
    blogid: {type: mongoose.Schema.Types.ObjectId, ref: 'blog'},//这里即为子表的外键,关联主表。  ref后的blog代表的是主表blog的Model。
    label: {type: String} //标签名
});

关联查询

labelModel.find({}).populate('blogid').exec(function(err,docs){})

哪里需要模型就去哪里去引用, 新增数据

const userModel = require('../models/userModel')
const user = new userModel({
  userName:'nickName',
  password: 'password'
})
user.save().then(res => console.log(res))

query 查询方法

新增数据

Model.create(docs, callback) 新增数据

const model = require('../models/model');
model.create({
  "productId":String,
   "productName":String,
   "salePrice":String,
   "productImage":String,
   "checked":String,
   "productNum":String
}).then(res=> console.log(res));

modelData.save();

const User = require('../models/user')
const admin = new User({
  username:'admin',
  password:'123456',
  email:'admin@admin.com'
})
admin.save(function(err,ret){})

Model.insertMany(docs, options, callback ) 插入多条数据

const blogSchema = require('../models/blog');
blogSchema.insertMany(blogs,(err) => {
    console.log(err);
  });

查询数据

Model.find(condition: FilterQuery, projection: any|null, options: QueryOptions, callback: Function): QueryWithHelpers<Array, DocType, THelpers, RawDocType>; 查找符合条件的内容

  • 查询条件 condition
  • field字段 projection 比如只查询 name 和friends 字段 ''
  • projection字段 包括分页信息
await Model.find({ name: /john/I }, 'name friends', { skip: 10 })

模糊查询 使用正则表达式 let regexp = new RegExp(xxx, 'i') 来匹配需要查询的 关键词。

@Injectable()
export class AppService {
  constructor(
    @InjectModel(User.name) private readonly userDao: Model<userModel>,
    @InjectModel(Post.name) private readonly postDao: Model<postModel>,
  ) { }
  
  async test() {
    let regexp = new RegExp('证书','i')
    return this.postDao.find({ content: { $regex: regexp }}, null , { populate: {path: 'users'} });
  }
}

如果是多个字段都要使用模糊匹配请使用$or

return await this.postDao.find({
  $or:[{ title: { $regex: regexp } }, { content: { $regex: regexp } },{ author: { $regex: regexp } } ]
})

Model.findOne(condition:FilterQuery, projection:any | null , options:QueryOptions, callback:Function) QueryWithHelpers<Array, DocType, THelpers, RawDocType>;查找符合条件的内容

await Model.findOne({ type: 'iphone' }, 'name', { lean: true });
await  Model.findOne({ type: 'iphone' }).select('name').lean().exec(callback);

Model.findById(id:Object|String|Number, projection: Object, options:QueryOptions, callback) 根据ID查找符合条件的内容

await Adventure.findById(id, 'name', { lean: true });
await Adventure.findById(id, 'name').lean().exec();

Model.count(conditions:FilterQuery)

await Adventure.count({ type: 'jungle' })

更新数据

更新多条数据

Model.update(conditions, docs,options,callback) 更新数据

Model.updateMany(conditions, docs, options, callback) 更新多条数据

更新单条数据

Model.findOneAndUpdate(conditions, update, options, callback) 查询并更新内容

Model.findByIdAndUpdate(id, update, options, callback ) 根据id查询并更新当前数据

Model.updateOne(conditions, options, callback ) 更新单条数据

删除数据

Model.remove()

const User = require('../models/user');
User.remove({username:'admin'},function(err,ret){})

Model.findOneAndRemove(conditions, delete, options ,callback) 查找并删除并当前数据

Model.findByIdAndRemove(conditions, delete, options ,callback) 根据id删除当前数据

中间件 Middleware

中间件 (pre 和 post 钩子) 是在异步函数执行时函数传入的控制函数。Mongoose 4.x 有四种中间件: document 中间件model 中间件aggregate 中间件,和 query 中间件

1、document 中间件

  • init
  • validate
doc.validate(function (err) {
  if (err) handleError(err);
  else // validation passed
});
  • save
product.sold = Date.now();
product.save(function (err, product) {
  if (err) ..
})
  • remove
product.remove(function (err, product) {
  if (err) return handleError(err);
  Product.findById(product._id, function (err, product) {
    console.log(product) // null
  })
})

2、query 中间件

  • count
var countQuery = model.where({ 'color': 'black' }).count();

query.count({ color: 'black' }).count(callback)

query.count({ color: 'black' }, callback)

query.where('color', 'black').count(function (err, count) {
  if (err) return handleError(err);
  console.log('there are %d kittens', count);
})
  • find
  • findOne
  • findOneAndRemove
  • findOneAndUpdate
  • update

aggregate 中间件

query 中间件

验证 Validators

Mongoose 有一些内建验证器。

所有 SchemaTypes 都有内建 required 验证器。required 验证器使用 checkRequired() 函数 判定这个值是否满足 required 验证器

  • Numbersminmax 验证器.

  • `Strings 有 enum、 match、 maxlength 和 minlength 验证器

Populate(填充) 的关联查询

Population 可以自动替换 document 中的指定字段,替换内容从其他 collection 获取。 我们可以填充(populate)单个或多个 document、单个或多个纯对象,甚至是 query 返回的一切对象。

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var personSchema = Schema({
  _id: Schema.Types.ObjectId,
  name: String,
  age: Number,
  stories: [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});

var storySchema = Schema({
  author: { type: Schema.Types.ObjectId, ref: 'Person' },
  title: String,
  fans: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});

var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);

现在我们创建了两个 Model。Person model 的 stories 字段设为 ObjectId数组。 ref 选项告诉 Mongoose 在填充的时候使用哪个 model,本例中为 Story model。 所有储存在此的 _id 都必须是 Story model 中 document 的 _id。

注意: ObjectId、Number、String 以及 Buffer 都可以作为 refs 使用。 但是最好还是使用 ObjectId,除非你是进阶玩家,并且有充分理由使用其他类型 作为 refs。

Population的实际运用

主表

//博客schema
var blogSchema = new mongoose.Schema({
    title: {type: String}, //博客题目
    abstract: {type: String}, //摘要
    content: {type: String}, //文章内容
    click: {type: Number},//点击量
    createtime: {type: String} //消费时间
})

//创建model,第三个参数是实际表名
var blogModel = db.model("blog", blogSchema, "blog");

子表

//标签表
var labelSchema = new mongoose.Schema({
    blogid: {type: mongoose.Schema.Types.ObjectId, ref: 'blog'},//这里即为子表的外键,关联主表。  ref后的blog代表的是主表blog的Model。
    label: {type: String} //标签名
});

//创建model,第三个参数是实际表名
var labelModel = db.model("label", labelSchema, "label");

插入数据

//1.主表插入数据
blogModel.create({...}, function (err, doc) {
       if(err) return xxx;
       //2.子表插入数据。 blogid为刚插入主表的主键
       labelModel.create({blogid: doc._id, label: label}, function (err, doc) {
if (err) return xxx;
       })
})

关联查询

//子表关联主表查询,populate里面为子表外键
labelModel.find({}).populate('blogid').exec(function(err,docs){
     
})

聚合查询

//MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果; 注意_id,num_tutorial这两个字段都不能变(固定写法)
labelModel.aggregate([{$group : {_id : "$label", num_tutorial : {$sum : 1}}}],function(err,docs){
console.log(docs)
})

posted @ 2021-01-06 11:46  boygdm  阅读(710)  评论(0编辑  收藏  举报