【问题标题】:MongoDB update array of documents and replace by an array of replacement documentsMongoDB更新文档数组并替换为替换文档数组
【发布时间】:2022-01-17 23:49:42
【问题描述】:

是否可以通过替换字段(文档)数组使用 MongoDB 批量更新(更新插入)文档数组?

基本上摆脱了这个伪代码示例中的for循环:

for user in users {
  db.users.replaceOne(
      { "name" : user.name },
      user,
      { "upsert": true }
}

updateMany 文档仅记录以下所有文档都以相同方式更新的情况:

db.collection.updateMany(
   <query>,
   { $set: { status: "D" }, $inc: { quantity: 2 } },
   ...
)

我正在尝试更新(更新)一组文档,其中每个文档都有自己的一组替换字段:

updateOptions := options.UpdateOptions{}
updateOptions.SetUpsert(true)
updateOptions.SetBypassDocumentValidation(false)
_, error := collection.Col.UpdateMany(ctx, bson.M{"name": bson.M{"$in": names}}, bson.M{"$set": users}, &updateOptions)

其中 users 是一个文档数组:

[
{ "name": "A", ...further fields},
{ "name": "B", ...further fields},
...
]

显然,$set 不能用于这种情况,因为我收到以下错误:批量写入时出错 *v1.UserCollection (FailedToParse) 修饰符对字段进行操作,但我们找到了类型数组。

非常感谢任何帮助!

【问题讨论】:

    标签: arrays mongodb go mongo-go


    【解决方案1】:

    您可以使用Collection.BulkWrite()

    由于您希望以不同方式更新每个文档,因此您必须为每个文档更新准备不同的mongo.WriteModel

    您可以使用mongo.ReplaceOneModel 来替换单个文档。你可以这样构造它们:

    wm := make([]mongo.WriteModel, len(users)
    for i, user := range users {
        wm[i] = mongo.NewReplaceOneModel().
            SetUpsert(true).
            SetFilter(bson.M{"name": user.name}).
            SetReplacement(user)
    }
    

    您可以通过这样的一次调用来执行所有替换:

    res, err := coll.BulkWrite(ctx, wm)
    

    是的,这里我们也有一个循环,但那是准备我们要执行的写入任务。所有这些都通过一次调用发送到数据库,如果可能,数据库可以“免费”并行执行它们。这可能比为每个文档单独调用Collection.ReplaceOne() 快​​得多。

    【讨论】:

      猜你喜欢
      • 2012-03-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-08
      • 2019-03-12
      • 1970-01-01
      • 2023-03-05
      • 2016-10-01
      相关资源
      最近更新 更多