使用MongoDB Golang驱动程序的UpdateOne时,Upsert未能工作

10

供参考,我有以下结构体:

type OpenOrderCleaned struct {
    OrderID             string    `json:"orderId" bson:"orderId"`
    DateTimeOrderPlaced time.Time `json:"dateTimeOrderPlaced" bson:"dateTimeOrderPlaced"`
    OrderItems          []struct {
        OrderItemID   string `json:"orderItemId" bson:"orderItemId"`
        Ean           string `json:"ean" bson:"ean"`
        CancelRequest bool   `json:"cancelRequest" bson:"cancelRequest"`
        Quantity      int    `json:"quantity" bson:"quantity"`
    } `json:"orderItems" bson:"orderItems"`
}

我收到了一个包含多个JSON实例的API响应,我想将其保存在MongoDB中,因此我使用了for循环。我希望通过使用唯一的orderId字段来检查数据库中是否已经存在文档。我认为UpdateOne是一个不错的选择,因为它有upsert选项。因此,如果orderId不存在,就应该生成完整的文档并存储在数据库中。

for _, OpenOrderCleaned := range o.Orders {

    c := auth.GetClient()
    collection := c.Database("goprac").Collection(x)

    filter := bson.M{"orderId": bson.M{"$eq": OpenOrderCleaned.OrderID}}
    update := bson.M{
        "$set": bson.M{
            "orderId":             OpenOrderCleaned.OrderID,
            "dateTimeOrderPlaced": OpenOrderCleaned.DateTimeOrderPlaced,
            "orderItems":          OpenOrderCleaned.OrderItems,
        },
    }

    ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)
    result, err := collection.UpdateOne(ctx, filter, update)

    if err != nil {
        fmt.Println("UpdateOne() result ERROR:", err)
        os.Exit(1)
    } else {
        fmt.Println("UpdateOne() result:", result)
        fmt.Println("UpdateOne() result TYPE:", reflect.TypeOf(result))
        fmt.Println("UpdateOne() result MatchedCount:", result.MatchedCount)
        fmt.Println("UpdateOne() result ModifiedCount:", result.ModifiedCount)
        fmt.Println("UpdateOne() result UpsertedCount:", result.UpsertedCount)
        fmt.Println("UpdateOne() result UpsertedID:", result.UpsertedID)
    }

}

但是现在 Upsert 没有起作用。当我手动将文档放入 MongoDB 并运行程序时,它会进行更新。那么为什么没有在数据库中创建新的实例呢?我需要在某个地方声明 upsert=True 吗?或者是 "orderItems": OpenOrderCleaned.OrderItems 的映射不正确吗?

感谢任何帮助。

1个回答

27
你正在调用update而不是upsert。你需要向UpdateOne传递正确的选项以执行upsert操作。这是来自mongo驱动程序示例的提示:
opts := options.Update().SetUpsert(true)
filter := bson.D{{"_id", id}}
update := bson.D{{"$set", bson.D{{"email", "newemail@example.com"}}}}

result, err := coll.UpdateOne(context.TODO(), filter, update, opts)

你缺少opts参数。

1
似乎自版本1.8以来,“UpdateOne”尽管设置了“options.Update().SetUpsert(true)”,但仍未插入。发生了什么?文档自相矛盾。 - Zyl
update参数不是更新文档时,UpdateOne似乎会默默失败。在从旧版本迁移代码时,我们忽略了这个变化。 - Zyl
当您的id是primitive.NilObjectID时,您是否遇到过问题,导致upsert最终会在id为00000000000的记录中结束?您如何处理这种情况? - Someone Special

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接