doushi1510 2016-09-12 09:21
浏览 236
已采纳

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

The larger goal here is to have an update query in go set only those fields that are sent to it in the request.

For e.g., I have a document to update where I am allowing the user to update a variable number of fields by simply specifying them in the request like so -

{
"field1": valueOfField1,
"field2": valueOfField2,
"field3": valueOfField3,
...
}

The problem here is that when I decode this input using json.Decode to a custom struct type which has most fields optional, the values which do not exist in the input are left nil.

My struct looks like this -

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"`
...
}

Now in my update query, I say,

bson.M{"$set": bson.M{"field1": body.Field1, "field2": body.Field2, "field3": body.Field3, "field4": body.Field4, ...}}

The problem is that if one of these fields does not exist in the input, it still over-writes existing values in the database and makes it null.

To avoid this, I would ideally want that this {"field1": body.Field1, "field2": body.Field2, "field3": body.Field3, "field4": body.Field4, ...} part is dynamically constructed depending on the fields coming in.

To do that, I did a json.Marshal of the input, like so -

finalbody, err := json.Marshal(body)

And then I am trying to use this inside the $set field as -

bson.M{"$set": string(finalbody)}

Of course this gives me an error saying - "Modifiers operate on fields but we found a string instead". The string is perfectly just like the bson.M would've been except that it is not a bson.M i.e. {"field1": valueOfField1, "field2": valueOfField2, "field3": valueOfField1, ...}

Where am I going wrong? [... represents 'and so on']

  • 写回答

1条回答 默认 最新

  • doubao7287 2016-09-15 06:26
    关注

    I found the solution by Unmarshalling finalbody into a map[string]interface{} and then using that as the update map.

    So,

    finalbody, err := json.Marshal(body)
    var finalbodymap map[string]interface{}
    json.Unmarshal(finalbody, &finalbodymap)
    

    Of course, you need to add some error handling so the final code looks like this -

    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)
        }
    

    And then in the update query, I can simply write -

    bson.M{"$set": finalbodymap}
    

    One issue here though was that while Marshalling, it would set any time.Time type values to nil i.e. "0001-01-01T00:00:00Z". I suspect such behavior could be observed with certain other types as well.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog