使用过滤器中的值更新文档

我在 MongoDB 中有一个具有以下结构的集合:


{

  "userId": String,

  "refs": Set<String>

}

我需要用这些文档更新集合。我想为refsfilter 中的用户添加一个新字符串$in。但是,如果用户不存在,我需要“更新”他。


在代码(golang)中,它看起来像这样:


filter := bson.M{

    "userId": bson.M{

        "$in:": tokens // tokens is []string

    }

}


update := bson.M{

    "$addToSet": bson.M{

        "refs": newReference

    }

}


ctx, _ := newDbOperationContext()

_, err := driver.UpdateMany(ctx, filter, update)

因此,对于现有用户来说它工作正常,添加了参考。但是,对于不存在的用户,什么都不会发生。


我设置了driver.UpdateMany(bson, bson, opts...)opts to options.UpdateOptions.SetUpsert(true)",但结果我得到了一个没有 userId 的文档:


{

  "_id": ObjectId("..."),

  "refs": ["new_reference"]

}

所以,我的问题是,如何用userId字段更新新值。


规模就像要更新 2*10^6 个用户,所以我想使用批处理请求来做到这一点。我认为,使用“一个一个”创建并更新他不是一个选项。


谢谢你的支持!


小怪兽爱吃肉
浏览 103回答 3
3回答

LEATH

根据之前在 SO 中的问题,例如这个和另一个,似乎不可能upserts仅使用$in运算符执行多个,因为它只会插入一个文档(与过滤器匹配的那个):如果没有文档与查询条件匹配,则 db.collection.update() 插入单个文档。因此,正如@Kartavya 所提到的,最好的方法是使用BulkWrite.为此,您需要为每个用户附加一个 upsert 操作(= WriteModel)tokens作为过滤器,并且您可以使用相同的$addToSet更新操作:tokens := [...]string{"userId1", "userId3"}newRef := "refXXXXXXX"// all docs can use the same $addToSet update operationupdateOp := bson.D{{"$addToSet", bson.D{{"refs", newRef}}}}// we'll append one update for each userId in tokens as a filterupserts := []mongo.WriteModel{}for _, t := range tokens {&nbsp; &nbsp; upserts = append(&nbsp; &nbsp; &nbsp; &nbsp; upserts,&nbsp; &nbsp; &nbsp; &nbsp; mongo.NewUpdateOneModel().SetFilter(bson.D{{"userId", t}}).SetUpdate(updateOp).SetUpsert(true))}opts := options.BulkWrite().SetOrdered(false)res, err := col.BulkWrite(context.TODO(), upserts, opts)if err != nil {&nbsp; &nbsp; log.Fatal(err)}fmt.Println(res)

catspeake

查看您的用例,我认为最好的解决方案如下:由于您的规模很大并且希望进行批量请求,因此最好使用 BulkWrite : db.collection.bulkWrite() 方法提供了执行批量插入、更新和删除操作的能力。示例:https ://godoc.org/go.mongodb.org/mongo-driver/mongo#example-Collection-BulkWrite这使用 UpdateOne 模型,但它也支持 UpdateMany 模型。它也是 SetUpsert(true) 的一个功能 现在对于 _id 字段:您更新/更新的文档应该具有 _id 字段,以便新文档具有该 _id 字段,否则 mongoDb 会在插入文档时自动生成一个 _id 字段,如果您的 upsert 文档有没有 _id 字段我认为,在您的文档中包含 _id 字段不会很痛苦,这样您的问题就解决了。关于规模,我建议将 BulkWrite 与 UpdateOne 或 UpdateMany 模型一起使用。

手掌心

在 upsert 的情况下,如果文档不存在,那么只有查询的更新部分会插入到数据库中。所以这就是为什么你的输出是这样的。你可以在这里看到。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go