这里更大的目标是在go中设置一个更新查询,只设置在请求中发送给它的那些字段。
例如,我有一个要更新的文档,允许用户通过简单地在请求中指定它们来更新可变数量的字段,如下所示:
{
"field1": valueOfField1,
"field2": valueOfField2,
"field3": valueOfField3,
...
}
这里的问题是,当我使用json.Decode
具有大多数字段可选的自定义结构类型对该输入进行解码时,将保留输入中不存在的值nil
。
我的结构看起来像这样-
type Fields struct {
Field1 string `bson:"field1" json:"field1,omitempty"`
Field2 string `bson:"field2" json:"field2"`
Field3 time.Time `bson:"field3,omitempty" json:"field3,omitempty"`
Field4 bool `bson:"field4,omitempty" json:"field4,omitempty"`
...
}
现在在更新查询中,我说,
bson.M{"$set": bson.M{"field1": body.Field1, "field2": body.Field2, "field3": body.Field3, "field4": body.Field4, ...}}
问题是,如果输入中不存在这些字段之一,则它仍将覆盖数据库中的现有值并使它为空。
为避免这种情况,理想情况下,我希望{"field1": body.Field1, "field2": body.Field2, "field3": body.Field3, "field4": body.Field4, ...}
根据进入的字段动态构建此部分。
为此,我做了一个json.Marshal
输入,就像这样-
finalbody, err := json.Marshal(body)
然后我试图在$ set字段中使用它-
bson.M{"$set": string(finalbody)}
当然,这给了我一个错误信息-“修饰符在字段上操作,但我们找到了一个字符串”。该字符串与bson.M完全一样,只是它不是bson.M,即{"field1": valueOfField1, "field2": valueOfField2, "field3": valueOfField1, ...}
我要去哪里错了?[...代表“依此类推”]
我找到了解决方案,方法是将最终主体解组到map [string] interface {}中,然后将其用作更新地图。
所以,
finalbody, err := json.Marshal(body)
var finalbodymap map[string]interface{}
json.Unmarshal(finalbody, &finalbodymap)
当然,您需要添加一些错误处理,因此最终代码如下所示-
finalbody, err := json.Marshal(body)
if err != nil {
log.Println(err)
return
}
var finalbodymap map[string]interface{}
if err = json.Unmarshal(finalbody, &finalbodymap); err != nil{
log.Println(err)
}
然后在更新查询中,我可以简单地写-
bson.M{"$set": finalbodymap}
但这里的一个问题是,在编组时,它将设置任何时间。时间类型的值设置为nil,即“ 0001-01-01T00:00:00Z”。我怀疑在某些其他类型上也可以观察到这种行为。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句