当前位置: 首页 > 知识库问答 >
问题:

用MongoDB更新嵌套数组

欧阳睿范
2023-03-14

我正在尝试更新嵌套数组中的值,但无法使其工作。

我的对象是这样的

 {
    "_id": {
        "$oid": "1"
    },
    "array1": [
        {
            "_id": "12",
            "array2": [
                  {
                      "_id": "123",
                      "answeredBy": [],
                  },
                  {
                      "_id": "124",
                      "answeredBy": [],
                  }
             ],
         }
     ]
 }
callback = function(err,value){
     if(err){
         res.send(err);
     }else{
         res.send(value);
     }
};
conditions = {
    "_id": 1,
    "array1._id": 12,
    "array2._id": 123
  };
updates = {
   $push: {
     "array2.$.answeredBy": "success"
   }
};
options = {
  upsert: true
};
Model.update(conditions, updates, options, callback);

提前谢谢!

共有1个答案

危砚
2023-03-14

你在这里做的事情有些不对劲。首先是您的查询条件。您引用了几个不需要的_id值,其中至少有一个值不在顶层。

为了进入“嵌套”值,同时假定_id值是唯一的,不会出现在任何其他文档中,查询表单应该如下所示:

Model.update(
    { "array1.array2._id": "123" },
    { "$push": { "array1.0.array2.$.answeredBy": "success" } },
    function(err,numAffected) {
       // something with the result in here
    }
);

现在这实际上是有效的,但实际上这只是一个侥幸,因为有很好的理由,为什么它不应该为你工作。

重要的阅读内容在“嵌套数组”主题下的位置$运算符的正式文档中。这句话的意思是:

位置$运算符不能用于遍历多个数组的查询,例如遍历嵌套在其他数组中的数组的查询,因为$占位符的替换是一个值

因此,如果您查看如图所示的查询符号,我们已经“硬编码”了顶层数组中的第一个(或0索引)位置,碰巧“array2”中的匹配元素也是零索引项。

为了演示这一点,您可以将匹配的_id值更改为“124”,结果将$push一个新条目加到_id“123”的元素上,因为它们都在“array1”的零索引条目中,这是返回给占位符的值。

这就是嵌套数组的一般问题。您可以删除其中的一个级别,并且仍然可以将$push添加到“top”数组中的正确元素,但是仍然会有多个级别。

尽量避免嵌套数组,因为您会遇到更新问题,如图所示。

一般的情况是将你“认为”是“层次”的东西“扁平化”,实际上在最后的细节项目上使论文成为“属性”。例如,问题中结构的“扁平化”形式应该是这样的:

 {
   "answers": [
     { "by": "success", "type2": "123", "type1": "12" }
   ]
 }

甚至在接受内部数组时仅为$push,且从不更新:

 {
   "array": [
     { "type1": "12", "type2": "123", "answeredBy": ["success"] },
     { "type1": "12", "type2": "124", "answeredBy": [] }
   ]
 }
Model.update(
  {
    "_id": 1,
    "array1": {
      "$elemMatch": {
        "_id": "12","array2._id": "123"
      }
    }
  },
  {
    "$push": { "array1.$[outer].array2.$[inner].answeredBy": "success" }
  },
  {
    "arrayFilters": [{ "outer._id": "12" },{ "inner._id": "123" }] 
  }
)

这个新的扩展使嵌套数组内容的更新成为可能,但它对“查询”这类数据的实用性并没有真正的帮助,因此与前面解释的相同的警告适用。

你通常真的“意思”表达为“属性”,即使你的大脑最初认为“嵌套”,它通常只是对你如何相信“先前的关系部分”聚集在一起的反应。实际上,你真的需要更多的非规范化。

还要看看如何更新mongodb中的多个数组元素,因为这些新的更新运算符实际上匹配并更新“多个数组元素”,而不是只更新第一个数组元素,后者是位置更新的前一个动作。

但是,mongoshell不是这样的,因为在那里实现方法的方式(“讽刺的是,向后兼容”)arrayfilters参数不被内部方法识别和删除,该内部方法解析选项,以提供与以前MongoDB服务器版本和“遗留”.update()API调用语法的“向后兼容”。

因此,如果您想在mongoshell或其他“基于shell”的产品(特别是Robo3T)中使用该命令,则需要开发分支或生产版本的最新版本,该版本应达到3.6或更高版本。

另请参阅positional all$[],它还更新“多个数组元素”,但不应用于指定的条件,并应用于数组中的所有元素,这是所需的操作。

 类似资料:
  • 问题内容: 我正在尝试更新嵌套数组中的值,但无法使其正常工作。 我的对象是这样的 我需要将值推送到“ answeredBy”数组。 在下面的示例中,我尝试将“成功”字符串推到“ 123 _id”对象的“ answeredBy”数组中,但是它不起作用。 我找到了此链接,但其答案仅表示我应该使用类似结构的对象而不是数组。这不适用于我的情况。我真的需要将我的对象嵌套在数组中 如果您能在这里帮助我,那就太

  • 问题内容: 我正在尝试更新嵌套数组中的值,但无法使其正常工作。 我的对象是这样的 我需要将值推送到“ answeredBy”数组。 在下面的示例中,我尝试将“成功”字符串推到“ 123 _id”对象的“ answeredBy”数组中,但是它不起作用。 我找到了此链接,但其答案仅表明我应该使用像结构这样的对象而不是数组。这不适用于我的情况。我真的需要将我的对象嵌套在数组中 如果您能在这里帮助我,那就

  • 我正在使用平均堆栈在网格中显示以下数组。 嵌套数组:

  • 我需要更新嵌套在我的用户文档中的一个字段,该字段包含一个part对象数组,以添加新的part。一个part对象如下所示: 所以这意味着$addToset对我的情况没有好处...现在我不知道该怎么办。

  • 我有以下JSON: 我希望能够将内容推送到与迭代 2 关联的任务数组中。如何正确查询并插入到正确的位置?这就是我到目前为止所拥有的,但它总是插入到与迭代 1 关联的任务数组中。 我已经看到了这个:MongoDB嵌套数组查询,但他只是试图推送到一个嵌套数组。

  • 问题内容: 我有以下mongodb文件结构: 我已经能够使用$ elemMatch来更新操作中的字段,但是当我尝试对参数执行相同的操作(修改)时,它似乎不起作用。我想知道我应该尝试哪种其他方法,以便能够成功更新特定参数中的字段(通过其pid查找)。 我当前拥有但不起作用的更新代码如下所示: 问题答案: MongoDB 3.6及更高版本 MongoDB3.6及更高版本提供了一项新功能,该功能允许您使