【问题标题】:update specific element from nested document array mongodb where has two matches从嵌套文档数组 mongodb 更新特定元素,其中有两个匹配项
【发布时间】:2021-05-06 20:14:57
【问题描述】:

如果不存在,我需要更新或创建特定的 obj,设置 score.b1 =50 和 total=100 where object match curse=5 block=2

{ "_id":"sad445"
  "year":2020,
  "grade":4,
  "seccion":"A",
    "id": 100,
  "name": "pedro",
  "notes":[{"curse":5, 
          "block":1, 
          "score":{ "a1": 5,"a2": 10, "a3": 15},
          "total" : 50
          },{
          "curse":5, 
          "block":2, 
          "score":{ "b1": 10,"b2": 20, "b3": 30},
          "total" : 20
          }
   ]
}

我可以更新所有 obj,但我需要从分数而不是全部更新或创建特定的元素。和/或创建 objs "notes":[{curse, block and score}] 如果 notes 为空 notes:[]

notas.UpdateMany(
{"$and":[{"_id":"sad445"},{"notes":{"$elemMatch":{"curse":5,"block":3}}}]},

{"$set":{"updated_at":{"$date":{"$numberLong":"1620322881360"}},

"notes.$.score":{"vvkzo":15,"i2z4i":2,"i2z4i|pm":5},
"notes.$.total":100}},

{"multiple":false})

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework laravel-mongodb


    【解决方案1】:

    演示 - https://mongoplayground.net/p/VaE28ujeOPx

    使用$ (update)

    位置 $ 运算符标识数组中要更新的元素,而无需明确指定该元素在数组中的位置。

    位置 $ 运算符充当与查询文档匹配的 first 元素的占位符,并且

    数组字段必须作为查询文档的一部分出现。

    db.collection.update({
      "notes": {
        "$elemMatch": { "block": 2, "curse": 5 }
      }
    },
    {
      $set: { "notes.$.score.b4": 40 }
    })
    

    阅读upsert:是的

    可选。如果为真,update() 要么:

    如果没有与查询匹配的文档,则创建一个新文档。更多 细节见upsert行为。更新匹配的单个文档 查询。如果 upsert 和 multi 都为真并且没有文档匹配 查询时,更新操作只插入一个文档。

    为避免多次更新插入,请确保查询字段是唯一的 索引。有关示例,请参阅带有唯一索引的 Upsert。

    默认为false,不匹配时不插入新文档 找到了。


    更新

    演示 - https://mongoplayground.net/p/iQQDyjG2a_B

    使用$function

    db.collection.update(
        { "_id": "sad445" },
        [
          {
            $set: {
              notes: {
                $function: {
                  body: function(notes) {
                            var record = { curse:5, block:2, score:{ b4:40 } };
                            if(!notes || !notes.length) { return [record]; } // create new record and return in case of no notes
                            var updated = false;
                            for (var i=0; i < notes.length; i++) {
                                if (notes[i].block == 2 && notes[i].curse == 5) { // check condition for update
                                    updated = true;
                                    notes[i].score.b4=40; break; // update here
                                }
                            }
                            if (!updated) notes.push(record); // if no update push the record in notes array
                            return notes;
                        },
                  args: [
                    "$notes"
                  ],
                  lang: "js"
                }
              }
            }
          }
        ]
    )
    

    【讨论】:

    • 是的!有效,但我的问题是当"notes": [] 为空时,在这种情况下,我需要创建 obj {"curse": 5, "block": 2, "notes":{"b4": 100} } 请帮帮我我该怎么做。
    • @Carlos 你用的是哪个版本的mongodb?
    • mongodb v 4.4.5
    • 非常感谢!!!你从哪来?你在哪里学的?
    • @Carlos 很高兴它有帮助:)
    【解决方案2】:

    尝试添加upsert: true

    如果没有与查询匹配的文档,则创建一个新文档。更新匹配的单个文档 查询。

    notas.UpdateMany(
    {"$and":[{"_id":"sad445"},{"notes":{"$elemMatch":{"curse":5,"block":3}}}]},
    
    {"$set":{"updated_at":{"$date":{"$numberLong":"1620322881360"}},
    
    "notes.$.score":{"vvkzo":15,"i2z4i":2,"i2z4i|pm":5},
    "notes.$.total":100}},
    
    {"multiple":false, "upsert":true})
    

    【讨论】:

      猜你喜欢
      • 2017-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      相关资源
      最近更新 更多