首页 > 解决方案 > UUID as _id 错误 - 不能为 _id 使用数组

问题描述

我正在尝试_id在 MongoDB 中为我的字段使用 UUID。

我有一个包装结构来保存我的记录,如下所示:

type mongoWrapper struct {
    ID      uuid.UUID       `bson:"_id" json:"_id"`
    Payment storage.Payment `bson:"payment" json:"payment"`
}

这是我在 MongoDB 驱动程序包中围绕 InsertOne 函数的代码:

func (s *Storage) Create(newPayment storage.Payment) (uuid.UUID, error) {
    mongoInsert := wrap(newPayment)
    c := s.client.Database(thisDatabase).Collection(thisCollection)

    insertResult, errInsert := c.InsertOne(context.TODO(), mongoInsert)
    if errInsert != nil {
        return uuid.Nil, errInsert
    }

    fmt.Println("Inserted a single document: ", insertResult.InsertedID)

    return mongoInsert.ID, nil
}

这是我的 wrap() 函数,它包装了支付记录数据,并采用可选的 UUID 参数或相应地生成自己的参数:

func wrap(p storage.Payment, i ...uuid.UUID) *mongoWrapper {
    mw := &mongoWrapper{ID: uuid.Nil, Payment: p}

    if len(i) > 0 {
        mw.ID = i[0]
        return mw
    }

    newID, errID := uuid.NewV4()
    if errID != nil {
        log.Fatal(errID)
    }

    mw.ID = newID

    return mw
}

当我的一项测试调用 Create() 时,它返回以下错误:

storage_test.go:38: err: multiple write errors: [{write errors: [{can't use an array for _id}]}, {<nil>}]

我正在为我的 UUID 和 MongoDB 驱动程序使用以下软件包:

import(
    uuid "github.com/satori/go.uuid"

    "go.mongodb.org/mongo-driver/mongo"
)

我不清楚问题究竟出在哪里。

我是否需要在 UUID 周围进行一些额外的管道才能正确处理它?

编辑:我做了更多更改,但 UUID 仍然作为数组出现:

type mongoWrapper struct {
    UUID    mongoUUID       `bson:"uuid" json:"uuid"`
    Payment storage.Payment `bson:"payment" json:"payment"`
}

type mongoUUID struct {
    uuid.UUID
}

func (mu *mongoUUID) MarshalBSON() ([]byte, error) {
    return []byte(mu.UUID.String()), nil
}

func (mu *mongoUUID) UnmarshalBSON(b []byte) error {
    mu.UUID = uuid.FromStringOrNil(string(b))
    return nil
}

标签: mongodbgouuid

解决方案


uuid.UUID是一个[16]byte在引擎盖下。

但是,这种类型也实现了encoding.TextMarshaler接口,我希望 mongo 能够兑现(与json包相同的方式)。

我相信解决方案是创建自己的类型,嵌入uuid.UUID类型,并提供bson.Marshaler接口的自定义实现。


推荐阅读