英文:
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}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论