在mongodb-go-driver中,如何将BSON编组/解组为结构体?

15

我是mongodb-go-driver的新手,但我遇到了问题。

cursor, e := collection.Find(context.Background(), bson.NewDocument(bson.EC.String("name", id)))

for cursor.Next(context.Background()) {

    e := bson.NewDocument()
    cursor.Decode(e)

    b, _ := e.MarshalBSON()
    err := bson.Unmarshal(b, m[id])
}

当查看m[id]的内容时,它没有任何内容 - 全部为null。

我的映射表是这样的: m map[string]Language

而Language的定义如下:

type Language struct {
    ID         string   `json:"id" bson:"_id"`                   // is this wrong?
    Name       string   `json:"name" bson:"name"`
    Vowels     []string `json:"vowels" bson:"vowels"`
    Consonants []string `json:"consonants" bson:"consonants"`
}

我做错了什么?

我正在使用这个例子学习: https://github.com/mongodb/mongo-go-driver/blob/master/examples/documentation_examples/examples.go


cursor.Decode(e)这一行也返回了错误。请将其结果添加到您的问题中。 - CallMeLoki
不,如果我打印e,我会看到来自MongoDB的有效BSON数据。 - iam thadiyan
1
如果函数Decode()也返回错误,请打印出错误信息,如果它不是'nil'。 - CallMeLoki
是的,你说得对。Decode(interface{}) errorDecode 的定义。 - iam thadiyan
4个回答

23

较新版本的 "github.com/mongodb/mongo-go-driver" 期望以如下方式定义对象 ID:

Newer "github.com/mongodb/mongo-go-driver" expects object IDs defined as
type Application struct {
    ID      *primitive.ObjectID `json:"ID" bson:"_id,omitempty"`
}

这将序列化为 JSON "ID":"5c362f3fa2533bad3b6cf6f0",以下是从插入结果获取 ID 的方法

if oid, ok := res.InsertedID.(primitive.ObjectID); ok {
    app.ID = &oid
}

转换自字符串

appID := "5c362f3fa2533bad3b6cf6f0"    
id, err := primitive.ObjectIDFromHex(appID)
if err != nil {
    return err
}
_, err = collection.DeleteOne(nil, bson.M{"_id": id})

转换为字符串

str_id := objId.Hex()

12
官方的MongoDB驱动程序使用objectid.ObjectID类型来表示MongoDB的ObjectId。该类型为: type ObjectID [12]byte 因此,您需要将结构体更改为:
type Language struct {
    ID         objectid.ObjectID   `json:"id" bson:"_id"`             
    Name       string   `json:"name" bson:"name"`
    Vowels     []string `json:"vowels" bson:"vowels"`
    Consonants []string `json:"consonants" bson:"consonants"`
}

我使用以下方法获得成功:

m := make(map[string]Language)
cursor, e := collection.Find(context.Background(), bson.NewDocument(bson.EC.String("name", id)))

for cursor.Next(context.Background()) {

    l := Language{}
    err := cursor.Decode(&l)
    if err != nil {
        //handle err
    }
    m[id] = l // you need to handle this in a for loop or something... I'm assuming there is only one result per id
}

请问,您真的需要从 Mongodb 中检查 _id 吗? - tomriddle_1234
我注意到这个结构体描述了JSON和BSON序列化。感觉上,从数据库中“获取”的相同结构体然后以JSON的形式呈现给用户,没有经过任何转换,基本上是直接将数据结构暴露给客户端。作为Go的相对新手,我真的很好奇这是否被认为是良好的实践?这是Go的惯用法吗? - apostrophedottilde
我会让专家来回答“这是否是惯用的Go语言?”问题。您可以始终使用Field int json:“ - ”来避免将字段发送到客户端。 - Farhad Farahi

8

更新: 最近进行了新更改,现在必须更改为:

import "github.com/mongodb/mongo-go-driver/bson/primitive"

type Language struct {
    ID         primitive.ObjectID `bson:"_id,omitempty"` // omitempty to protect against zeroed _id insertion         
    Name       string   `json:"name" bson:"name"`
    Vowels     []string `json:"vowels" bson:"vowels"`
    Consonants []string `json:"consonants" bson:"consonants"`
}

并取出该ID的值:

log.Println("lang id:", objLang.ID)
...

这个可行,但它将JSON序列化为"ID":{"Type":7,"Value":"XDYvP6JTO607bPbw"} - Alexey Podlasov

2
我得到了 "无法将objectID解码为数组" 的错误信息,所以我改成了 ID interface{} `bson:"_id,omitempty"`,没有出现任何问题。翻译成中文就是:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接