为了账号安全,请及时绑定邮箱和手机立即绑定

使用 MongoDB 解码将字符串从 MongoDB 转换为 int

使用 MongoDB 解码将字符串从 MongoDB 转换为 int

Go
MMTTMM 2022-05-18 10:21:35
当我尝试将我的集合中的字符串类型的属性解码为我的结构中的 int 类型的属性时,我在使用 Go 的 mongodb 驱动程序时遇到了一些问题。我有一个集合,该集合的属性应该是 int 类型,该属性被编辑单个文档的人转换为 string 类型。由于所有文档都具有该属性作为 int 除了那个,我收到一个错误“无法将字符串解码为整数类型”。我想出了一种方法来做到这一点,但这不是“应该”做的事情。我在 Go 的 mongodb 驱动程序中修改了 default_value_decoders.go 中的 IntDecodeValue 函数。下面是我添加的。    case bsontype.String:    s, err := vr.ReadString()    if err != nil {        return err    }    i32, err := strconv.Atoi(s)    if err != nil {        return err    }    i64 = int64(i32)我知道当我更新驱动程序时这将被覆盖,但我一直在努力思考如何处理这种情况。我知道最好的解决方案是不允许直接编辑文档,但要考虑这种情况。
查看完整描述

2 回答

?
喵喵时光机

TA贡献1846条经验 获得超7个赞

您可以通过自定义 BSON 解码器执行此操作。文档中的一个示例是https://pkg.go.dev/go.mongodb.org/mongo-driver/bson/bsoncodec?tab=doc#example-Registry-CustomDecoder。对于您的特定用例,以下应该有效:


func intDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) {


// Same logic as DefaultValueDecoders.IntDecodeValue

// In the switch statement for vr.Type, you can add a case for bsontype.String


}

要注册此解码器以便在执行 CRUD 操作时使用它,您可以使用SetRegistry客户端选项:


decoder := bsoncodec.ValueDecoderFunc(intDecodeValue)

registry := bson.NewRegistryBuilder().RegisterDefaultDecoder(reflect.Int, decoder).Build()


clientOpts := options.Client().SetRegistry(registry)

client, err := mongo.Connect(context.TODO(), clientOpts)

请注意,由于 Go 区分不同的整数类型(例如 int8/int16/int32/int64),因此您需要调用RegisterDefaultDecoder为您可能在结构中看到的每种整数类型注册自定义解码器,类似于在RegisterDefaultDecoders中的函数default_value_decoders.go。


查看完整回答
反对 回复 2022-05-18
?
慕运维8079593

TA贡献1876条经验 获得超5个赞

这是在处理字符串和 int 字段的结构中将该字符串字段解码为 int 的可能解决方案。


我在这个例子中使用了以下结构:


type Obj struct {

    Field1   string `bson:"field1"`

    IntField int    `bson:"intField"`

}

并插入以下文档(注意第二个文档的字符串字段为"intField": "2"):


db.s2i.insertOne({"field1": "value", "intField": 3})

db.s2i.insertOne({"field1": "value2", "intField": "2"})

使用聚合框架中的$toInt运算符,如下所示:


pipeline := []bson.M{bson.M{"$match": bson.M{}}, bson.M{"$project": bson.M{"field1": 1, "intField": bson.M{"$toInt": "$intField"}}}}


cur, err := client.Database("stack").Collection("s2i").Aggregate(context.TODO(), pipeline)


for cur.Next(context.TODO()) {

    var res *Obj

    err = cur.Decode(&res)


    fmt.Println(res, err)

    fmt.Println("Value of res.IntField:")

    fmt.Println(res.IntField)

    fmt.Println("Type of res.IntField:")

    fmt.Println(reflect.TypeOf(res.IntField))

}

返回以下文档,其中“2”解码为 int:


&{value 3} <nil>

Value of res.IntField:

3

Type of res.IntField:

int

&{value2 2} <nil>

Value of res.IntField:

2

Type of res.IntField:

int


查看完整回答
反对 回复 2022-05-18
  • 2 回答
  • 0 关注
  • 162 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信