参考

https://laixiazheteng.com/article/page/id/Bj7qgmJ3CJUE
https://laixiazheteng.com/article/page/id/6s0OlGT8AnCk
https://laixiazheteng.com/article/page/id/1NSGRZGU93cy
https://blog.csdn.net/Dong_vs/article/details/106566596
https://www.cnblogs.com/chris-oil/p/9142795.html

MongoDB

概念

简单的说,document是Mongodb中的最小单位,相当于行,并且mongodb中每个文档都有一个_id的键,它在所处的集合中是唯一的。collection相当于表,由document组成。database是由集合组成的数据合集,每个database之间是完全独立的,每一个database都有独立的权限控制。。

命令

  1. show dbs; 查看集合列表
  2. use mall; 切换某个数据库,若不存在则新建
  3. db.mall.insert({name:"张三",age:"18"}));
  4. db.dropDatabase();
  5. db.getName();
  6. db.stats();
  7. db.version();
  8. db.getMongo(); 查看当前db的链接地址
  9. db.shutdownServer();
  10. db.createCollection(name, options); 创建集合,即table
  11. db.getCollection("test");
  12. show collections; 集合有可能在insert时会自动创建,如下collection1
  13. db.collection.drop(); 删除集合
  14. db.collection1.find().pretty(); 如果集合在数据库中不存在,那么MongoDB 将创建此集合,然后把它插入文档。
  15. db.collection1.findOne(); 查询第一条数据
  16. db.userInfo.find({age: {$gte: 25}}).count(); 查询符合条件的条数
  17. db.collection1.find().sort({"ID":1}).pretty().limit(10).skip(10); 根据ID排序后,跳过10,查询10条,结果为10-19条的数据
  18. db.userInfo.find().limit(5); 查询前五条数据
  19. db.userInfo.find().skip(10); 查询10条以后的数据
  20. db.userInfo.find().limit(10).skip(5); 查询5~10条之间的数据
  21. db.collection1.remove({name: 'xxx'}, true); 第二个参数为true则只删除一条
  22. db.collection1.update({name: 'xxx'}, {$set: {age: 33}});
  23. db.collection1.find().sort({"ID":1});
  24. db.userInfo.find().sort({age: -1}); 接受一个文档,其中包含的字段列表连同他们的排序顺序。要指定排序顺序1和-1 1用于升序排列,而-1用于降序,默认升序

查询语句的一些条件:

  1. AND: find({name: xxx, age: xxx}),即可实现AND
  2. OR:db.col.find({$or: [{key1: value1}, {key2:value2}]}).pretty(),即可实现OR
  3. image.png

image.png

Mongoose CRUD

参考资料

https://itbilu.com/database/mongo/page-2.html

概念

Mongoose中最重要的三个概念:schema,model和entity。三者关系为:schema生成model,model生成entity,model和entity可对数据库进行操作。用代码解释下:

  1. // 定义Schema
  2. UserSchema = new mongoose.Schema({
  3. user: {// 真实姓名
  4. type: String
  5. },
  6. password: { // 密码
  7. type: String
  8. },
  9. shopCar: {
  10. type: Array,
  11. // default: []
  12. }
  13. }, { collection: 'user'});
  14. // 定义Model
  15. let UserModel = mongoose.model('user', UserSchema);
  16. // 新增一条记录:写法1
  17. let TestEntity = new User({
  18. user : req.query.user,
  19. password : req.query.password,
  20. shopCar: []
  21. });
  22. // 写法2
  23. TestEntity.save(function(error, doc){
  24. if(error){
  25. console.log("error :" + error);
  26. }else{
  27. console.log(doc);
  28. db.close();
  29. }
  30. });

mongoose没有统一提供一个findOrCreate的功能,也就是不存在就新建,此时可以使用mongoose-findorcreate这个包来解决,它提供了一个model的静态方法

save()create()

  1. const newTodoObj = new Todo(req.body);
  2. newTodoObj.save(err => {
  3. if (err) return res.status(500).send(err);
  4. return res.status(200).send(newTodoObj);
  5. });
  6. let hero = new HeroModel({
  7. name:'孙尚香',
  8. life:5300,
  9. type:'射手'
  10. });
  11. hero.save();
  12. // or
  13. hero.create();

create

  1. Tank.create({ size: 'small' }, function (err, small) {
  2. if (err) return handleError(err);
  3. // saved!
  4. });
  5. // pass an array of docs
  6. var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
  7. Candy.create(array, function (err, candies) {
  8. if (err) // ...
  9. var jellybean = candies[0];
  10. var snickers = candies[1];
  11. // ...
  12. });

insertMany()

  1. HeroModel.insertMany([
  2. {name:'刘备',life:'5400',type:'射手'},
  3. {name:'关羽',life:'5500',type:'战士'},
  4. {name:'张飞',life:'5900',type:'坦克'},
  5. ],(err, result)=>{
  6. if (err) {
  7. console.log(err);
  8. return;
  9. }
  10. console.log(result)
  11. })

更新一条数据,使用update()或者updateOne()方法

  1. const Todo = require("../models/todo");
  2. // This would likely be inside of a PUT request, since we're updating an existing document, hence the req.params.todoId.
  3. // Find the existing resource by ID
  4. Todo.findByIdAndUpdate(
  5. // the id of the item to find
  6. req.params.todoId,
  7. // the change to be made. Mongoose will smartly combine your existing
  8. // document with this change, which allows for partial updates too
  9. req.body,
  10. // an option that asks mongoose to return the updated version
  11. // of the document instead of the pre-updated one.
  12. {new: true},
  13. // the callback function
  14. (err, todo) => {
  15. // Handle any possible database errors
  16. if (err) return res.status(500).send(err);
  17. return res.send(todo);
  18. }
  19. )
  20. // 将第一条role为法师的文档的life更新为5300
  21. // 第一个参数为条件,第二个参数为更新文档
  22. HeroModel.updateOne({role:'法师'},{life:'5300'},(err,result) => {
  23. if (err) console.log(err)
  24. console.log(result);
  25. })
  1. 使用updateMany({},{},callback)方法,更新多条数据
  2. 使用findByIdAndUpdate(id,{},callback),将返回更新前的数据
  3. 使用findOneAndUpdate({},{},callback),将返回更新前的数据

除了上面的方法外,还可以find()findById()一个方法后,用.save()方法来保存改变。

使用remove()方法

  1. // 删除所有匹配条件的数据,删除所有role为法师的数据
  2. // 第一个参数为条件
  3. HeroModel.remove({role:'法师'},(err,result) => {
  4. if (err) console.log(err)
  5. console.log(result);
  6. })
  1. 使用deleteOne({},callback)方法,只删除第一条匹配条件的数据
  2. 使用deleteMany({},callback)方法,删除所有匹配条件的数据
  3. 使用findByIdAndDelete(id,callback),将返回被删除的数据
  4. 使用findByIdAndRemove(id,callback),将返回被删除的数据
  5. 使用findOneAndDelete({_id:id},callback),将返回被删除的数据
  6. 使用findOneAndRemove({_id:id},callback),将返回被删除的数据

    1. // The "todo" in this callback function represents the document that was found.
    2. // It allows you to pass a reference back to the client in case they need a reference for some reason.
    3. Todo.findByIdAndRemove(req.params.todoId, (err, todo) => {
    4. // As always, handle any potential errors:
    5. if (err) return res.status(500).send(err);
    6. // We'll create a simple object to send back with a message and the id of the document that was removed
    7. // You can really do this however you want, though.
    8. const response = {
    9. message: "Todo successfully deleted",
    10. id: todo._id
    11. };
    12. return res.status(200).send(response);
    13. });

  7. find({},callback)方法

  8. findOne({},callback)方法

    1. Kitten.findOne(
    2. // query
    3. {color: "white", name: "Dr. Miffles", age: 1},
    4. // Only return an object with the "name" and "owner" fields. "_id"
    5. // is included by default, so you'll need to remove it if you don't want it.
    6. {name: true, owner: true}, // "name owner"
    7. // callback function
    8. (err, kitten) => {
    9. if (err) return res.status(200).send(err)
    10. return res.status(200).send(kitten)
    11. }
    12. );
  9. findById(id, [fieldsToReturn], [callback])方法

  10. 进阶.where(selector)方法,支持更为复杂的查询,例如用于查询数据库中所有age在1到4之间的小猫。
    1. Kitten.where("age").gte(1).lte(4).exec((err, kittens) => {
    2. // Do stuff
    3. });
    ```javascript // No query passed in means “find everything” Person.find((err, people) => { // Note that this error doesn’t mean nothing was found, // it means the database had an error while searching, hence the 500 status if (err) return res.status(500).send(err) // send the list of all people return res.status(200).send(people); });

// If query IS passed into .find(), filters by the query parameters Person.find({name: “John James”, age: 36}, (err, people) =>{ if (err) return res.status(500).send(err)

  1. // send the list of all people in database with name of "John James" and age of 36
  2. // Very possible this will be an array with just one Person object in it.
  3. return res.status(200).send(people);

});

// 第一个参数为条件 HeroModel.findById(“5ed7c432ae5f501e6ca4217b”,(err,doc) => { if (err) console.log(err) console.log(doc); })

  1. <a name="RTRtD"></a>
  2. ### 总结
  3. 所以改、删、查相关的api都会返回一个mongoose query对象,该对象默认不会执行查询。可以通过以下两种方式之一执行mongoose查询:
  4. 1. 传入`callback(error, result)`,若error存在,则result为null,若执行操作成功,则error为null,result会是操作结果。
  5. 1. 执行`.exec((err, result) => {...})`方法
  6. 1. 方法1:传入回调
  7. ```javascript
  8. var query = Person.findOne({ 'name.last': 'Ghost' });
  9. query.select('name occupation'); // 仅返回name、occupation
  10. query.exec(function (err, person) {
  11. if (err) return handleError(err);
  12. // Prints "Space Ghost is a talk show host."
  13. console.log('%s %s is a %s.', person.name.first, person.name.last,
  14. person.occupation);
  15. });

b. 方法2:promise后用.then().catch((err) => {...})

  1. query.exec().then((person) => {
  2. // Prints "Space Ghost is a talk show host."
  3. console.log('%s %s is a %s.', person.name.first, person.name.last,
  4. person.occupation);
  5. }).catch((err) => {
  6. handleError(err);
  7. })

query变量是一个Query实例。Query允许你使用链式语法构建查询,而不仅是指定JSON对象。以下2个示例是等效的:

  1. // With a JSON doc
  2. Person.
  3. find({
  4. occupation: /host/,
  5. 'name.last': 'Ghost',
  6. age: { $gt: 17, $lt: 66 },
  7. likes: { $in: ['vaporizing', 'talking'] }
  8. }).
  9. limit(10).
  10. sort({ occupation: -1 }).
  11. select({ name: 1, occupation: 1 }).
  12. exec(callback);
  13. // Using query builder
  14. Person.
  15. find({ occupation: /host/ }).
  16. where('name.last').equals('Ghost').
  17. where('age').gt(17).lt(66).
  18. where('likes').in(['vaporizing', 'talking']).
  19. limit(10).
  20. sort('-occupation').
  21. select('name occupation').
  22. exec(callback);

Schema

Mongoose是node提供连接 mongodb的一个库。

Mongoose 的一切始于 Schema。每个 schema 都会映射到一个 MongoDB collection ,并定义这个collection里的文档的构成。

说白了,每一个 schema 就是相当于一个collection。Schema不仅定义了文档的属性和类型结构,还定义了文档实例方法和静态模型方法,复合索引和被称之为中间件的生命周期钩子。

是的,Mongoose就是把mongodb封装成了JavaScript对象以供我们在应用中使用。

  1. var blogSchema = new Schema({
  2. title: String,
  3. author: String,
  4. body: String,
  5. comments: [{ body: String, date: Date }],
  6. date: { type: Date, default: Date.now },
  7. hidden: Boolean,
  8. meta: {
  9. votes: Number,
  10. favs: Number
  11. }},
  12. { collection: 'artiles' }
  13. );

第一个参数就是结构对象,每一个键就是一个字段,你可以定义类型/默认值/验证/索引等;第二个参数是可选的(默认是取model的第一个参数加s),用来自定义Collection的名称。
⚠️注意,在mongoose中,我们不需手动去创建Collection,当你操作时,如Collection不存在,会自动创建。

models

创建可供操作的model

我们把定义好的schema转换成需要使用的模型,需要通过mongoose.model(modelName, schema);来实现。如下,collection名字被定义为blogs。

  1. var Blog = mongoose.model('Blog', blogSchema);
  2. var blog = new Schema({ name: String, type: String });//模型实例

schema 和 model 的理解

这是最核心的两个概念,Model对应mongodb中的集合 collection,而Schema对应集合的结构,也就是集合都有哪些字段、字段的类型、是否必填、是否有缺省值等。

实例方法

模型的实例是文档(documents)。文档有许多自己内置的实例方法。我们可以自定义文档实例方法。
常用的内置方法如下:

  1. removesetgetinvalidatepopulatesave

自定义实例方法

  1. animalSchema.methods.findSimilarTypes = function(cb) {
  2. return this.model('Animal').find({ type: this.type }, cb);
  3. };

静态方法

常用的内置静态方法有:

  1. createfindfindOne

给model增加静态方法,来封装一些curd操作,语法是:[schema].statics.[yourFunction] = function(xxx) {xxxx};

  1. animalSchema.statics.findByName = function(name, cb) {
  2. return this.find({ name: new RegExp(name, 'i') }, cb);
  3. };
  4. var Animal = mongoose.model('Animal', animalSchema);
  5. Animal.findByName('fido', function(err, animals) {
  6. console.log(animals);
  7. });
  8. // Assign a function to the "statics" object of our animalSchema
  9. animalSchema.statics.findByName = function(name) {
  10. return this.find({ name: new RegExp(name, 'i') });
  11. };
  12. // Or, equivalently, you can call `animalSchema.static()`.
  13. animalSchema.static('findByBreed', function(breed) {
  14. return this.find({ breed });
  15. });

query helper

您还可以像实例方法那样添加查询辅助功能,这是,但对于mongoose的查询。查询辅助方法可以让你扩展mongoose链式查询生成器API。

  1. animalSchema.query.byName = function(name) {
  2. return this.find({ name: new RegExp(name, 'i') });
  3. };
  4. var Animal = mongoose.model('Animal', animalSchema);
  5. Animal.find().byName('fido').exec(function(err, animals) {
  6. console.log(animals);
  7. });

Index

索引是什么?

  • 索引的优点是提高了查询效率,缺点是在插入、更新和删除记录时,需要同时修改索引,因此,索引越多,插入、更新和删除记录的速度就越慢。
  • 通过创建唯一索引,可以保证某一列的值具有唯一性。

mongoose同样也对索引做了处理,在mongoose中定义索引有两种方法。
第一种:直接在schema里面定义,如下所示

  1. var User = mongoose.model('User', {
  2. username: {
  3. type: String,
  4. index: true,
  5. unique: true // 创建唯一索引
  6. },
  7. password: String
  8. })

第二种:统一定义索引

  1. var User = mongoose.model('User', {
  2. username: {
  3. type: String
  4. },
  5. password: String
  6. });
  7. User.index({
  8. username: 1 / -1 (正向和逆向)
  9. })

注:需要注意的是,当应用启动的时候, ,Mongoose会自动为Schema中每个定义了索引的调用ensureIndex,确保生成索引,并在所有的ensureIndex调用成功或出现错误时,在 Model 上发出一个’index’事件。 开发环境用这个很好, 但是建议在生产环境不要使用这个。所以推荐禁用索引:

  1. animalSchema.set('autoIndex', false); //推荐
  2. mongoose.connect('mongodb://localhost/blog', { config: { autoIndex: false } });

虚拟属性

虚拟属性 是文档属性,您可以获取和设置但不保存到MongoDB。用于格式化或组合字段,从而制定者去组成一个单一的值为存储多个值是有用的。

可以格式化和自定义组合想要的属性值,类似于vue的computed的意思。

  1. // define a schema
  2. var personSchema = new Schema({
  3. name: {
  4. first: String,
  5. last: String
  6. }
  7. });
  8. // compile our model
  9. var Person = mongoose.model('Person', personSchema);
  10. // create a document
  11. var bad = new Person({
  12. name: { first: 'Walter', last: 'White' }
  13. });
  14. // 通过虚拟属性的getter,虚拟出全名属性full
  15. personSchema.virtual('name.full').get(function () {
  16. return this.name.first + ' ' + this.name.last;
  17. });
  18. console.log('%s is insane', bad.name.full); // Walter White is insane
  19. app.route('/api/users/name').get(usersController.getFullName);
  20. exports.getFullName = (req, res) => {
  21. UsersModel.findById(req.query.id, (err, result) => {
  22. if (err) {
  23. return err.status(400).send({
  24. message: '用户不存在',
  25. data: []
  26. });
  27. } else {
  28. console.log(result);
  29. res.jsonp(result.name.full);
  30. }
  31. })
  32. }

截屏2020-10-18 下午11.31.37.png

注意,这里的虚拟属性并没有存入数据库,所以如果是直接获取,是获取不到值的。

验证器

在你save数据之前, 你可以对数据进行一些列的validation,防止破坏了数据完整性

几种内置的验证器:

  1. required:必须填写的字段
  • Number
  1. min\max:给number类型做数据限制
  • String
  1. enum:列出枚举值
  2. match:匹配正则表达式的,match:/^a/
  3. maxlength/minlength:匹配字符串长度的
  1. var breakfastSchema = new Schema({
  2. eggs: {
  3. type: Number,
  4. min: [6, 'Too few eggs'], // 第二个参数为错误理由
  5. max: 12
  6. },
  7. bacon: {
  8. type: Number,
  9. required: [true, 'Why no bacon?']
  10. },
  11. drink: {
  12. type: String,
  13. enum: ['Coffee', 'Tea']
  14. }
  15. });
  16. var Breakfast = db.model('Breakfast', breakfastSchema);
  17. var badBreakfast = new Breakfast({
  18. eggs: 2,
  19. bacon: 0,
  20. drink: 'Milk'
  21. });
  22. var error = badBreakfast.validateSync();
  23. assert.equal(error.errors['eggs'].message,
  24. 'Too few eggs');
  25. assert.ok(!error.errors['bacon']);
  26. assert.equal(error.errors['drink'].message,
  27. '`Milk` is not a valid enum value for path `drink`.');
  28. badBreakfast.bacon = null;
  29. error = badBreakfast.validateSync();
  30. assert.equal(error.errors['bacon'].message, 'Why no bacon?');

还可以通过在Schema定义中加入validate字段来自定义验证器,cat.save(function(error) { //自动执行,validation });时会自动执行验证。

  1. const UsersSchema = new Schema({
  2. ...
  3. phone: {
  4. type: String,
  5. validate: { // 自定义验证器
  6. validator: function(data) {
  7. return /\d{3}-\d{3}-\d{4}/.test(data);
  8. },
  9. message: '`{PATH}:{value}`必须是有效的11位手机号码!'
  10. },
  11. required: [true, 'User phone number required']
  12. }
  13. }, {collection: 'users'});

联表查询

如果你使用过mysql,肯定用过join,用来联表查询,但mongoose中并没有join,不过它提供了一种更方便快捷的办法,Population。

Mongoose 的 populate() 可以连表查询,即在另外的集合中引用其文档。Populate() 可以自动替换 document 中的指定字段,替换内容从其他 collection 中获取。

我们只要提供某一个collection的_id , 就可以实现完美的联合查询. population 用到的关键字是: ref 用来指明外联的数据库的名字,写在schema中。

操作方法如下:

  • refs:创建 schema 时,可给该 Model 中关联存储其它集合 _id 的字段设置 ref 选项。ref 选项告诉 Mongoose 在使用 populate() 填充的时候使用哪个 Model。
  1. const mongoose = require("mongoose");
  2. const { Schema, model } = mongoose;
  3. const answerSchema = new Schema(
  4. {
  5. __v: { type: Number, select: false },
  6. content: { type: String, required: true },
  7. answerer: {
  8. type: Schema.Types.ObjectId,
  9. ref: "User",
  10. required: true,
  11. select: false
  12. },
  13. questionId: { type: String, required: true },
  14. voteCount: { type: Number, required: true, default: 0 }
  15. },
  16. { timestamps: true }
  17. );
  18. module.exports = model("Answer", answerSchema);

上例中 Answer model 的 answerer 字段设为 ObjectId 数组。 ref 选项告诉 Mongoose 在填充的时候使用 User model。所有储存在 answerer 中的 _id 都必须是 User model 中 document 的 _id。

ObjectId、Number、String 以及 Buffer 都可以作为 refs 使用。 但是最好还是使用 ObjectId。在创建文档时,保存 refs 字段与保存普通属性一样,把 _id 的值赋给它就好了。

  1. const Answer = require("../models/answers");
  2. async create(ctx) {
  3. ctx.verifyParams({
  4. content: { type: "string", required: true }
  5. });
  6. const answerer = ctx.state.user._id;
  7. const { questionId } = ctx.params;
  8. const answer = await new Answer({
  9. ...ctx.request.body,
  10. answerer,
  11. questionId
  12. }).save();
  13. ctx.body = answer;
  14. }

补充:
image.png

截屏2020-10-18 下午11.16.03.png

截屏2020-10-18 下午11.22.45.png

middleware

mongoose提供了pre和post两个中间件

  • pre: 在指定方法执行之前绑定。 中间件的状态分为 parallel和series.
  • post: 相当于事件监听的绑定

这里需要说明一下, 中间件一般仅仅只能限于在几个方法中使用. (但感觉就已经是全部了)

  • doc 方法上: init,validate,save,remove;
  • model方法上: count,find,findOne,findOneAndRemove,findOneAndUpdate,update
    1. // series执行, 串行
    2. var schema = new Schema(..);
    3. schema.pre('save', function(next) {
    4. // exe some operations
    5. this.model.
    6. next(); // 这里的next()相当于间执行权给下一个pre
    7. });
    在你调用 model.save方法时, 他会自动执行pre. 如果你想并行执行中间件, 可以设置为:
    1. schema.pre('save', true, function(next, done) {
    2. // 并行执行下一个中间件
    3. next();
    4. });

    image.png

    例子

    schema例子

    ```javascript const mongoose = require(‘mongoose’);

let HeroSchema = new mongoose.Schema({ name: {
required:true, // 设置该字段为必传字段 type: String, // 字段类型 trim:true, //修饰符,去掉两端的空格 set(name) { //自定义修饰符 return “WZRY·”+name; }, index: true // 为该字段创建索引 // unique:true // 为该字段创建唯一索引 // 创建索引可加快查询速度 }, life: {
required: true, type: Number, min: 4000, // 设置该字段最大值,只能用于Number类型 max: 6000 // 设置该字段最小值,只能用于Number类型 }, type: {
required: true, type: String, enum: [“射手”,”辅助”,”法师”,”战士”,”刺客”,”坦克”] // 枚举,该字段必须满足枚举值,只能用于String类型 } price:{ required: true, type: Number, validate: function(price){ // 自定义验证器,返回boolean值 return price > 0 && price < 20000; } } create_time: { type: Date, default: Date.now // 为该字段设置默认值 } })

  1. ```javascript
  2. const UserSchema = mongoose.Schema({
  3. name: String,
  4. age: Number,
  5. sex: Boolean
  6. });
  7. // Schema的静态方法
  8. UserSchema.statics.findUserByAge = function (age) {
  9. // 用then来拿到结果,如findUserByAge(21).then((res) => {})。
  10. // 也可以在find第二个参数传回调函数,如下
  11. return this.find({'age': age});
  12. }
  13. bookSchema.statics.FindbookByName = (name,callback) => { // 根据name查找图书
  14. this.model("Book").find({"name": name}, callback);
  15. }
  16. // 调用
  17. exports.edit = (req,res,next) => { // 查找到要修改的图书显示
  18. Book.FindbookByName(req.query.name,function(err,result){ res.render("edit",result[0]); });}
  19. // id是独一无二的 mongo分配的 根据id去修改图书的内容即可
  20. export.doedit = (req,res,next) => {
  21. Book.update({id: req.query.id}, {name: req.query.name,author: req.query.author,price:req.query.price},(err,result)=>{
  22. if(err) {
  23. res.send(err)
  24. }
  25. res.send('修改成功')
  26. })
  27. }
  28. // Schema的实例方法
  29. UserSchema.methods.findUserByName = function(name) {
  30. return this.model('User').find({ name: name });
  31. };
  32. // 创建一个Model,第三参数指定mongodb中collection的名字,如果不传则默认为变为复数(即Users)
  33. const User = mongoose.model('User', UserSchema, 'user');
  34. // 创建一条数据
  35. // 1. 直接用User创建
  36. User.create({name: 'zhangsan', age: 27, sex: true}, function(err, info) {
  37. console.log(info);
  38. });
  39. // 2. 新创建一个对象再添加数据到数据库
  40. // 再次说明下现在mongoose默认是支持promise方式的,可以使用then 或 回调函数的方式
  41. var person = new User({name: 'lisi', age: 20, sex: false});
  42. person.save().then(res => {
  43. console.log(res);
  44. })
  45. // 调用Schema中定义的静态方法,可以通过User直接调
  46. User.findUserByAge(21);
  47. // 调用Schema中定义的实例方法方法,先实例化再调
  48. const user = new User();
  49. user.findUserByName('zhangsan');
  50. // 删除数据,删除符合条件的一条
  51. User.deleteOne({name: 'lisi'}).then();
  52. // 删除符合条件的所有数据
  53. User.deleteMany({age: 20}).then();
  54. // 注意:remove()方法已经被弃用了!

CURD操作

对博客文章进行crud操作的示范

  1. const mongoose = require('mongoose');
  2. const ArticlesModel = mongoose.model('articles');
  3. mongoose.Promise = global.Promise;
  4. const commonFunction = require('../common/common_function');
  5. const _ = require('lodash');
  6. exports.get = (req, res) => {
  7. const articleId = req.query['id'];
  8. ArticlesModel.findById(articleId, (err, result) => {
  9. if (err) {
  10. return res.status(400).send({
  11. message: '查找失败',
  12. data: []
  13. });
  14. } else {
  15. res.jsonp({
  16. data: [result]
  17. });
  18. }
  19. });
  20. };
  21. exports.add = (req, res) => {
  22. req.body['articleId'] = commonFunction.getRandom();
  23. req.body['modifyOn'] = new Date();
  24. const article = new ArticlesModel(req.body);
  25. article.save((err) => {
  26. if (err) {
  27. return res.status(400).send({
  28. message: '新增失败',
  29. data: []
  30. });
  31. } else {
  32. res.jsonp({
  33. data: [article]
  34. });
  35. }
  36. })
  37. };
  38. exports.remove = (req, res) => {
  39. const id = req.query['id'];
  40. ArticlesModel.remove({'_id': id}, (err) => {
  41. if (err) {
  42. return res.status(400).send({
  43. message: '删除失败',
  44. data: []
  45. });
  46. } else {
  47. res.jsonp({
  48. status: 1
  49. });
  50. }
  51. })
  52. };
  53. exports.update = (req, res) => {
  54. const id = req.body['id'];
  55. ArticlesModel.findById(id, (err, result) => {
  56. if (err) {
  57. return res.status(400).send({
  58. message: '更新失败',
  59. data: []
  60. });
  61. } else {
  62. delete req.body['id'];
  63. const articles = _.extend(result, req.body);
  64. articles.save((err, result) => {
  65. if (err) {
  66. return res.status(400).send({
  67. message: '更新失败',
  68. data: []
  69. });
  70. } else {
  71. res.jsonp({
  72. data: [articles]
  73. });
  74. }
  75. })
  76. }
  77. })
  78. };
  79. /**
  80. * 进阶篇
  81. */
  82. exports.getAuthorByArticleid = (req, res) => {
  83. ArticlesModel.findById(req.query.id)
  84. .populate('by', 'name -_id')
  85. .exec(function (err, story) {
  86. if (err) {
  87. return res.status(400).send({
  88. message: '更新失败',
  89. data: []
  90. });
  91. }
  92. res.jsonp({
  93. data: [story]
  94. })
  95. });
  96. };