更新MongoDB中的非零值

huangapple go评论69阅读模式
英文:

Go Mongo Update NonZero values only

问题

如何仅更新非零值的文档。例如,对于状态(status)我没有收到任何值,而Struct只有两个要更新的值。因此,它应该只更新这两个值并跳过零/空值。但是如下所示,它将其更新为零/空/""。

type Product struct {
	ID          primitive.ObjectID `json:"id" bson:"_id"`
	Status      int                `json:"status" bson:"status"`
	DisplayName string             `json:"displayName" bson:"display_name"`
	Text        string             `json:"text" bson:"text"`
}

我尝试了以下方法,但如果没有为状态(status)传递任何值,它会将其覆盖为0。

opts := options.Update().SetUpsert(false)

filter := bson.D{primitive.E{Key: "_id", Value: product.ID}}
update := bson.D{
	{"$set", bson.D{
		{"status", product.Status},
		{"text", product.Text},
		{"display_name", product.DisplayName},
	}},
}
_, err := db.Collection("product").UpdateOne(context.TODO(), filter, update, opts)

如何在不使用if语句的情况下实现这一点。对于Service中的任何结构体都适用。

英文:

How to update the document with non zero values only. As example I didn't received any value for status and Struct has only two values to be updated. So it should only update those 2 values and skip zero/null values. But as given below it's updating it to zero/null/""

type Product struct {
	ID          primitive.ObjectID `json:"id" bson:"_id"`
	Status      int                `json:"status" bson:"status"`
	DisplayName string             `json:"displayName" bson:"display_name"`
	Text        string             `json:"text" bson:"text"`
}

I have tried the following up it's overriding the status value to 0 if no value is passed for it.

	opts := options.Update().SetUpsert(false)

	filter := bson.D{primitive.E{Key: "_id", Value: product.ID}}
	update := bson.D{{"$set", bson.D{{"status", product.Status}, bson.D{{"text",product.Text}, {"display_name", product.DisplayName}}}}
	_, err := db.Collection("product").UpdateOne(context.TODO(), filter, update, opts)

How to achieve this cleanly without ifs. For any struct in Service.

答案1

得分: 3

首先,你的update文档如果Product是你模型化文档的Go结构体,就不应该包含嵌入文档。应该是这样的:

update := bson.D{
    {"$set", bson.D{
        {"status", product.Status},
        {"text", product.Text},
        {"display_name", product.DisplayName},
    }},
}

现在来解决你的问题。你在update文档中明确告诉MongoDB将它们设置为零值,所以MongoDB就会这样做。

如果你不想设置零值,就不要将它们添加到更新文档中。可以像这样构建你的update文档:

setDoc := bson.D{}
if product.Status != 0 {
    setDoc = append(setDoc, bson.E{"status", product.Status})
}
if product.Text != "" {
    setDoc = append(setDoc, bson.E{"text", product.Text})
}
if product.DisplayName != "" {
    setDoc = append(setDoc, bson.E{"display_name", product.DisplayName})
}

update := bson.D{{"$set", setDoc}}

请注意,如果你使用,omitempty的BSON标签选项,并为setDoc使用/传递Product结构体值,你也可以实现相同的效果:

type Product struct {
    ID          primitive.ObjectID `json:"id" bson:"_id"`
    Status      int                `json:"status" bson:"status,omitempty"`
    DisplayName string             `json:"displayName" bson:"display_name,omitempty"`
    Text        string             `json:"text" bson:"text,omitempty"`
}

然后简单地

```go
update := bson.D{{"$set", product}}
英文:

First, your update document should not contain an embedded document if Product is the Go struct that models your documents. It should be:

update := bson.D{
	{"$set", bson.D{
		{"status", product.Status},
		{"text", product.Text},
		{"display_name", product.DisplayName},
	}},
}

Now on to your issue. You explicitly tell in the update document to set them to their zero value, so that's what MongoDB does.

If you don't want to set zero values, don't add them to the update document. Build your update document like this:

setDoc := bson.D{}
if product.Status != 0 {
	setDoc = append(setDoc, bson.E{"status", product.Status})
}
if product.Text != "" {
	setDoc = append(setDoc, bson.E{"text", product.Text})
}
if product.DisplayName != "" {
	setDoc = append(setDoc, bson.E{"display_name", product.DisplayName})
}

update := bson.D{{"$set", setDoc}}

Note that you can achieve the same if you use the ,omitempty BSON tag option and use / pass a Product struct value for the setDoc:

type Product struct {
	ID          primitive.ObjectID `json:"id" bson:"_id"`
	Status      int                `json:"status" bson:"status,omitempty"`
	DisplayName string             `json:"displayName" bson:"display_name,omitempty"`
	Text        string             `json:"text" bson:"text,omitempty"`
}

And then simply:

update := bson.D{{"$set", product}}

huangapple
  • 本文由 发表于 2022年12月15日 21:28:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/74812304.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定