在go中使用预先构造的字符串作为bson.M进行mgo查询
这里更大的目标是让go中的更新查询只设置请求中发送给它的字段 例如,我有一个要更新的文档,我允许用户通过在请求中简单地指定字段来更新可变数量的字段,如下所示-在go中使用预先构造的字符串作为bson.M进行mgo查询,go,marshalling,bson,mgo,gorilla,Go,Marshalling,Bson,Mgo,Gorilla,这里更大的目标是让go中的更新查询只设置请求中发送给它的字段 例如,我有一个要更新的文档,我允许用户通过在请求中简单地指定字段来更新可变数量的字段,如下所示- { "field1": valueOfField1, "field2": valueOfField2, "field3": valueOfField3, ... } finalbody, err := json.Marshal(body) 这里的问题是,当我使用json.decode将此输入解码为具有大多数可选字段的自定义结构类型时,
{
"field1": valueOfField1,
"field2": valueOfField2,
"field3": valueOfField3,
...
}
finalbody, err := json.Marshal(body)
这里的问题是,当我使用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"`
...
}
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": 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
,如下所示-
{
"field1": valueOfField1,
"field2": valueOfField2,
"field3": valueOfField3,
...
}
finalbody, err := json.Marshal(body)
然后我尝试在$set字段中使用它作为-
bson.M{"$set": string(finalbody)}
当然,这给了我一个错误:“修饰符对字段进行操作,但我们找到了一个字符串”。
字符串与bson.M完全相同,只是它不是bson.M,即{“field1”:valueofield1,“field2”:valueofield2,“field3”:valueofield1,…}
我哪里做错了?
[…represents'等']我通过将finalbody解组到map[string]接口{}中,然后将其用作更新映射找到了解决方案 所以 当然,您需要添加一些错误处理,以便最终代码如下所示-
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"`
...
}
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}
但这里的一个问题是,在编组时,它会将任何time.time类型的值设置为nil,即“0001-01-01T00:00:00Z”。我怀疑在其他类型的人身上也可以观察到这种行为。嘿,伙计,你做得很好!