【问题标题】:Mongoose, update values in array of objectsMongoose,更新对象数组中的值
【发布时间】:2013-03-19 10:40:50
【问题描述】:

有没有办法更新对象中的值?

{
  _id: 1,
  name: 'John Smith',
  items: [{
     id: 1,
     name: 'item 1',
     value: 'one'
  },{
     id: 2,
     name: 'item 2',
     value: 'two'
  }]
}

假设我想更新 id = 2 的项目的名称和值项目;

我已经尝试了以下 w/猫鼬:

var update = {name: 'updated item2', value: 'two updated'};
Person.update({'items.id': 2}, {'$set':  {'items.$': update}}, function(err) { ...

这种方法的问题是它会更新/设置整个对象,因此在这种情况下我会丢失 id 字段。

在 mongoose 中有没有更好的方法来设置数组中的某些值但不理会其他值?

我也只查询了这个人:

Person.find({...}, function(err, person) {
  person.items ..... // I might be able to search through all the items here and find item with id 2 then update the values I want and call person.save().
});

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    使用点对象找到了这个解决方案,它帮助了我。

    import dot from "dot-object";
    
    const user = await User.findByIdAndUpdate(id, { ...dot.dot(req.body) });
    

    【讨论】:

      【解决方案2】:
      model.update(
          { _id: 1, "items.id": "2" },
          {
              $set: {
                  "items.$.name": "yourValue",
                  "items.$.value": "yourvalue",
               }
          }
      )
      

      MongoDB Document

      【讨论】:

      • 而不是update,最好使用updateOneupdateMany
      【解决方案3】:

      以下是如何更动态地更新对象数组中的值的示例。

      Person.findOneAndUpdate({_id: id}, 
      { 
        "$set": {[`items.$[outer].${propertyName}`]: value} 
      },
      { 
        "arrayFilters": [{ "outer.id": itemId }]
      },
      function(err, response) {
        ...
      })
      

      请注意,通过这样做,您可以通过添加额外的arrayFilters 和位置运算符来更新嵌套数组的更深层次,如下所示:

      "$set": {[`items.$[outer].innerItems.$[inner].${propertyName}`]: value} 
      
      "arrayFilters":[{ "outer.id": itemId },{ "inner.id": innerItemId }]
      

      更多用法可以在official docs找到。

      【讨论】:

      • 酷,也许请添加一个链接到有关这件事的官方文档
      • 兄弟,"arrayFilters":[{$and:[{ "outer.id": itemId },{ "outer.name": itemName }]}]。它不适用于 mongoose 5.2 和 findOneAndUpdate。得到“没有为标识符项目找到数组过滤器......”。请提供一些见解
      • @FirojSiddiki 我相信您的问题与过时的 MongoDB Node.JS 驱动程序有关。请更新到 3.0+。另外,我认为你不需要$and
      【解决方案4】:

      我也有类似的问题。这是最干净的方法。

          const personQuery = {
             _id: 1  
          }
      
          const itemID = 2;
      
          Person.findOne(personQuery).then(item => {
             const audioIndex = item.items.map(item => item.id).indexOf(itemID);
             item.items[audioIndex].name = 'Name value';
             item.save();
          });
      

      【讨论】:

      • 我认为内存中的操作可能会导致在非常高的写入周期内处理过时的数据。
      【解决方案5】:
      update(
          {_id: 1, 'items.id': 2},
          {'$set': {'items.$[]': update}},
          {new: true})
      

      这是关于$[]的文档:https://docs.mongodb.com/manual/reference/operator/update/positional-all/#up.S[]

      【讨论】:

      • 不幸的是,这不起作用。它不会替换整个数组
      • 应该替换items数组的元素(id为2的item)
      • 我需要这个谢谢
      【解决方案6】:

      尝试了其他效果很好的解决方案,但他们的答案的缺陷是只有已经存在的字段会更新,添加 upsert 将无济于事,所以我想出了这个。

       Person.update({'items.id': 2}, {$set: {
          'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
      true })
      

      【讨论】:

        【解决方案7】:

        有一种猫鼬方法。

        const itemId = 2;
        const query = {
          item._id: itemId 
        };
        Person.findOne(query).then(doc => {
          item = doc.items.id(itemId );
          item["name"] = "new name";
          item["value"] = "new value";
          doc.save();
        
          //sent respnse to client
        }).catch(err => {
          console.log('Oh! Dark')
        });
        

        【讨论】:

        • 如果您对父文档以及数组项进行操作,此方法很方便。
        • 当我更新文档时,是否也更新了该文档的_id?很奇怪。
        【解决方案8】:

        要记住一件事,当您根据多个条件在数组中搜索对象时,请使用 $elemMatch

        Person.update(
           {
             _id: 5,
             grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } }
           },
           { $set: { "grades.$.std" : 6 } }
        )
        

        这里是docs

        【讨论】:

          【解决方案9】:

          你很接近;您应该在使用 $ update operator 时使用点符号来做到这一点:

          Person.update({'items.id': 2}, {'$set': {
              'items.$.name': 'updated item2',
              'items.$.value': 'two updated'
          }}, function(err) { ...
          

          【讨论】:

          • 您好,当我完全按照您的建议进行操作时。 board.update({ _id: board._id,"users.username": req.user.username}, {$set: {"users.$.lastViewed": new Date()}}, function (err) {} );我得到一个错误:不能使用部分(users.username的用户)来遍历元素({users:[{用户名:“nlm”,_id:ObjectId('583c8cc3813daa6c29f69cb0'),状态:“邀请”,角色:“审稿人”}]})。我有什么不同的做法吗?
          • 这很好用,谢谢。但是,如果它不在数组中,有什么方法可以创建一个项目?
          • @SergeyMell 如果我认为这可能是一个解决方案:stackoverflow.com/a/33577318/6470918
          • 如何更新集合中所有文档中 id = 2 的名称?
          • 如果数组中有一个对象数组,这将如何工作?就像你有items.users.$.status 而不是items.$.name?那行得通吗?
          【解决方案10】:

          在 Mongoose 中,我们可以使用 $set inside dot(.) 表示法将数组值更新为以下方式的特定值

          db.collection.update({"_id": args._id, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})
          

          【讨论】:

          • 请您编辑带有解释的答案,还是与问题相关?
          • 你能看看我的问题吗,猫鼬正在删除我的查询中使用 $[] 的部分,即使它在 CLI stackoverflow.com/questions/64223672/…987654321@ 中工作
          【解决方案11】:

          在 mongoose 中我们可以更新,比如简单的数组

          user.updateInfoByIndex(0,"test")
          
          User.methods.updateInfoByIndex = function(index, info) ={
              this.arrayField[index]=info
              this.save()
          }
          

          【讨论】:

          • 您的回答对一些解释会更有帮助。请考虑编辑它。
          【解决方案12】:

          对于每个文档,更新运算符$set 可以set multiple values,因此您可以单独设置对象的namevalue 字段,而不是替换items 数组中的整个对象。

          {'$set':  {'items.$.name': update.name , 'items.$.value': update.value}}
          

          【讨论】:

            猜你喜欢
            • 2019-03-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-16
            • 1970-01-01
            • 2015-01-31
            相关资源
            最近更新 更多