我正在尝试在MongoDB的_id
字段中使用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
}
答案 0 :(得分:1)
uuid.UUID
是引擎盖下的[16]byte
。
但是,这种类型也实现了encoding.TextMarshaler
接口,我希望mongo能够使用它(与json
包相同)。
我相信解决方案是创建自己的类型,该类型嵌入uuid.UUID
类型,并提供bson.Marshaler
interface的自定义实现。
答案 1 :(得分:0)
我作为解决方案来到了以下实施方案:
type mongoUUID struct {
uuid.UUID
}
func (mu mongoUUID) MarshalBSONValue() (bsontype.Type, []byte, error) {
return bsontype.Binary, bsoncore.AppendBinary(nil, 4, mu.UUID[:]), nil
}
func (mu *mongoUUID) UnmarshalBSONValue(t bsontype.Type, raw []byte) error {
if t != bsontype.Binary {
return fmt.Errorf("invalid format on unmarshal bson value")
}
_, data, _, ok := bsoncore.ReadBinary(raw)
if !ok {
return fmt.Errorf("not enough bytes to unmarshal bson value")
}
copy(mu.UUID[:], data)
return nil
}