MongoDB更新操作符的实践
和查询操作符类似,更新操作符处理最复杂的对象也是数组。我们按照上一篇文章的方法,先总结我所用到的操作符,再结合项目中遇到的实例组合使用操作符。
####1. 字段更新操作符
上图描述十分清晰地阐明了使用场景。$inc不仅可以增加还可以减少字段的值。$setOnInsert则需要和{ upsert: true }一起使用,当需要插入新数据时,$setOnInsert就会实效;反之则不会触发插入新字段。
####2. 数组更新操作符
$的作为为占位符,匹配查询条件的数组元素以提供更新数据的数组位置,由于其使用条件的限制,就不能和upsert参数一起使用,因为upsert插入新数据时会将$解释为字段名的一个元素。比如下面的代码就是将grades数组中的grade为80的元素std更新为6。
db.students.update(
{ _id: 4, "grades.grade": 85 },
{ $set: { "grades.$.std" : 6 } }
)
$addToSet更新不存在的数组元素,如果参数是传递一个数组,则将整个数组以一个更新上去,只有与$each一起使用才可以同时更新多个元素。比如下面的代码就是将"camera", “electronics”, “accessories"更新到tags数组中。
db.inventory.update(
{ _id: 2 },
{$addToSet: { tags: { $each: [ "camera", "electronics", "accessories" ] } } }
)
接下来的5个就说数组更新操作了。
####3. 修饰符
$slice将指定数量的数组元素保留到文档中,$position则是将数组元素插入数组的指定位置。其他不表。
####1. 添加数组的元素案例
operations字段的格式为对象数组,而$push操作能将新添加的operation数据插入到数组最末端。Mongoose的update方法的第二个参数就是更新数据。
Mails.update(updateCondition, {
'commonStatus': updateData.commonStatus,
$push: {
'operations': updateData.operation
}
}, function(err, numAffected){});
####2. 添加对象数组的字段案例
与上篇文章的privateInfo字段格式一样(如下),我们需要依据应用的业务逻辑,添加数组中的_creator和userStatus字段。
privateInfo: [{
_creator: {
type: Schema.Types.ObjectId, ref: 'User'
},
score: {
type: Number
},
scoredTime: {
type: Date
},
userStatus: {
type: String
},
tag: [{
type: Schema.Types.ObjectId, ref: 'User.customTags'
}]
}],
我们就可以这样编写更新语句。
Mails.update(updateCondition, {
$set: {
'privateInfo.$._creator': updateData.userId,
'privateInfo.$.userStatus': updateData.userStatus
}
}, function(err, numAffected){});
####3. 移除数组元素案例
通过在数据库中记录特征字段来指定文档的临时状态,当需要取消这个状态或者条件时,就需要清楚记录。比如一个标记实效、收藏操作的一个取消操作。这里需要使用$pull操作符。 以取消精华操作举例,每个用户都可以将数据设置为自己的收藏或者取消。
//还需依据用户id定位privateInfo
updateCondition.privateInfo = {
$elemMatch: { '_creator': userId }
};
Mails.update(updateCondition, {
$pull: {
'operations': { '_operator': userId, 'keyword': updateData.operation.keyword },
'privateInfo.$.tag': customTags[0]._id }
}, function(err, numAffected){});
####4. 更新不存在的数据案例
当我们按照数据定期获取数据时,不可避免的出现重复数据的更新,而我们只需要没有提交到mongodb的数据,当$addToSet与$each一起使用时就能提供这个功能,在$each的参数设置为一个数组,里面有数据库已经存入的数据。比如当我们通过一个字段’contactAddress’与mails的mail.to.address字段匹配时就插入ContactLists数组表示对同一个联系人的归类的功能实现。
所以Mongoose的对象是ContactList,而使用findOneAndUpdate方法的意义在于当数据库没有查询的数据中时能插入当前数据。
ContactList.findOneAndUpdate({ 'contactAddress': fromAddr },
{
'subject': mailSubject,
'date': Date.now(),
$addToSet: {
'mails': {
$each: mails
},
'contactors': new Object(userIdStr)
}
}, { upsert: true }, function(err, numAff){});
####总结
上述内容就是MongoDB更新操作符使用,update的操作符在使用上可能更常见,数组操作也是最复杂的。通过这篇文章和上一篇文章总结了MongoDB的一些比较常用的操作符,希望在以后的项目中更新提供姿势水平。
#####参考