Mongoose学习

Mongoose学习javascript

1. 说明

由于网上关于mongoose的文档有不少,可是都是分块的没有系统的总结,因此我总结网上的文章理出来一条思路,文档中的不少内容都是从其余文章中复制过来的,只做为我的知识的学习,不会用于商用,在文章多处我也注明了出处html

2. Mongoose介绍

2.1. 什么是MongoDB?

MongoDB是一个开源的NoSQL数据库,相比MySQL那样的关系型数据库,它更为轻巧、灵活,很是适合在数据规模很大、事务性不强的场合下使用。java

2.2. 什么是Mongoose?

Mongoose是封装了MongoDB的操做的一个对象模型库,为nodejs而生。就好像咱们嫌原生javascript难写,代码量多,因而用jQuery库同样,由于MongoDB的操做接口复杂,不人性,因此有了Mongoose。这个库彻底是可选的。node

2.3. 名词解释

  • Schema:一种以文件形式存储的数据库模型骨架,不具有数据库的操做能力
  • Model:由Schema发布生成的模型,具备抽象属性和行为的数据库操做对
  • Entity:由Model建立的实体,他的操做也会影响数据库

2.4. 注意

  • Schema、Model、Entity的关系请牢记,Schema生成Model,Model创造Entity,Model和Entity均可对数据库操做形成影响,但Model比Entity更具操做性。

2.5. 学习文章

3. Schema

3.1. Schema.Type

  • 内置类型git

    String Number Date Buffer Boolean Mixed Objectid Arraygithub

  • 用法实例数据库

var schema = new Schema({
  name:    String,
  binary:  Buffer,
  living:  Boolean,
  updated: { type: Date, default: Date.now },
  age:     { type: Number, min: 18, max: 65 },
  mixed:   Schema.Types.Mixed,
  _someId: Schema.Types.ObjectId,
  array:      [],
  ofString:   [String],
  ofNumber:   [Number],
  ofDates:    [Date],
  ofBuffer:   [Buffer],
  ofBoolean:  [Boolean],
  ofMixed:    [Schema.Types.Mixed],
  ofObjectId: [Schema.Types.ObjectId],
  nested: {
    stuff: { type: String, lowercase: true, trim: true }
  }
})

// example use

var Thing = mongoose.model('Thing', schema);

var m = new Thing;
m.name = 'Statue of Liberty';
m.age = 125;
m.updated = new Date;
m.binary = new Buffer(0);
m.living = false;
m.mixed = { any: { thing: 'i want' } };
m.markModified('mixed');
m._someId = new mongoose.Types.ObjectId;
m.array.push(1);
m.ofString.push("strings!");
m.ofNumber.unshift(1,2,3,4);
m.ofDates.addToSet(new Date);
m.ofBuffer.pop();
m.ofMixed = [1, [], 'three', { four: 5 }];
m.nested.stuff = 'good';
m.save(callback);

3.2. Validation(验证)

  • Validation是在SchemaType定义
  • Validation是中间件的内部组件
  • Validation发生在document试图在默认值应用以后保存的时候。
  • Validation不在未定义的值运行,惟一例外是必要的验证器。
  • Validation是异步递归的,当你调用Model#save,子文档验证也会执行。若是发生错误,Model#save回调会接收它。
  • 验证支持彻底定制

3.2.1. 内置校验器

  • 全部SchemaTypes都有内置requiredValidation。
  • 数字有最大值和最小值验证。
  • 字符串有枚举、匹配、最大长度和最小长度验证。
  • 用法实例
var schema = new mongoose.Schema({
    name:{
        type:'String',
        required: true,
        maxlength: 10,
        match: /^a/   
    },
    date: {
        type: Date,
        default: Date.now
    },
    age:{
        type:'Number',
        min:18,       //年龄最小18
        max:120     //年龄最大120
    },
    city:{
        type:'String',
        enum:['北京','上海']  //只能是北京、上海人
    },
});

3.2.2. 自定义校验器

  • 若是内置验证器不够,validation可以彻底能够知足你的需求
  • 用法实例
var userSchema = new Schema({
  phone: {
    type: String,
    validate: {
      validator: function(v) {
        return /d{3}-d{3}-d{4}/.test(v);
      },
      message: '{VALUE} is not a valid phone number!'
    }
  }
});

var User = mongoose.model('user', userSchema);

var u = new User();

u.phone = '555.0123';
// Prints "ValidationError: 555.0123 is not a valid phone number!"
console.log(u.validateSync().toString());

u.phone = '201-555-0123';
// Prints undefined - validation succeeded!
console.log(u.validateSync());

3.3. 建立

  • 语法:mongoose.model(modelName, schema)
  • 用法实例
var Blog = mongoose.model('Blog', blogSchema)

3.4. 实例方法

  • 用法实例
// define a schema
var animalSchema = new Schema({ name: String, type: String });

// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function (cb) {
  return this.model('Animal').find({ type: this.type }, cb);
}
var Animal = mongoose.model('Animal', animalSchema);
var dog = new Animal({ type: 'dog' });

dog.findSimilarTypes(function (err, dogs) {
  console.log(dogs); // woof
});

3.5. 静态方法

  • 用法实例
// assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function (name, cb) {
  return this.find({ name: new RegExp(name, 'i') }, cb);
}

var Animal = mongoose.model('Animal', animalSchema);
Animal.findByName('fido', function (err, animals) {
  console.log(animals);
});

3.6. 索引

  • MongoDB支持二级索引。在mongoose,at the path level或schema层次定义Schema的索引。当建立复合索引时,在shema定义索引是必要的。
var animalSchema = new Schema({
  name: String,
  type: String,
  tags: { type: [String], index: true } // field level
});

animalSchema.index({ name: 1, type: -1 }); // schema level
  • 当程序启动时,Mongoose为每一个在schema定义的索引自动地调用ensureIndex 。Mongoose会连续为每一个索引调用ensureIndex,当全部ensureIndex调用成功或发生错误在model发出index事件。建议在生产中禁止这种行为由于索引建立可以致使显著的性能影响。经过给schema设置autoIndex选项为false来禁用行为,或者在connection全局设置选项config.autoIndex为false。
animalSchema.set('autoIndex', false);
// or
new Schema({..}, { autoIndex: false });

3.7. Virtuals(虚拟属性)

  • virtual是你能 get 和 set 但不能保存到MongoDB的document属性。getter用于格式化或符合的field,而setter用于de-composing一个单值到多值存储。
  • 用法实例
// define a schema
var personSchema = new Schema({
  name: {
    first: String,
    last: String
  }
});

personSchema.virtual('name.full').get(function () {
  return this.name.first + ' ' + this.name.last;
});

// compile our model
var Person = mongoose.model('Person', personSchema);

// create a document
var bad = new Person({
    name: { first: 'Walter', last: 'White' }
});

console.log('%s is insane', bad.name.full); // Walter White is insane
bad.name.full = 'Breaking Bad';

personSchema.virtual('name.full').set(function (name) {
  var split = name.split(' ');
  this.name.first = split[0];
  this.name.last = split[1];
});

...

mad.name.full = 'Breaking Bad';
console.log(mad.name.first); // Breaking
console.log(mad.name.last);  // Bad

3.8. option(扩展选项)

  • 用法实例
new Schema({..}, options);

// or

var schema = new Schema({..});
schema.set(option, value);

3.9. Middleware(中间件)

  • 中间件(也称为pre and post hook)是执行异步函数期间传递控制权的函数。中间件在schema级别上被指定并对于编写插件很是有用

3.9.1. document中间件和query中间件

  • document中间件支持如下document函数promise

    • init
    • validate
    • save
    • remove
  • query中间件支持如下model和query函数app

    • count
    • find
    • findOne
    • findOneAndRemove
    • findOneAndUpdate
    • update
  • 注意:没有对remove()的query hook,只有对document的。若是你设置了一个remove hook,执行myDoc.remove()时它会激活,而不是执行MyModel.remove()。

3.9.2. pre类型中间件

3.9.3. post类型中间件

3.10. Plugins(插件)

  • schema是可插入的,即,它们能够应用预包装的能力,从而扩展其功能。这是一个很是强大的功能。

4. Model

5. Document

5.1. Population(join)

  • http://www.cnblogs.com/surahe/p/5188211.html
  • population是自动将document中指定path替换为其余collection的document的过程。咱们能迁移document、多个document、简单对象、多个简单对象或者是查询返回的全部对象。

5.2. Sub-Docs(子文档)

6. CURD

6.1. 链接

var mongoose = require('mongoose');    //引用mongoose模块
var db = mongoose.createConnection('localhost','test'); //建立一个数据库链接
  • 打开本机localhost的test数据库时,咱们能够监测是否有异常
db.on('error',console.error.bind(console,'链接错误:'));
db.once('open',function(){
  //一次打开记录
});

6.2. 建立

6.2.1. document保存

var Tank = mongoose.model('Tank', yourSchema);

var small = new Tank({ size: 'small' });
small.save(function (err) {
  if (err) return handleError(err);
  // saved!
})

6.2.2. model保存

  • 语法

  • 该方法既能够存储一条数据也能够存储多条数据
  • 若是有回调函数,那么在存储多条数据的时候若是有一条报错了,那么不会走promise的then方法,可是其余没有报错的数据已经被插入了
  • 若是没有回调函数,那么在存储多条数据的时候若是有一条报错了,那么会走promise的then方法,可是其余没有报错的数据已经被插入了
Model.create({ size: 'small' }, function (err, doc) {
  if (err) return handleError(err);
  // saved!
})

const promise= Model.create(Doc)
promise.then(function (result) {
    console.log(1111111111)
    console.log(result)
},function (err) {
    console.log(2222222222)
    console.log(err)
})

6.3. 修改

6.3.1. 修改不返回document

  • 语法:Model.update(conditions, doc, [options], [callback])
  • 用法实例
Tank.update({ _id: id }, { $set: { size: 'large' }}, function (err, raw) {
    if (err) return handleError(err);
    console.log('The raw response from Mongo was ', raw);
});

6.3.2. 修改返回document

  • 写法一
Tank.findById(id, function (err, tank) {
  if (err) return handleError(err);

  tank.size = 'large';
  tank.save(function (err) {
    if (err) return handleError(err);
    res.send(tank);
  });
});
  • 写法二(推荐)
Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
  if (err) return handleError(err);
  res.send(tank);
});

6.4. 删除

Tank.remove({ size: 'large' }, function (err) {
  if (err) return handleError(err);
  // removed!
});

6.5. 查询

6.5.1. 直接查询

  • 在查询时带有回调函数的,称之为直接查询,查询的条件每每经过API来设定
  • 用法实例
PersonModel.findOne({'name.last':'dragon'},'some select',function(err,person){
      //若是err==null,则person就能取到数据
    });

6.5.2. 链式查询

6.5.2.1. 写法一

  • 这种方式相对直接查询,分的比较明细,若是不带callback,则返回query,query没有执行的预编译查询语句,该query对象执行的方法都将返回本身,只有在执行exec方法时才执行查询,并且必须有回调。
  • 用法实例
var query = PersonModel.findOne({'name.last':'dragon'});
     query.select('some select');
     query.exec(function(err,pserson){
     //若是err==null,则person就能取到数据
  });

 

6.5.2.2. 写法一

  • 用法实例
Person
      .find({ occupation: /host/ })
      .where('name.last').equals('Ghost')
      .where('age').gt(17).lt(66)
      .where('likes').in(['vaporizing', 'talking'])
      .limit(10)
      .sort('-occupation')
      .select('name occupation')
      .exec(callback);

 

免责说明

一、本博客中的文章摘自网上的众多博客,仅做为本身知识的补充和整理,并分享给其余须要的coder,不会用于商用。异步

二、由于不少博客的地址看完没有及时作保存,因此不少不会在这里标明出处,很是感谢各位大牛的分享,也但愿你们理解。

相关文章
相关标签/搜索