qmgo icon indicating copy to clipboard operation
qmgo copied to clipboard

关于在Update方法中设置upsert的问题

Open roirea opened this issue 2 years ago • 2 comments

我希望能够实现如果文档不存在就插入的功能,在update的option中设置了upsert为true。 实际应用中,当匹配不到条件时,能够执行插入功能,但是会返回 mongo: no documents in result 错误信息。告诉我没有匹配结果。 按理说如果设置了upsert为true,那么就算没有匹配结果也应该是正常的,不应该返回这个错误吧。

这是业务代码

now := time.Now()
filter := bson.M{"year": now.Year(), "month": int(now.Month()), "day": now.Day(), "operate": operate}
update := bson.M{operator.Push: bson.M{"posts": item}}

var upset bool = true
  option := options.UpdateOptions{
  UpdateOptions: &mongoOptions.UpdateOptions{Upsert: &upset},
}

err := db.Mongo.Collection(this.table()).UpdateOne(context.TODO(), filter, update, option)
if err != nil {
  fmt.Println(err)
}

在源码的 collection.go 的217行,对匹配条件进行判断,如果匹配结果数量为0,就会返回未匹配错误,并没有对upsert进行判断。

res, err := c.collection.UpdateOne(ctx, filter, update, updateOpts)
if res != nil && res.MatchedCount == 0 {
  err = ErrNoSuchDocuments
}
if err != nil {
  return err
}

当文档未匹配时,res的MatchedCount为0,UpsertedCount为1。 是否应该对upsert的结果进行判断,来决定要不要返回 ErrNoSuchDocuments 错误呢?

例如进行如下修改,如果没有设置upsert,或者设置了upsert但值为false的话,才返回未匹配错误。

res, err := c.collection.UpdateOne(ctx, filter, update, updateOpts)
if res != nil && res.MatchedCount == 0 {
  if updateOpts.Upsert == nil || *updateOpts.Upsert == false {
    err = ErrNoSuchDocuments
  }
  // 其他判断条件 如 if UpsertedCount == 0 { err = upsert错误 }
}
if err != nil {
  return err
}

roirea avatar May 09 '22 04:05 roirea

返回这个错误就是告知调用者到底是update还是insert吧

srt180 avatar May 11 '22 01:05 srt180

我也遇到了这个问题,看官方怎么解决吧

BBplux avatar Aug 02 '22 04:08 BBplux