MongoDB - $设置更新或推送Array元素 [英] MongoDB - $set to update or push Array element

查看:170
本文介绍了MongoDB - $设置更新或推送Array元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在产品系列中,我有一系列近期视图,其中有2个字段被浏览过& amp;已审查日期。

In products collection, i have an Array of recentviews which has 2 fields viewedBy & viewedDate.

在某种情况下,如果我已经拥有的记录,那么我需要更新它。例如,如果我有这样的数组: -

In a scenario if i already have a record with viewedby, then i need to update it. For e.g if i have array like this :-

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

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

And user is abc, so i need to update the above & if there is no record for abc i have to $push.

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

I have tried $set as follows :-

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

上述查询将删除Array中的所有其他元素。

The above query erases all my other elements in Array.

推荐答案

实际上做你说你正在做的事情并不是一个单一的操作,但我会完成所需的部分,以便做到这一点或以其他方式涵盖其他可能的情况。

Actually doing what it seems like you say you are doing is not a singular operation, but I'll walk through the parts required in order to do this or otherwise cover other possible situations.

什么是y你正在寻找的部分是位置 $ 运营商。您需要部分查询来查找所需数组的元素。

What you are looking for is in part the positional $ operator. You need part of your query to also "find" the element of the array you want.

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

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

So the $ stands for the matched position in the array so the update portion knows which item in the array to update. You can access individual fields of the document in the array or just specify the whole document to update at that position.

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

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

If the fields do not in fact change and you just want to insert a new array element if the exact same one does not exist, then you can use $addToSet

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

但是,如果您只是想通过单个键值推送到数组,如果不存在那么您需要做更多的手动处理,首先看看数组中的元素是否存在,然后制作 $ push 声明它没有。

However if you are just looking for for "pushing" to an array by a singular key value if that does not exist then you need to do some more manual handling, by first seeing if the element in the array exists and then making the $push statement where it does not.

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

You get some help from the mongoose methods in doing this by tracking the number of documents affected by the update:

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) {

                }
            );
        }            

    }
);

这里唯一需要注意的是,来自writeConcern消息的实现有一点变化MongoDB 2.6到早期版本。目前还不确定mongoose API如何在回调中实际返回 numAffected 参数,差异可能意味着什么。

The only word of caution here is that there is a bit of an implementation change in the writeConcern messages from MongoDB 2.6 to earlier versions. Being unsure right now as to how the mongoose API actually implements the return of the numAffected argument in the callback the difference could mean something.

在以前的版本中,即使您在初始更新中发送的数据与现有元素完全匹配且且不需要进行实际更改,修改后的金额也将返回为 1 即使没有实际更新。

In prior versions, even if the data you sent in the initial update exactly matched an existing element and there was no real change required then the "modified" amount would be returned as 1 even though nothing was actually updated.

来自MongoDB 2.6的写入关注响应包含两部分。一部分显示修改后的文档,另一部分显示匹配。因此,当匹配现有元素的查询部分返回匹配时,实际修改的文档计数将返回 0 ,如果实际上没有需要更改。

From MongoDB 2.6 the write concern response contains two parts. One part shows the modified document and the other shows the match. So while the match would be returned by the query portion matching an existing element, the actual modified document count would return as 0 if in fact there was no change required.

因此,根据实际在mongoose中实现返回数的方式,使用 $ addToSet 操作符,以确保如果原因为零受影响的文件不仅仅是已存在的确切元素。

So depending on how the return number is actually implemented in mongoose, it might actually be safer to use the $addToSet operator on that inner update to make sure that if the reason for the zero affected documents was not just that the exact element already existed.

这篇关于MongoDB - $设置更新或推送Array元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆