我如何使用Golang在MongoDB中查找并修改一条记录?

6

我希望得到这样的结果:

  1. 在MongoDB中查找一条记录 old_record
  2. 将此记录更新为 new_record
  3. 返回 old_record

我的代码如下:

ret = nil
// First, Find the obj
obj := &orm.QuerySetObj{}
err2 := this.querySetCollection.With(session).Find(objKey).One(obj)
if nil != err2 {
    this.logger.Println("Error find obj")
    return
}

ret = obj

// Then, update this obj
obj.updateTime = time.Now().Unix()
err3 := this.querySetCollection.With(session).Upsert(objKey, obj)
if nil != err3 {
    this.logger.Println("Error update obj")
    return
}

return

但是,我认为查找更新应该是一种原子操作,因此我的代码不安全。

如何在一个原子操作中完成这个操作?

1个回答

16
这里采用的方法是.Apply(),它接受一个Change类型并返回ChangeInfo
文档中的直接示例:
change := mgo.Change{
        Update: bson.M{"$inc": bson.M{"n": 1}},
        ReturnNew: false,
}
info, err = col.Find(M{"_id": id}).Apply(change, &doc)
fmt.Println(doc.N)

其中doc是找到的文档,并且其状态取决于Change参数中ReturnNew值的设置,当您想要原始文档时该值为false

基本上,所有参数的形式都与.findAndModify()相同。


其实在我提问之前我已经找到了这个答案,但是我只找到了一条记录,我应该用 limit(1) 替换 One(obj) 吗? - roger
@roger 不是相反的。这里使用的Change集合的.Apply()原子性的,而你的代码不是。这就是我在这里解决的问题。没有.One()调用。这个方法“只”一次修改一个文档。这就是mgo版本的.findAndModify(),这也是你所问的问题。 - Blakes Seven
@罗杰,.findAndModify()方法会做你问题所问的事情。你不能同时修改“n”条记录并一次性返回它们。MongoDB没有这种方法,因为这根本没有意义。要么一个一个用.findAndModify(),要么一次性使用.update()。但是对于多个记录,你不能返回修改后或原始数据。那是一个单独的查询。 - Blakes Seven
让我们在聊天室里继续讨论 - roger
1
我们如何使用Go官方的MongoDB驱动程序来实现相同的功能呢? - Arka Mukherjee
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接