Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upsert not working when using UpdateOne with the MongoDB Golang driver

Tags:

mongodb

go

For reference, I have this struct:

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"`
}

I get an API response with multiple JSON instances that I want to save in MongoDB, so I use a for loop. I want to check if a document already exists in the database, by using the orderId field, which is unique for every JSON instance. I thought UpdateOne was a good option for this because it has upsert. So if the orderId does not exist, the full document should be generated and stored in the database.

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)
    }

}

But right now the Upsert is not working. When I put a manual document into MongoDB and running the program, it is updating though. So why are new instances not made in the database? Do I have to state somewhere upsert=True or something? Or is maybe the mapping of "orderItems": OpenOrderCleaned.OrderItems not correct?

Any help is appreciated.

like image 762
Raf Rasenberg Avatar asked Dec 12 '19 18:12

Raf Rasenberg


People also ask

Does MongoDB support Upsert?

Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.

Is there an Upsert option in the MongoDB insert command?

insert() provides no upsert possibility.

Is Upsert false by default?

By default, the value of the upsert option is false. If the value of upsert in a sharded collection is true then you have to include the full shard key in the filter.

What is MongoDB go Driver?

Getting started with MongoDB The first step is to install mongo-go-driver, the official Go driver for MongoDB. It provides functionalities that allow a Go application to connect to a MongoDB database and execute queries.


1 Answers

You are calling update, not upsert. You have to pass the correct options to UpdateOne to upsert. This is from the mongo driver examples:

opts := options.Update().SetUpsert(true)
filter := bson.D{{"_id", id}}
update := bson.D{{"$set", bson.D{{"email", "[email protected]"}}}}

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

You are missing the opts.

like image 97
Burak Serdar Avatar answered Sep 20 '22 02:09

Burak Serdar