如何用Go驱动替换MongoDB中的一个文件?

How to replace a document in MongoDB with Go driver?

我正在尝试用 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 %v\n", 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 is a map, so if you use it, you have to write: bson.M{"_id": oid}. See .

bson.D是struct的一个slice,所以如果用到的话应该写成bson.D{{Key:"$set", Value: input}}。省略字段名称不是编译器错误,这只是兽医警告。

现在开始更换。替换必须是文档本身,不使用 $set (这不是更新而是替换)。有关参考,请参阅 MongoDB 的 collection.replaceOne() and the driver's doc: Collection.ReplaceOne():

The replacement parameter must be a document that will be used to replace the selected document. It cannot be nil and cannot contain any update operators (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)
}