Maicmi
Maicmi

Reputation: 1104

Golang and MongoDB - I try to update toggle boolean using golang to mongodb but got object instead

I used to implement todo application using React and Nodejs. The toggle function in React and Nodejs to update Mongodb database as following code:

const toggleChecked = ({ _id, isChecked }) => {
  TasksCollection.update(_id, {
    $set: {
      isChecked: !isChecked
    }
  })
};

I would like to implement toggle function in Golang to update boolean field, but I got object instead, the following is golang code:

func updateOneMovie(movieId string) model.Netflix {
    id, _ := primitive.ObjectIDFromHex(movieId)
    filter := bson.M{"_id": id}
    update := bson.M{"$set": bson.M{"watched": bson.M{"$not": "$watched"}}}
    var updateResult model.Netflix

    result, err := collection.UpdateOne(context.Background(), filter, update)

    err = collection.FindOne(context.Background(), filter).Decode(&updateResult)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(result)
    return updateResult
}

The result in Mongodb updates as the object instead of boolean. How can I fix to make it update toggle boolean?

Upvotes: 1

Views: 264

Answers (2)

icza
icza

Reputation: 418435

Passing a single document (e.g. bson.M or bson.D) as the update document, field names and values will be interpreted as-is (literally).

To use aggregation pipelines with updates, you must pass an array as the update document, this is what triggers interpreting it as an aggregation pipeline. This is the only requirement. The array may be mongo.Pipeline, bson.A, []bson.D, []bson.M or even []any, it doesn't matter, it just must be an array or slice in Go. The elements may be bson.M, bson.D or any other values representing a document.

So the simplest solution:

filter := bson.M{"_id": id}
update := []any{
    bson.M{"$set": bson.M{"watched": bson.M{"$not": "$watched"}}}
}

Upvotes: 1

Maicmi
Maicmi

Reputation: 1104

I found the solution, I use Pipeline with bson.D as the following code:

func updateOneMovie(movieId string) model.Netflix {
    id, _ := primitive.ObjectIDFromHex(movieId)
    filter := bson.M{"_id": id}
    update := bson.D{{Key: "$set", Value: bson.D{{Key: "watched", Value: bson.D{{Key: "$not", Value: "$watched"}}}}}}
    var updateResult model.Netflix

    result, err := collection.UpdateOne(context.Background(), filter, mongo.Pipeline{update})

    err = collection.FindOne(context.Background(), filter).Decode(&updateResult)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Modified Count: ", result.ModifiedCount)
    return updateResult
}

The result, I can update boolean correctly.

Upvotes: 1

Related Questions