MongoDB – $设置为更新或推送数组元素

在产品收集,我有一个最近的观点数组有2个字段viewsBy&viewingDate。

在情况下,如果我已经有了一个logging,然后我需要更新它。 例如,如果我有像这样的数组: –

 "recentviews" : [ { "viewedby" : "abc", "vieweddate" : ISODate("2014-05-08T04:12:47.907Z") } ] 

而用户是abc ,所以我需要更新上面&如果没有logging的abc我必须$push

我已经尝试过$set ,如下所示:

 db.products.update( { _id: ObjectId("536c55bf9c8fb24c21000095") }, { $set: { "recentviews": { viewedby: 'abc', vieweddate: ISODate("2014-05-09T04:12:47.907Z") } } } ) 

上面的查询将擦除Array中的所有其他元素。

实际上,做你所说的你所做的不是一个单独的操作,但是我将通过所需的部分来完成这个任务,或者覆盖其他可能的情况。

你正在寻找的是位置$运算符的一部分。 你需要查询的一部分也“find”你想要的数组的元素。

 db.products.update( { "_id": ObjectId("536c55bf9c8fb24c21000095"), "recentviews.viewedby": "abc" }, { "$set": { "recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z") } } ) 

所以$表示数组中的匹配位置,所以更新部分知道数组中哪个项目要更新。 您可以访问数组中文档的各个字段,或者只是指定要在该位置更新的整个文档。

 db.products.update( { "_id": ObjectId("536c55bf9c8fb24c21000095"), "recentviews.viewedby": "abc" }, { "$set": { "recentviews.$": { "viewedby": "abc", "vieweddate": ISODate("2014-05-09T04:12:47.907Z") } } ) 

如果这些字段实际上并没有改变,并且你只是想插入一个新的数组元素,如果完全相同的元素不存在,那么你可以使用$addToSet

 db.products.update( { "_id": ObjectId("536c55bf9c8fb24c21000095"), "recentviews.viewedby": "abc" }, { $addToSet:{ "recentviews": { "viewedby": "abc", "vieweddate": ISODate("2014-05-09T04:12:47.907Z") } } ) 

然而,如果你只是寻找“推”到一个单一的数组,如果不存在,那么你需要做一些更多的手动处理,首先看看数组中的元素是否存在,然后使$push声明哪里没有。

通过跟踪受更新影响的文档数量,您可以通过mongoose方法获得一些帮助:

 Product.update( { "_id": ObjectId("536c55bf9c8fb24c21000095"), "recentviews.viewedby": "abc" }, { "$set": { "recentviews.$": { "viewedby": "abc", "vieweddate": ISODate("2014-05-09T04:12:47.907Z") } }, function(err,numAffected) { if (numAffected == 0) { // Document not updated so you can push onto the array Product.update( { "_id": ObjectId("536c55bf9c8fb24c21000095") }, { "$push": { "recentviews": { "viewedby": "abc", "vieweddate": ISODate("2014-05-09T04:12:47.907Z") } } }, function(err,numAffected) { } ); } } ); 

这里唯一值得警惕的是,从MongoDB 2.6到早期版本的writeConcern消息有一些实现的改变。 现在不确定如何mongooseAPI实际上在callback中实现numAffected参数的返回,差异可能意味着什么。

在之前的版本中,即使您在初始更新中发送的数据与现有元素完全匹配,并且没有实际更改,那么即使没有实际更新,“修改”数量也会返回为1

从MongoDB 2.6开始,写关注响应包含两部分。 一部分显示修改后的文件,另一部分显示匹配。 所以,当查询部分与现有元素相匹配时,匹配将返回,如果实际上没有需要更改,则实际修改的文档数将返回为0

因此,根据在mongoose中如何实际实现返回值,在内部更新上使用$addToSet操作符可能更安全,以确保受影响文档的原因不仅仅是确切的元素已经存在。