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

在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']

此处的更大目标是在go中设置一个更新查询,仅设置在请求中发送给它的那些字段 。 p>

例如,我有一个要更新的文档,允许用户通过像这样简单地在请求中指定它们来更新可变数量的字段- p>

  {
“ field1”:valueOfField1,
“ field2”:valueOfField2,
“ field3”:valueOfField3,
 ... 
} 
  code>  pre  > 
 
 

这里的问题是,当我使用 json.Decode code>将此输入解码为具有大多数字段可选的自定义结构类型时,输入中不存在的值是 左 nil code>。 p>

我的结构如下所示- p>

  type字段结构{
 Field1字符串`  bson:“ field1” json:“ field1,omitempty”`
 Field2字符串`bson:“ field2” json:“ field2”`
 Field3 time.Time`bson:“ field3,omitempty” json:“ field3,omitempty”  
 Field4 bool`bson:“ field4,omitemp  ty“ json:” field4,omitempty“`
 ... 
} 
  code>  pre> 
 
 

现在在我的更新查询中,我说, p>

  bson.M {“ $ set”:bson.M {“ field1”:body.Field1,“ field2”:body.Field2,“ field3”:body.Field3,“ field4”:body  .Field4,...}} 
  code>  pre> 
 
 

问题是,如果输入中不存在这些字段之一,它仍然会覆盖 数据库并使其为空。 p>

为避免这种情况,我理想上希望此 {“ field1”:body.Field1,“ field2”:body.Field2,“ field3” :body.Field3,“ field4”:body.Field4,...} code>部分是根据传入的字段动态构建的。 p>

为此,我做了一个 输入的 json.Marshal code>,就像这样- p>

  finalbody,err:= json.Marshal(body)
  code>   pre> 
 
 

然后我尝试在$ set字段内使用它-- p>

  bson.M {“ $ set”:string(finalbody  )} 
  code>  pre> 
 
 

当然,这给了我一个错误信息-“修饰符对字段进行操作,但我们发现了 该字符串与bson.M完全一样,只是它不是bson.M,即 {“ field1”:valueOfField1,“ field2”:valueOfField2,“ field3”:valueOfField1 ,...} code> p>

我要去哪里了? [...代表'依此类推'] p> div>

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.