MongoDB 更新文档数组并替换为替换文档数组

MongoDB update array of documents and replace by an array of replacement documents

是否可以通过一组替换字段(文档)批量更新(插入)具有 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) 修饰符对字段进行操作,但我们发现类型数组。

非常感谢任何帮助!

您可以使用 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() 快得多。