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.

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

报告相同问题?

悬赏问题

  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 C#调用python代码(python带有库)
  • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面