美文网首页
Mongoose简明教程

Mongoose简明教程

作者: candice2cc | 来源:发表于2017-11-15 17:00 被阅读51次

Mogoose connection

  • default connection eg.
var dbURI = 'mongodb://localhost/mydatabase';
mongoose.connect(dbURI);
  • multiple connections eg.
 var dbURI = 'mongodb://localhost/myadmindatabase';
var adminConnection = mongoose.createConnection(dbURI);

mongoose.connect 和 mongoose.createConnection创建的连接均为连接池模式,默认poolSize: 5,可根据业务需要自行修改。

  • sample code
    helpers/mongoose_conn.js
import mongoose from 'mongoose';
import mongooseOptions from '../config/mongoose';
import { debugLogger, errorLogger } from './logger_creator';

mongoose.Promise = global.Promise;
// conenct mongodb
const monOptions = mongooseOptions();
mongoose.connect(monOptions.connectionString, monOptions.options);
const mongooseConn = mongoose.connection;

mongooseConn.once('connected', () => {
    debugLogger.debug('mongodb connect success!!!');
});

mongooseConn.on('error', (err) => {
    errorLogger.error(`mongodb error:${err}`);
});




export default mongooseConn;

config/mongoose.js

import { isProduction} from '../../../common/helpers/env_helper';

const mongooseOptions = function mongooseOptions() {
    if (isProduction()) {
        return {
            connectionString: 'mongodb://username:password@hostname:port,hostname:port/dbname', // TODO
            options: {
                auth: { authdb: 'dbname' },
                replset: { rs_name: 'mgset-xxx' },
                keepAlive: 1,
                useMongoClient: true,

            },
        };
    }
    return {
        connectionString: 'mongodb://192.168.1.1:27020/dbname', // TODO
        options: {
            keepAlive: 1,
            useMongoClient: true,
        },
    };
};
export default mongooseOptions;

Schema

Schema对应描述MongoDB中的Document的数据结构。

  • String
  • Number
  • Date
  • Boolean
  • Buffer
  • ObjectId
  • Mixed
  • Array

Schema的数据类型可支持扩展,字段可以动态添加。同时还支持各种限定条件。

 var userSchema = new mongoose.Schema({
     name: String,
     email: {type: String, unique:true},
     createdOn: { type: Date, default: Date.now },
     modifiedOn: Date,
     lastLogin: Date
   });

对应的文档对象:


   { "__v" : 0,
   "_id" : ObjectId("5126b7a1f8a44d1e32000001"),
   "createdOn" : ISODate("2013-02-22T00:11:13.436Z"),
   "email" : "simon@theholmesoffice.com",
   "lastLogin" : ISODate("2013-04-03T12:54:42.734Z"),
   "modifiedOn" : ISODate("2013-04-03T12:56:26.009Z"),
   "name" : "Simon Holmes" }

Model

Model是Schema的编译版本。

mongoose.model( 'User', userSchema );

CURD

Create

create有两种实现方式:

  var newUser = new User({
     name: 'Simon Holmes',
     email: 'simon@theholmesoffice.com',
     lastLogin : Date.now()
   }).save( function( err ){
     if(!err){
       console.log('User saved!');
     }
});

User.create({
     name: 'Simon Holmes',
     email: 'simon@theholmesoffice.com',
     lastLogin : Date.now()
   }, function( err, user ){
     if(!err){
       console.log('User saved!');
       console.log('Saved user name: ' + user.name);
       console.log('_id of saved user: ' + user._id);
} });

Read

  • QueryBuilder
var myQuery = User.find({'name' : 'Simon Holmes'})
   .where('age').gt(18)
   .sort('-lastLogin')
   .select('_id name email');
   // do some other operations
   // and then...
   myQuery.exec(function (err, users){
     if (!err){
       console.log(users); // output array of users found
} });
  • Single query
Model.find(conditions, [fields], [options], [callback])

User.find(
     {'name' : 'Simon Holmes'}, // users called Simon Holmes
     function (err, users){
       if (!err){console.log(users);}
   });

 User.find(
     {'name' : 'Simon Holmes'}, // users called Simon Holmes
     'name email', // returning just the name and email fields
     function (err, users){
       if (!err){console.log(users);}
   });

 User.find(
     {'name' : 'Simon Holmes'}, // users called Simon Holmes
     null, // returning all fields in model
     {sort : {lastLogin : -1}}, // sorted by lastLogin descending
     function (err, users){
       if (!err){console.log(users);}
   });

Model拥有内置的静态helper方法:

Model.find(query) 
Model.findOne(query) 
Model.findById(ObjectID) 

我们可以可以自定义helper方法(置于model compiled之前):

projectSchema.statics.findByUserID = function (userid, callback) {
     this.find(
       { createdBy: userid },
       '_id projectName',
       {sort: 'modifiedOn'}
       callback);
}

Update

Model拥有内置的静态helper方法:

update() //更新数据,不返回
findOneAndUpdate() 
findByIdAndUpdate()

Delete

Model拥有内置的静态helper方法:

remove()
findOneAndRemove()
findByIdAndRemove()

validators

  • 适用于所有的SchemaType的validator
email: { type: String, unique: true, required: true }
  • Number
 var teenSchema = new Schema({
     age : {type: Number, min: 13, max:19}
});
  • String
 var weekdaySchema = new Schema({
     day : {type: String, match: /^(mon|tues|wednes|thurs|fri)day$/i}
});

var weekdays = ['monday', 'tuesday', 'wednesday', 'thursday',
   'friday'];
   var weekdaySchema = new Schema({
     day : {type: String,  enum: weekdays}
   });

在save的callback中我们收到error:

{ message: 'Validation failed',
     name: 'ValidationError',
     errors:
      { email:
         { message: 'Validator "required" failed for path email',
           name: 'ValidatorError',
           path: 'email',
           type: 'required' },
        name:
         { message: 'Validator "required" failed for path name',
           name: 'ValidatorError',
           path: 'name',
           type: 'required' } } }
  • 自定义
// 定义函数
 var lengthValidator = function(val) {
     if (val && val.length >= 5){
       return true;
     }
     return false;
   };

name: {type: String, required: true, validate: { validator: lengthValidator, msg: 'Too short' } }

// 定义正则

 var weekdaySchema = new Schema({
     day : {type: String, validate: {validator:
   /^(mon|tues|wednes|thurs|fri)day$/i, msg: 'Not a day' }
   });

// 数组形式
 var validateLength = [lengthValidator, 'Too short' ];
 var validateDay = [/^(mon|tues|wednes|thurs|fri)day$/i, 'Not a day' ];

name: {type: String, required: true, validate: validateLength }
day : {type: String, validate: validateDay }

// 多个validator组合
var validateLength = [{validator: isNotTooShort, msg: 'Too short'} ];
name: {type: String, required: true, validate: validateLength },

复杂Schema

Population

MongoDB不支持JOIN,Population有点类似关系数据库中的JOIN

var projectSchema = new mongoose.Schema({
     ...
     createdBy: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
     contributors: [ {type: mongoose.Schema.Types.ObjectId, ref: 'User'} ] ,
    ... });

对应的document:

{ "projectName" : "Population test",
     "createdBy" : ObjectId("5126b7a1f8a44d1e32000001"),
     "_id" : ObjectId("51ac2fc4c746ba1645000002"),
     "contributors" : [
       ObjectId("5126b7a1f8a44d1e32000001"),
       ObjectId("5126b7a1f8a44d1e32000002") ] }

查询数据时:

Project
   .findById( req.params.id)
  .populate('createdBy', 'name email')
   .populate('contributors', 'name email')
   .exec(function(err,project) { ...

查询结果为:

{ __v: 0,
     _id: 51b495e01e686ea360000002,
     createdBy:
      { _id: 5126b7a1f8a44d1e32000001,
        email: 'simon@theholmesoffice.com',
        name: 'Simon Holmes' },
     modifiedOn: Sun Jul 07 2013 16:21:50 GMT+0100 (BST),
     projectName: 'Updated project schemas',
     createdOn: Sun Jun 09 2013 15:49:04 GMT+0100 (BST),
     contributors: [
       { _id: 5126b7a1f8a44d1e32000001,
         email: 'simon@theholmesoffice.com',
         name: 'Simon Holmes' },
       { _id: 5126b7a1f8a44d1e32000002,
         email: 'someone@theholmesoffice.com',
         name: 'Someone Else' }
] }

population支持进一步的子查询操作:

 .populate({
     path: 'contributors',
     match: { email: /@theholmesoffice\.com/i },
     select: 'name lastLogin',
     options: { limit: 5, sort: 'name' }
   })
.exec()

Subdocument

  var projectSchema = new mongoose.Schema({
     projectName: String,
     ...
     tasks: [taskSchema]
});

对应的document:

 {
     "projectName" : "Project 2",
     "tasks" : [
         "taskName" : "A task please",
         "taskDesc" : "A short description of the task",
         "createdBy" : ObjectId("5126b7a1f8a44d1e32000001"),
         "_id" : ObjectId("51ad7d6cfa492a174a000005"),
         "createdOn" : ISODate("2013-06-04T05:38:52.847Z")
}, {
         "createdBy" : ObjectId("5126b7a1f8a44d1e32000002"),
         "_id" : ObjectId("51ad7d80fa492a174a000006"),
         "createdOn" : ISODate("2013-06-04T05:39:12.728Z"),
         "modifiedOn" : ISODate("2013-06-04T05:39:48.553Z"),
         "taskDesc" : "A quick description of this one too",
         "taskName" : "A secondary task"
 } ]
}

每一个subdocument都会自动生成一个唯一 _id 字段。
所有对subdocument的操作,均需要通过parent进行。parent document save时,即完成了subdocument的save。

// 创建 subdocument
Project.findById( req.body.projectID, 'tasks modifiedOn',
  function (err, project) {
    if(!err){
      project.tasks.push({
        taskName: req.body.taskName,
        taskDesc: req.body.taskDesc,
        createdBy: req.session.user._id
      });
      project.modifiedOn = Date.now();
      project.save(function (err, project){
        var qstring = '?';
        if(err){
          console.log('Oh dear', err);
          if (err.name === "ValidationError") {
            for (var input in err.errors) {
              qstring += err.errors[input].path + '=invalid&';
              console.log(err.errors[input].message);
            }
          }else{
            res.redirect('/?error=true');
          }
          req.session.tmpTask = { "taskName": req.body.taskName, "taskDesc": req.body.taskDesc };
          res.redirect('/project/' + req.body.projectID + '/task/new' + qstring);
        } else {
          console.log('Task saved: ' + req.body.taskName);
          res.redirect( '/project/' + req.body.projectID );
        }
      });
    }
  }
);


// 查询 subdocument
 Project.findById( req.body.projectID, 'tasks modifiedOn',function (err, project) {
    if(!err){
        console.log(project.tasks); // array of tasks
        var thisTask = project.tasks.id(req.params.taskID); 
        console.log(thisTask); // individual task document
    }});

// 删除 subdocument
project.tasks.id(req.body.taskID).remove();

常见问题

Replica-Set

多个MongoDB Server,镜像同样的数据。
数据读写操作:当read时,请求任意一个set;当write时,只会写入Primary server。

Multiple mongos

分片:每个connection通过MongoDB的路由,再由路由进行转发给具体负责的MongoDB

Multiple connections

当应用创建了数据库的多个连接,可以并行处理多个请求。数据库驱动会自动处理这种情况。
只有当同时连接多个数据库或者每个连接的配置不同时,此时需要自己处理每个请求的逻辑。
eg.

var conn = mongoose.createConnection('mongodb://localhost1/test1');
var conn2 = mongoose.createConnection('mongodb://localhost2/test2');
var model1 = conn.model('Model', Schema);
var model2 = conn2.model('Model', Schema);
model1.find({long query}, function() {
   console.log("this will print out last");
});
model2.find({short query}, function() {
   console.log("this will print out first");
});

相关文章

  • Mongoose简明教程

    Mogoose connection default connection eg. multiple connec...

  • Mongoose介绍和入门

    Mongoose介绍和入门 mongoose对查询结果进行排序 mongoose教程06--排序 MyModel....

  • OPENGL ES 教程

    Android OpenGL ES 简明开发教程一:概述Android OpenGL ES 简明开发教程二:构造O...

  • webpack 几个很棒的教程

    初学webpack,网上找到了几个简明易懂的入门教程十分感谢教程的作者! WebPack 简明学习教程 Webpa...

  • Linux 常用命令总结

    linux 命令速查手册linux 常用操作命令 sed 简明教程 awk 简明教程 常用命令 ls ...

  • Socket使用简明教程- AsyncSocket

    Socket使用简明教程- AsyncSocket

  • Markdown语法

    经常忘记,写个备忘录。简明教程1简书教程

  • Mongoose教程翻译

    原文地址 本文简单的介绍了数据库,以及如何在 Node/Express 中应用他们。之后展示如何使用Mongoos...

  • mongoose简要教程

    主要是自己使用mongoose的一些有疑虑的地方简单介绍 初次使用mongoose的过程中有很多的疑惑,Mongo...

  • pycaffe使用

    pycaffe简明文档Caffe for Python 官方教程(翻译) pycaffe使用教程 caffe添加C...

网友评论

      本文标题:Mongoose简明教程

      本文链接:https://www.haomeiwen.com/subject/ylocvxtx.html