【问题标题】:Mongo-go-driver get objectID from insert resultMongo-go-driver 从插入结果中获取 objectID
【发布时间】:2018-09-30 16:12:58
【问题描述】:

使用InsertOne 创建新文档后,当我返回结果时,我得到的是一个数字数组,而不是ObjectID。在数据库中,id 生成良好。

type User struct {
  ID       string
  Email    string
  Username string
  Password string
}

var db = ...

// UserStore creates user
func UserStore(c echo.Context) (err error) {

  coll := db.Collection("users")

  u := new(User)
  if err = c.Bind(u); err != nil {
    return c.JSON(http.StatusInternalServerError, err)
  }

  result, err := coll.InsertOne(
    context.Background(),
    bson.NewDocument(
        bson.EC.String("email", u.Email),
        bson.EC.String("username", u.Username),
        bson.EC.String("password", u.Password),
    ),
  )
  if err != nil {
    return c.JSON(http.StatusInternalServerError, err)
  }

  return c.JSON(http.StatusCreated, result)
}

这会返回类似InsertedID: [90, 217, 85, 109, 184, 249, 162, 204, 249, 103, 214, 121] 的内容,而不是普通的ObjectID。如何从新插入的文档中返回实际的ObjectID

【问题讨论】:

    标签: json mongodb http go mongo-go


    【解决方案1】:

    一个成功的Collection.InsertOne()会返回一个mongo.InsertOneResult类型的结果,这是一个包装了新插入文档ID的结构体:

    type InsertOneResult struct {
        // The identifier that was inserted.
        InsertedID interface{}
    }
    

    官方的 MongoDB Go 驱动使用 primitive.ObjectID 类型来表示 MongoDB ObjectIds。这种类型是一个简单的字节数组:

    type ObjectID [12]byte
    

    要访问此类型,您需要导入 primitive package

    import "go.mongodb.org/mongo-driver/bson/primitive"
    

    InsertOneResult.InsertedID 将持有动态类型 primitive.ObjectIDprimitive.ObjectID 类型没有定义自定义的 JSON 封送方法(没有实现json.Marshaler),这意味着当结果转换为 JSON 时,将使用默认的封送规则,对于字节数组(不是切片)是您所看到的:ObjectID 字节的十进制表示。

    您不应将 InsertOneResult 类型的值转换为 JSON,因为它(或者更确切地说是 primitive.ObjectID 本身)不是“JSON 友好的”(至少在当前版本中不是)。

    改为创建/包装您自己的类型,您可以在其中定义您希望结果在 JSON 中的样子,例如:

    if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
        return c.JSON(http.StatusCreated, map[string]interface{}{
            "id": oid.String(),
        })
    } else {
        // Not objectid.ObjectID, do what you want
    }
    

    上面的代码会产生这样的 JSON 响应:

    {"id":"ObjectID(\"5ad9a913478c26d220afb681\")"}
    

    或者如果您只想要十六进制表示:

    if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
        return c.JSON(http.StatusCreated, map[string]interface{}{
            "id": oid.Hex(),
        })
    }
    

    应该是:

    {"id":"5ad9a913478c26d220afb681"}
    

    【讨论】:

    • 很好的答案!但是现在情况发生了变化,您需要使用primitive.ObjectID而不是使用objectid.ObjectID
    • @AdamD 是的,你是对的。答案是在 primitive.ObjectID 之前创建的。
    • 答案是正确的,要获得objectid,您可以使用原始用户。primitive.ObjectIDFromHex("your generated hex") 将返回ibjectid,而不是十六进制字符串表示形式。
    • golang 新手。当你说result.InsertedID.(primitive.ObjectID) 你在这里做什么时,我不太明白。 InsertedID 是空接口,所以...
    • @Tannu 是类型断言,见Is this casting in golang?
    猜你喜欢
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 2022-12-20
    • 2019-05-21
    相关资源
    最近更新 更多