在MongoDB中更新精确元素数组中的字段

76

我有一个结构如下的文档:

{
    _id:"43434",
    heroes : [
        { nickname : "test",  items : ["", "", ""] },
        { nickname : "test2", items : ["", "", ""] },
    ]
}
我可以用$set方法更改在数组heros中,昵称为"test"的嵌套对象的items数组的第二个元素吗?
{
    _id:"43434",
    heroes : [
        { nickname : "test",  items : ["", "new_value", ""] }, // modified here
        { nickname : "test2", items : ["", "", ""] },
    ]
}
5个回答

147
你需要利用2个概念:mongodb的位置运算符和简单地使用数字索引来更新所需的条目。

位置运算符允许您使用类似于这样的条件:

{"heroes.nickname": "test"}

然后可以像这样引用找到的数组条目:

{"heroes.$  // <- the dollar represents the first matching array key index

你想要更新"items"中第2个数组条目,而数组键是从0开始计数的 - 这就是键1。

所以:

> db.denis.insert({_id:"43434", heroes : [{ nickname : "test",  items : ["", "", ""] }, { nickname : "test2", items : ["", "", ""] }]});
> db.denis.update(
    {"heroes.nickname": "test"}, 
    {$set: {
        "heroes.$.items.1": "new_value"
    }}
)
> db.denis.find()
{
    "_id" : "43434", 
    "heroes" : [
        {"nickname" : "test", "items" : ["", "new_value", "" ]},
        {"nickname" : "test2", "items" : ["", "", "" ]}
    ]
}

我如何访问匹配元素的值?例如 {"heros.$.items.2": "heros.$.nickname"}? - kommradHomer
@ad7six 我该如何更新最后一个元素。我不知道数组的大小。(在Python中类似于items[-1] = 'new value')。 - Amit Tripathi
@Amit 如果你需要的话:可以通过提问来获得帮助 =) - AD7six

4

尝试使用位置占位符$更新包含嵌入式文档的数组(更新数组中的文档)

位置占位符$操作符简化了对包含嵌入式文档的数组进行更新的操作。使用位置占位符$操作符上的点符号表示法访问嵌入式文档中的字段。

db.collection.update(
  { "heroes.nickname": "test" },
  { $set: { "heroes.$.items.1": "new_value" } },
  { multi: true }
);

游乐场


1

尝试使用位置标记$和$position进行更新。

db.collection.update(
  { heroes:{ $elemMatch:{ "nickname" : "test"} } },
  {
    $push: {
      'heroes.$.items': {
        $each: ["new_value" ],
        $position: 1
      }
    }
  }
)

1

更进一步!使用字符串模板以便按照所需的方式插入变量索引

   yourModel.findOneAndUpdate(
     { _id: "43434" },
     {
       $set: {
         [`heroes.${heroesIndex}.items.${itemIndex}`]: "new_value",
       },
     }
   );

或者没有模板
   yourModel.findOneAndUpdate(
     { _id: "43434" },
     {
       $set: {
         'heroes.0.items.1': "new_value",
       },
     }
   );

1

这个解决方案很好。只想补充一点。这是结构。我需要找到OrderItemId为'yyy'的并更新。如果查询条件中的字段是一个数组,比如"OrderItems.OrderItemId"是一个数组,你不能在查询中使用"OrderItems.OrderItemId[0]"作为操作。相反,你需要使用"OrderItems.OrderItemId"进行比较。否则,它无法匹配到一个。

{
  _id: 'orderid',
  OrderItems: [
   {
     OrderItemId: ['xxxx'], 
    ... },
   {
     OrderItemId: ['yyyy'], 
    ...}, 
]

}

 result =  await collection.updateOne(
        { _id: orderId, "OrderItems.OrderItemId": [orderItemId] },
        { $set: { "OrderItems.$.imgUrl": imgUrl[0], "OrderItems.$.category": category } },
        { upsert: false },
      )
    console.log('  (result.modifiedCount) ', result.modifiedCount)
    console.log('  (result.matchedCount) ', result.matchedCount)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接