【问题标题】:Why does mgo not return the ID of inserted document?为什么 mgo 不返回插入文档的 ID?
【发布时间】:2012-08-14 02:38:19
【问题描述】:

根据文档 (http://godoc.org/launchpad.net/mgo/v2),如果您使用 Upsert 方法,您可以获得“Upserted”文档的 ID。

还有一个不提供此功能的 Insert 方法。
这是为什么?如果我想执行插入而不是 Upsert 怎么办? (或者永远不会有任何正当理由想要这样做?我开始怀疑了。)

【问题讨论】:

    标签: mongodb go mgo


    【解决方案1】:

    您可以随时尝试使用 Upsert 函数来获取生成的 ID。

    db := service.ConnectDb()
    sessionCopy := db.Copy()
    defer sessionCopy.Close() // clean up
    
    collection := sessionCopy.DB(service.MongoDB.DTB).C(MessageCol.tbl)
    
    log.Println("before to write: ", msg)
    
    // Update record inserts and creates an ID if wasn't set (Returns created record with new Id)
    info, err := collection.Upsert(nil, msg)
    if err != nil {
        log.Println("Error write message upsert collection: ", err)
        return MessageMgo{}, err
    }
    
    if info.UpsertedId != nil {
        msg.Id = info.UpsertedId.(bson.ObjectId)
    }
    
    // gets room from mongo
    room, err := GetRoom(msg.Rid)
    if err != nil {
        return msg, err
    }
    
    // increments the msgcount and update it
    room.MsgCount = room.MsgCount + 1
    err = UpdateRoom(room)
    if err != nil {
        return msg, err
    }
    
    return msg, err
    

    这是我拥有的示例代码,并且工作正常.....

    【讨论】:

      【解决方案2】:

      这根本不应该发生,mgo 应该插入并返回 Id,因为如果我们从应用程序本身生成 ObjectId,如果应用程序重新启动,Object Id 生成器将从头开始生成相同的 ID一次又一次,从而更新数据库中的现有记录。

      这是错误的,MGO 应该依赖数据库生成这些 ID 并更新对象或立即返回插入对象的 objectId,就像绑定到 MongoDB 的其他语言在 Python 或 Java 中所做的那样。

      【讨论】:

      • 如果使用bson.NewObjectId() 而不是bson.NewObjectIdWithTime(time.Now()),那么重启应用程序的问题就不是问题了,对吧?
      • 这似乎不太可能阅读 ObjectID 文档,因为生成 ObjectID 的方法包括时间戳和 PID。如果您碰巧获得了示例 PID 并重置了系统时钟,那么您可能会遇到 ObjectID 冲突,否则您就可以了。 docs.mongodb.com/manual/reference/method/ObjectId
      【解决方案3】:

      您使用bson.NewObjectId() 生成要插入的ID。

      这是插入新文档的方式:

      i := bson.NewObjectId()
      c.Insert(bson.M{"_id": i, "foo": "bar"})
      

      由于您在发出 Upsert 时不知道是要插入还是更新,所以生成一个 ID 只是在查询后立即删除它是多余的(以防发生更新)。这就是它在数据库端生成并在适用时返回给您的原因。

      【讨论】:

      • 如何用我已经创建的结构替换 "foo":"bar"?
      • "如果重新启动应用程序,对象 ID 生成器将从头开始,一次又一次地生成相同的 ID,从而更新数据库中的现有记录。"这发布在第二个答案上,非常重要,并且没有在答案中提及。我认为您应该编辑答案,以便将来为人们添加此信息。
      • @cjf93 这不是真的(还有吗?)。如果您查看 bson.ObjectId 的实现,您会发现它考虑了当前时间。这也在这里解释:github.com/go-mgo/mgo/issues/392
      • @acidic 可能:i := bson.NewObjectId() c.Insert(bson.M{"_id": i}, yourStruct)
      • 您说“适用时”。根据我的经验,如果记录已经存在并已更新,则返回 null ;只有在创建记录时,upsertedId 才真正具有值。不是我所期望的,也不是文档所说的。
      猜你喜欢
      • 2018-07-25
      • 1970-01-01
      • 2012-09-12
      • 2016-01-07
      • 1970-01-01
      • 2017-02-10
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多