3.10 Mongoose 基于Model的更新操作
文档更新可以使用以下几种方法
update()//往上改
updateMany() //改多个
updateOne() //改一个
findByIdAndUpdate() //通过i的查询 然后改
fingOneAndUpdate() //找到一个就改
find() + save()//栈 让然后改
findOne() + save()//找一个改
update()
第一个参数conditions为查询条件,第二个参数doc为需要修改的数据,第三个参数options为控制选项,第四个参数是回调函数
Model.update(conditions, doc, [options], [callback])
options有如下选项
safe (boolean): 默认为true。安全模式。
upsert (boolean): 默认为false。如果不存在则创建新记录。
multi (boolean): 默认为false。是否更新多个查询记录。
runValidators: 如果值为true,执行Validation验证。
setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。
strict (boolean): 以strict模式进行更新。
overwrite (boolean): 默认为false。禁用update-only模式,允许覆盖记录。
现在使用update()方法查询age大于20的数据,并将其年龄更改为40岁
var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
if(!err){
var schema = new mongoose.Schema({ age:Number, name: String});
var temp = mongoose.model('temp', schema);
temp.update({age:{$gte:20}},{age:40},function(err,raw){
//{ n: 1, nModified: 1, ok: 1 }
console.log(raw);
})
}
});
如果要同时更新多个记录,需要设置options里的multi为true。下面将名字中有'a'字符的年龄设置为10岁
var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
if(!err){
var schema = new mongoose.Schema({ age:Number, name: String});
var temp = mongoose.model('temp', schema);
temp.update({name:/a/},{age: 10},{multi:true},function(err,raw){
//{ n: 2, nModified: 2, ok: 1 }
console.log(raw);
})
}
});
如果设置的查找条件,数据库里的数据并不满足,默认什么事都不发生
temp.update({age:100},{name: "hundred"},function(err,raw){
//{ n: 0, nModified: 0, ok: 1 }
console.log(raw);
})
如果设置options里的upsert参数为true,若没有符合查询条件的文档,mongo将会综合第一第二个参数向集合插入一个新的文档
temp.update({age:100},{name: "hundred"},{upsert:true},function(err,raw){
//{ n: 1, nModified: 0,upserted: [ { index: 0, _id: 5972c202d46b621fca7fc8c7 } ], ok: 1 }
console.log(raw);
})
temp.update({name:/aa/},{age: 0},{upsert:true},function(err,raw){
//{ n: 1, nModified: 0,upserted: [ { index: 0, _id: 5972c288d46b621fca7fdd8f } ], ok: 1 }
console.log(raw);
})
[注意]update()方法中的回调函数不能省略,否则数据不会被更新。如果回调函数里并没有什么有用的信息,则可以使用exec()简化代码
temp.update({name:/aa/},{age: 0},{upsert:true}).exec();
更新子文档的方法
//这里的第一个要找到子文档的位置 具体到哪一条数据的哪一个子文档
temp.update({"userid":userid,"cartList.productId":productId},
//这里要更新的属性是 子文档 然后 .$.要更改的属性 : 值
{cartList.$.productNum:10},[opintion],function(err,doc){
if(err){
res.json({
status:
result:
msg:
})
return
}
doc...//TODO
})
updateMany()
updateMany()与update()方法唯一的区别就是默认更新多个文档,即使设置{multi:false}也无法只更新第一个文档
Model.updateMany(conditions, doc, [options], [callback])
将数据库中名字中带有'huo'的数据,年龄变为50岁
temp.updateMany({name:/huo/},{age:50},function(err,raw){
//{ n: 2, nModified: 2, ok: 1 }
console.log(raw);
});
find() + save()
如果需要更新的操作比较复杂,可以使用find()+save()方法来处理,比如找到年龄小于30岁的数据,名字后面添加'30'字符
temp.find({age:{$lt:20}},function(err,docs){
//[ { _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 10 },
//{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 }]
console.log(docs);
docs.forEach(function(item,index,arr){
item.name += '30';
item.save();
})
//[ { _id: 5971f93be6f98ec60e3dc86d, name: 'wang30', age: 10 },
// { _id: 5971f93be6f98ec60e3dc86f, name: 'li30', age: 12 }]
console.log(docs);
});
updateOne()
updateOne()方法只能更新找到的第一条数据,即使设置{multi:true}也无法同时更新多个文档
将数据库中名字中带有'huo'的数据,年龄变为60岁
temp.updateOne({name:/huo/},{age:60},function(err,raw){
//{ n: 1, nModified: 1, ok: 1 }
console.log(raw);
});
findOne() + save()
如果需要更新的操作比较复杂,可以使用findOne()+save()方法来处理,比如找到名字为'huochai'的数据,年龄加100岁
temp.findOne({name:'huochai'},function(err,doc){
//{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 10 }
console.log(doc);
doc.age += 100;
doc.save();
//{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 110 }
console.log(doc);
});
findOneAndUpdate()
fineOneAndUpdate()方法的第四个参数回调函数的形式如下function(err,doc){}
Model.findOneAndUpdate([conditions], [update], [options], [callback])
findByIdAndUpdate
fineByIdAndUpdate()方法的第四个参数回调函数的形式如下function(err,doc){}
Model.findOneAndUpdate([conditions], [update], [options], [callback])
Update的更新操作符
"$inc"
增减修改器,只对数字有效
"$inc"
增减修改器,只对数字有效this.ctx.model.Article.update({"age":22}, {$inc:{"age":1} } );
复制代码
找到age=22的文档,修改文档的age值自增1
'$set'
指定一个键的值,这个键不存在就创建它.可以是任何MondoDB支持的类型
'$set'
指定一个键的值,这个键不存在就创建它.可以是任何MondoDB支持的类型this.ctx.model.Article.update({ _id:5c4a819fb87ba4002a47bc4f }, { $set: { isDelete: true } });
复制代码
对5c4a819fb87ba4002a47bc4f 表进行软删除,找到特定_id数据,增加或者修改isDelete属性
"$unset"
同上取反,删除一个键
"$unset"
同上取反,删除一个键this.ctx.model.Article.update({age:22}, {$unset:{age:18} } );
复制代码
执行后age键不存在
'$push'
给一个键push一个数组成员,键不存在会创建,对数组有效
'$push'
给一个键push一个数组成员,键不存在会创建,对数组有效this.ctx.model.Article.update({name:'wxw'}, {$push:{array:10} } );
复制代码
返回Article表中name为wxw的数据,增加一个array键,类型为数组,有一个成员 10
'$addToSet'
向数组中添加一个元素,如果存在就不添加
'$addToSet'
向数组中添加一个元素,如果存在就不添加this.ctx.model.Article.update({name:'wxw'},{$addToSet:{array:10} } );
复制代码
返回Article表中name为wxw的数据,array中有10所以不会添加
'$each'
遍历数组和 $push 修改器配合可以插入多个值
'$each'
遍历数组和 $push 修改器配合可以插入多个值this.ctx.model.Article.update({name:'wxw'}, {$push:{array:{$each: [1,2,3,4,5]}} } );
复制代码
返回Article表中name为wxw的数据,执行后array : [10,1,2,3,4,5]
'$pop'
向数组中尾部删除一个元素
'$pop'
向数组中尾部删除一个元素this.ctx.model.Article.update({name:'wxw'}, {$pop:{array:1} } );
复制代码
返回Article表中name为wxw的数据,其中array : [10,1,2,3,4,5],执行后 array : [10,1,2,3,4]
tip:将1改成-1可以删除数组首部元素
'$pull'
向数组中删除指定元素
'$pull'
向数组中删除指定元素this.ctx.model.Article.update({name:'wxw'}, {$pull:{array:10} });
复制代码
返回Article表中name为wxw的数据,匹配到array中的10后将其删除
Last updated
Was this helpful?