Mongoose教程增删改查结合NodeJS建模

MongoDb是最类似传统关系型数据库的NoSQL,原项目名称为10Gen,2009年开放源代码.13年重名为MongoDB, 国内喜欢称之为芒果数据库,实际上它的名字由‘Humongous’一词得来。她是NodeJS的最佳配偶,就连开源时间都与NodeJS那么匹配。哈哈~

她是面向文档的数据库,适用于存储大量的非结构性的数据。与Redis基于键值对内存存储NoSQL相比。她更加适用于做稳定的后端数据库,以替代MySQL等关系型数据库在整个应用架构中持久化数据的角色。

对于一个应用而言,我们执行的操作无非是CRUD(create,read,updat,delete),除了利用原始的driver接口,在应用中自己编写CRUD的底层逻辑和实现,我们是否有可复用的现行框架/包呢?当然,答案是肯定的。那就是今天的猪脚:MONGOOSE.

如果您对MongoDB比较陌生,我推荐您在继续阅读之前读一读《MongoDB入门基础教程》

Mongoose是什么?

Mongoose是一个基于文档面向对象建模,它作为NodeJS开发包的形式面世。它就像PHP框架Eloquent ORM/Laravel.

Mongoose帮助我们更简化更轻松的使用MongoDB命令实现CRUD。 我们开始使用她时只需要使用NPM/YARN安装到项目即可。


mkdir mongoosebasic && cd $_  ##安装expressJS,npm init建立package.json等我这就不演示了
yarn add mongoose #等同于npm install mongoose --save

好了,我们的项目已经拥有使用Mongoose的能力啦。我们只需要添加模块并指定需要连接的数据库即可。


var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mongoosebasic'); #mongoosebasic是使用的数据库实例名

好了,我们现在可以正式开启Mongoose之旅啦。

定义一个数据模型

我们在进行CRUD操作之前,必须有一个数据模型。我们定义的这些模型将以文档的形式存储到指定的MongoDB数据库。

在Mongoose中,Schema用于定义MongoDB文档的各个属性和方法。


// import the mongoose module and define Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// create a schema
var userSchema = new Schema({
  name: String,
  username: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  admin: Boolean,
  location: String,
  meta: {
    age: Number,
    website: String
  },
  created_at: Date,
  updated_at: Date
});

// the schema is useless so far
// we need to create a model using it
var User = mongoose.model('User', userSchema);

// make this available to our users in our Node applications
module.exports = User;

先引入mongoose和mongoose.Schema,然后定义出我们需要的schema(这里是UserSchema). 值得注意的是:但我们需要嵌套对象时,我们使用的是meta属性。

SchemaTypes可以是:

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

最后,我们调用model方法传入预设的schemas定义出model.

自定义方法

除了定义文档属性,我们还可以在shchema中实现自定义方法。例如:


// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// create a schema
var userSchema ...

// custom method to add string to end of name
// you can create more important methods like name validations or formatting
// you can also do queries and find similar users 
userSchema.methods.dudify = function() {
  // add some stuff to the users name
  this.name = this.name + '-dude'; 

  return this.name;
};

// the schema is useless so far
// we need to create a model using it
var User = mongoose.model('User', userSchema);

// make this available to our users in our Node applications
module.exports = User;

简单使用示例

现在我们建立了自定义模型以及其可以调用的方法。简单的使用示例如下;


// if our user.js file is at app/models/user.js
var User = require('./app/models/user');
  
// create a new user called chris
var chris = new User({
  name: 'Chris',
  username: 'sevilayha',
  password: 'password' 
});

// call the custom method. this will just add -dude to his name
// user will now be Chris-dude
chris.dudify(function(err, name) {
  if (err) throw err;

  console.log('Your new name is ' + name);
});

// call the built-in save method to save to the database
chris.save(function(err) {
  if (err) throw err;

  console.log('User saved successfully!');
});

当然,这里自定义的方法并没有多大生成环境下的意义,仅作为示例。

入库前执行某函数

根据之前定义的模型,我们的UserSchema中需要2个时间。这并不需要我们手动去指定,往往是在数据入库前自动执行。实现如下:


// on every save, add the date
userSchema.pre('save', function(next) {
  // get the current date
  var currentDate = new Date();
  
  // change the updated_at field to current date
  this.updated_at = currentDate;

  // if created_at doesn't exist, add to that field
  if (!this.created_at)
    this.created_at = currentDate;

  next();
});

通过调用Schema的内置方法pre,我们每次进行数据保存前都会更新updated_at时间。如果不存在建立时间,则添加建立时间到created_at。

关于Schema的更多定义方法,请参考官方文档.

我们现在可以演示如何在Mongoose中执行CRUD。

Create

模型内置方法保存(save),帮助我们实现数据文档的建立。


// grab the user model
var User = require('./app/models/user');

// create a new user
var newUser = User({
  name: 'Peter Quill',
  username: 'starlord55',
  password: 'password',
  admin: true
});

// save the user
newUser.save(function(err) {
  if (err) throw err;

  console.log('User created!');
});

Read – 读取操作

读操作是最常见的操作之一,而且读取操作有很多不同的场景。例如:

FindAll – 查找数据集


// get all the users
User.find({}, function(err, users) {
  if (err) throw err;

  // object of all the users
  console.log(users);
});

Find ONE – 查找出指定文档


// get the user starlord55
User.find({ username: 'starlord55' }, function(err, user) {
  if (err) throw err;

  // object of the user
  console.log(user);
});

FIND BY ID – 根据ID来查找


// get a user with ID of 1
User.findById(1, function(err, user) {
  if (err) throw err;

  // show the one user
  console.log(user);
});

Querying

往往用于实现搜索框,查询语法请点这里


// get any admin that was created in the past month

// get the date 1 month ago
var monthAgo = new Date();
monthAgo.setMonth(monthAgo.getMonth() - 1);

User.find({ admin: true }).where('created_at').gt(monthAgo).exec(function(err, users) {
  if (err) throw err;

  // show the admins in the past month
  console.log(users);
});

Update – 更新操作

更新一般都是建立在查找的基础上的,即可以分解成查找、更新、保存。

获取一个用户,然后更新信息


// get a user with ID of 1
User.findById(1, function(err, user) {
  if (err) throw err;

  // change the users location
  user.location = 'uk';

  // save the user
  user.save(function(err) {
    if (err) throw err;

    console.log('User successfully updated!');
  });
});

查找后更新

更加简便的模式,我们可以将以上过程封装到一个方法种。


// find the user starlord55
// update him to starlord 88
User.findOneAndUpdate({ username: 'starlord55' }, { username: 'starlord88' }, function(err, user) {
  if (err) throw err;

  // we have the updated user returned to us
  console.log(user);
});

自定义方法:查找指定ID用户并更新


// find the user with id 4
// update username to starlord 88
User.findByIdAndUpdate(4, { username: 'starlord88' }, function(err, user) {
  if (err) throw err;

  // we have the updated user returned to us
  console.log(user);
});

Delete – 删除操作

查找到执行用户并删除


// get the user starlord55
User.find({ username: 'starlord55' }, function(err, user) {
  if (err) throw err;

  // delete him
  user.remove(function(err) {
    if (err) throw err;

    console.log('User successfully deleted!');
  });
});

根据ID查找并删除


// find the user with id 4
User.findByIdAndRemove(4, function(err) {
  if (err) throw err;

  // we have deleted the user
  console.log('User deleted!');
});

到此,基本的使用方法介绍结束。我们在实际项目中,可以按照model,schemas的方式来组织代码结构,以便于后续维护。

希望,这一篇基础的Mongoose入门教程对您有帮助。