Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

With MongoDB, how to convert between types of decimal128 and decimal.Decimal? #3734

Open
shanweie opened this issue Nov 21, 2023 · 9 comments
Labels
area/orm Categorizes issue or PR as related to orm. stale

Comments

@shanweie
Copy link

registry := bson.NewRegistry()
registry.RegisterTypeEncoder(reflect.TypeOf(decimal.Decimal{}), &mongo.MongoDecimal{})

conn := mon.MustNewModel(url, db, collection, opts)

怎么设置opts,使用registry自动互转

@POABOB
Copy link
Contributor

POABOB commented Nov 21, 2023

Mongo Options 的原始碼在這裡:https://github.com/zeromicro/go-zero/blob/master/core/stores/mon/options.go

import (
    "reflect"

    "go.mongodb.org/mongo-driver/bson"
    // 引入 go mongo-driver
    mopt "go.mongodb.org/mongo-driver/mongo/options"
    "github.com/zeromicro/go-zero/core/stores/mon"
)

registry := bson.NewRegistry()
registry.RegisterTypeEncoder(reflect.TypeOf(decimal.Decimal{}), &mongo.MongoDecimal{})
// 使用 SetRegistry 註冊
opts := mon.Option(mopt.SetRegistry(registry))   // opts 的 type 會是 Option,這是 go-zero 自己訂的 type
conn := mon.MustNewModel(url, db, collection, opts)

資料來源:

  1. https://blog.csdn.net/u013053623/article/details/129023275
  2. https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo/options#ClientOptions.SetRegistry
  3. https://jira.mongodb.org/browse/GODRIVER-2886

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


The source code of Mongo Options is here: https://github.com/zeromicro/go-zero/blob/master/core/stores/mon/options.go

import (
    "reflect"

    "go.mongodb.org/mongo-driver/bson"
    //Introduce go mongo-driver
    mopt "go.mongodb.org/mongo-driver/mongo/options"
    "github.com/zeromicro/go-zero/core/stores/mon"
)

registry := bson.NewRegistry()
registry.RegisterTypeEncoder(reflect.TypeOf(decimal.Decimal{}), &mongo.MongoDecimal{})
//Register using SetRegistry
opts := mon.Option(mopt.SetRegistry(registry)) // The type of opts will be Option, which is the type set by go-zero itself
conn := mon.MustNewModel(url, db, collection, opts)

source:

  1. https://blog.csdn.net/u013053623/article/details/129023275
  2. https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo/options#ClientOptions.SetRegistry
  3. https://jira.mongodb.org/browse/GODRIVER-2886

@shanweie
Copy link
Author

mongo-driver v1.12.1,里面没有这个mopt.SetRegistry(registry)这个方法

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


mongo-driver v1.12.1, there is no mopt.SetRegistry(registry) method in it

@POABOB
Copy link
Contributor

POABOB commented Nov 22, 2023

@kevwan Hey! I have a problem with transfering mongo decimal128 to decimal.Decimal.
There doesn't seem to be a function that can set up the mongo configuration.

Could I make a pull request to add the setRegistry function for the mongo client on https://github.com/zeromicro/go-zero/blob/master/core/stores/mon/options.go?

core/stores/mon/options.go

// WithRegistry the mon client can transfer mongo types to custom types.
func WithRegistry(registry *bsoncodec.Registry) Option {
	return func(opts *options) {
		opts.SetRegistry(registry)
	}
}

To use this function, follow the example below:

registry := bson.NewRegistry()
registry.RegisterTypeEncoder(reflect.TypeOf(decimal.Decimal{}), MongoDecimal{})
// this code
opts := mon.WithRegistry(registry)
conn := mon.MustNewModel(url, db, collection, opts)

@shanweie
Copy link
Author

试过了还是不行,错误为: cannot decode 128-bit decimal into a decimal.Decimal

registry := bson.NewRegistry()
registry.RegisterTypeEncoder(reflect.TypeOf(decimal.Decimal{}), &mongo.MongoDecimal{})
conn := mon.MustNewModel(url, db, collection, mongo.WithRegistry(registry))

func WithRegistry(registry *bsoncodec.Registry) mon.Option {
return func(opts *mopt.ClientOptions) {
opts.SetRegistry(registry)
}
}

@shanweie
Copy link
Author

mongo.mongoDecimal的代码为:
`
package mongo

import (
"fmt"
"github.com/shopspring/decimal"
"github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/bson/bsoncodec"
"go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/bson/primitive"
mopt "go.mongodb.org/mongo-driver/mongo/options"
"reflect"
)

// MongoDecimal是一个允许十进制编码的ValueCodec,Decimal128到decimal.Decimal
type MongoDecimal struct{}

var _ bsoncodec.ValueCodec = &MongoDecimal{}

func WithRegistry(registry *bsoncodec.Registry) mon.Option {
return func(opts *mopt.ClientOptions) {
opts.SetRegistry(registry)
}
}

func (dc *MongoDecimal) EncodeValue(ect bsoncodec.EncodeContext, w bsonrw.ValueWriter, value reflect.Value) error {
// 使用反射转换,值改为 decimal.Decimal.
dec, ok := value.Interface().(decimal.Decimal)
if !ok {
return fmt.Errorf("value %v to encode is not of type decimal.Decimal", value)
}

// Convert decimal.Decimal to primitive.Decimal128.
primDec, err := primitive.ParseDecimal128(dec.String())
if err != nil {
	return fmt.Errorf("error converting decimal.Decimal %v to primitive.Decimal128: %v", dec, err)
}
return w.WriteDecimal128(primDec)

}

func (dc *MongoDecimal) DecodeValue(ect bsoncodec.DecodeContext, r bsonrw.ValueReader, value reflect.Value) error {
primDec, err := r.ReadDecimal128()
if err != nil {
return fmt.Errorf("error reading primitive.Decimal128 from ValueReader: %v", err)
}

// 将primitive.Decimal128转变为Golang的decimal.Decimal.
dec, err := decimal.NewFromString(primDec.String())
if err != nil {
	return fmt.Errorf("error converting primitive.Decimal128 %v to decimal.Decimal: %v", primDec, err)
}

// 设置值为 decimal.Decimal类型数据
value.Set(reflect.ValueOf(dec))
return nil

}

`

@POABOB
Copy link
Contributor

POABOB commented Nov 22, 2023

@shanweie
I found a problem that you only use registry.RegisterTypeEncoder, but there is no registry.RegisterTypeEncoder.

截圖 2023-11-22 下午9 15 36

You have to use BOTH so that you can transfering the Decimal to MongoDecimal.

截圖 2023-11-22 下午9 15 09

@kevwan kevwan changed the title 关于连接MongoDB,MongoDB的decimal128怎么和decimal.Decimal互转 With MongoDB, how to convert between types of decimal128 and decimal.Decimal? Nov 23, 2023
@kevwan kevwan added the area/orm Categorizes issue or PR as related to orm. label Nov 23, 2023
Copy link

This issue is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale label Nov 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/orm Categorizes issue or PR as related to orm. stale
Projects
None yet
Development

No branches or pull requests

4 participants