如何用Go驱动程序替换MongoDB中的文档



我正在尝试用mongodb/mongo-go-driver更新MongoDB中的一个文档。从其文档中,一个文档可以替换为:

var coll *mongo.Collection
var id primitive.ObjectID
// find the document for which the _id field matches id and add a field called "location"
// specify the Upsert option to insert a new document if a document matching the filter isn't found
opts := options.Replace().SetUpsert(true)
filter := bson.D{{"_id", id}}
replacement := bson.D{{"location", "NYC"}}
result, err := coll.ReplaceOne(context.TODO(), filter, replacement, opts)
if err != nil {
log.Fatal(err)
}
if result.MatchedCount != 0 {
fmt.Println("matched and replaced an existing document")
return
}
if result.UpsertedCount != 0 {
fmt.Printf("inserted a new document with ID %vn", result.UpsertedID)
}

但如果我的田地超过20块呢。我想知道我是否可以在不重写所有字段的情况下再次更新,我尝试了这样的方法:

// Replacement struct
type Input struct {
Name        *string `json:"name,omitempty" bson:"name,omitempty" validate:"required"`
Description *string `json:"description,omitempty" bson:"description,omitempty"`
Location    *string `json:"location,omitempty" bson:"location,omitempty"`
}
... 
oid, _ := primitive.ObjectIDFromHex(id) // because 'id' from request is string
filter := bson.M{"_id", oid} // throws `[compiler] [E] missing key in map literal`
//                      ^^^
replacement := bson.D{{"$set", input}} // throws `composite literal uses unkeyed fields`
//                             ^^^^^
result, err := coll.ReplaceOne(context.TODO(), filter, replacement, opts)
...

但它在过滤器和替换方面会出现错误。如何正确替换整个文档?

bson.M是一个映射,因此如果使用它,则必须编写:bson.M{"_id": oid}。请参阅复合文字go中缺少的类型和映射文字go中丢失的键。

bson.D是结构的切片,所以如果你使用它,你应该写bson.D{{Key:"$set", Value: input}}。省略字段名不是编译器错误,只是一个警告。

现在开始更换。替换必须是文档本身,而不使用$set(这不是更新而是替换(。参考MongoDB的collection.replaceOne()和驱动程序文档:Collection.ReplaceOne():

替换参数必须是将用于替换所选文档的文档。它不能为零并且不能包含任何更新运算符(https://docs.mongodb.com/manual/reference/operator/update/)。

所以这样做:

filter := bson.M{"_id": oid}
result, err := coll.ReplaceOne(context.TODO(), filter, input, opts)

以下是完整的代码。这将帮助读者理解代码流。

func UpdateFunction(echoCtx echo.Context) (error) {
//Web Section
documentID := echoCtx.Param("id")   //Provided in URL
var newObject myStruct
err := echoCtx.Bind(&newObject)  // Json with updated values sent by web client mapped to struct
ctx := echoCtx.Request().Context()
//Database Section
database := db.Conn.Database("myDatabase")
collection := database.Collection("myCollection")
existingHexID, err := primitive.ObjectIDFromHex(documentID)
if err != nil {
fmt.Println("ObjectIDFromHex ERROR", err)
} else {
fmt.Println("ObjectIDFromHex:", existingHexID)
}
// Replacing OLD document with new using _id
filter := bson.M{"_id": newDocumentID}
result, err := collection.ReplaceOne(ctx, filter, newObject)
if err != nil {
log.Fatal(err)
}
fmt.Printf(
"insert: %d, updated: %d, deleted: %d /n",
result.MatchedCount,
result.ModifiedCount,
result.UpsertedCount,
)
return echoCtx.JSON(http.StatusOK, result.ModifiedCount)
}

最新更新