在go中使用预先构造的字符串作为bson.M进行mgo查询

在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将此输入解码为具有大多数可选字段的自定义结构类型时,

这里更大的目标是让go中的更新查询只设置请求中发送给它的字段

例如,我有一个要更新的文档,我允许用户通过在请求中简单地指定字段来更新可变数量的字段,如下所示-

{
"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”。我怀疑在其他类型的人身上也可以观察到这种行为。

嘿,伙计,你做得很好!