MongoDB Go驱动程序会自动将"uint64"转换为bson类型吗?返回溢出错误



如标题所示,我有一个结构定义了一个uint64字段,但当我将其值设置为math.MaxUint64.时返回错误

这是我的代码:

type MyDoc struct {
Number    uint64 `bson:"_id"`
Timestamp int64  `bson:"time"`
}
// I just want to know whether uint64 overflows or not.
func main() {
mydoc := &MyDoc{
Number: math.MaxUint64,
Timestamp: time.Now().UnixNano(),
}
v, err := bson.Marshal(mydoc)
if err != nil {
panic(err)
}
fmt.Println(v)
}

执行后,错误如下:

panic: 18446744073709551615 overflows int64 [recovered]
panic: 18446744073709551615 overflows int64

显然,uint64类型的数据被处理为

int64那么,如何在MongoDB中存储uint64数据而不溢出呢??我不能使用字符串类型,因为我需要比较数字的大小,以便对文档进行排序。

我使用的是MongoDB官方Go驱动程序。

提前感谢!

您可以使用自定义编码器和解码器。

有了你提供的代码,你可以做这样的事情:


// define a custom type so you can register custom encoder/decoder for it
type MyNumber uint64
type MyDoc struct {
Number    MyNumber `bson:"_id"`
Timestamp int64    `bson:"time"`
}
// create a custom registry builder
rb := bsoncodec.NewRegistryBuilder()
// register default codecs and encoders/decoders
var primitiveCodecs bson.PrimitiveCodecs
bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)
bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb)
primitiveCodecs.RegisterPrimitiveCodecs(rb)
// register custom encoder/decoder
myNumberType := reflect.TypeOf(MyNumber(0))
rb.RegisterTypeEncoder(
myNumberType,
bsoncodec.ValueEncoderFunc(func(_ bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
if !val.IsValid() || val.Type() != myNumberType {
return bsoncodec.ValueEncoderError{
Name:     "MyNumberEncodeValue",
Types:    []reflect.Type{myNumberType},
Received: val,
}
}
// IMPORTANT STEP: cast uint64 to int64 so it can be stored in mongo
vw.WriteInt64(int64(val.Uint()))
return nil
}),
)
rb.RegisterTypeDecoder(
myNumberType,
bsoncodec.ValueDecoderFunc(func(_ bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
// IMPORTANT STEP: read sore value in mongo as int64
read, err := vr.ReadInt64()
if err != nil {
return err
}
// IMPORTANT STEP: cast back to uint64
val.SetUint(uint64(read))
return nil
}),
)
// build the registry
reg := rb.Build()

要使用此自定义注册表,您可以在创建集合时将其作为选项传递

collection := client.Database("testing").Collection("myCollection", &options.CollectionOptions{
Registry: reg,
})

相关内容

最新更新