当前位置: 首页 > 面试题库 >

MongoDB-$ set更新或推送Array元素

关正雅
2023-03-14
问题内容

在产品集合中,我有一个nearviews数组,其中有2个fieldsbyBy和viewedDate。

在一种情况下,如果我已经有记录viewedby,那么我需要对其进行更新。例如,如果我有这样的数组:

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

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

我尝试$set如下:

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

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


问题答案:

实际上,按照您说的去做并不是一个单一的操作,但是我将逐步介绍所需的步骤,以完成此操作或覆盖其他可能的情况。

您正在寻找的部分是位置$运算符。您还需要查询的一部分来“查找”所需数组的元素。

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

声明它不是。

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

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消息中有一些实现更改。现在不确定猫鼬API如何实际实现numAffected回调中参数的返回,这可能意味着一些不同。

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

从MongoDB
2.6开始,写关注响应包含两个部分。一部分显示修改后的文档,另一部分显示匹配项。因此,尽管匹配部分将由与现有元素匹配的查询部分返回,但实际修改后的文档数将返回,0好像实际上不需要进行任何更改一样。

因此,根据在猫鼬中实际实现返回号的方式,
$addToSet
在内部更新中使用运算符实际上可能更安全,以确保受影响的文档为零的原因不仅在于确切的元素已经存在。



 类似资料:
  • 问题内容: 我正在尝试使用MongoDB的Java驱动程序在同一操作中对记录进行两次更新($ set和$ push)。我正在使用类似于以下代码: 当我通过BasicDBList将$ set和$ push合并到同一更新中时,我得到一个IllegalArgumentException:“存储在db中的字段不能以’$’开头(错误键:’$ push’)”。 如果我进行两个单独的更新,则pushUpdate

  • 我有一个以下格式的mongodb文档。如何基于父属性_id更新数组中第一个元素的rolename字段。

  • Set Matrix Zeroes 描述 Given a m × n matrix, if an element is 0, set its entire row and column to 0. Do it in place. Follow up: Did you use extra space? A straight forward solution using O(mn) space is

  • 首先,我想声明我一直在研究推送通知和web通知之间的关系,但我有点困惑。 我从这里读到PWAs的推送通知在Safari上的iOS(iPhone)不起作用:从PWA向iOS发送推送通知 然而,如果iPhone用户使用的是Chrome,这是否意味着它们可以工作呢?或者推送通知在任何浏览器上对iPhone中的PWAs都不起作用? 这就把我带到了web通知。web通知在后台对PWAs起作用吗?我的问题是w

  • 问题内容: 我试图用nodejS在mongodb中做一个findAndModifiy,这是我的代码: 编辑: 尝试回调 但是给我这个错误需要删除或更新..但是我正在这样做.. 问题答案: 节点本机驱动程序实现中的方法与mongo shell实现不同。要进行上述更新,请执行以下操作: 奇怪的是要删除您在选项中指定的内容,以便相同内容将“删除”匹配的文档: 主要区别在于您没有为操作命名“关键”部分。