【问题标题】:In mongodb-go-driver, how to marshal/unmarshal BSON in to a struct在 mongodb-go-driver 中,如何将 BSON 编组/解组到结构中
【发布时间】:2019-01-05 17:24:47
【问题描述】:

我是 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] 的内容时,它没有内容 - 全部为空。

我的地图是这样的: m map[string]语言

语言定义如下:

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

【问题讨论】:

  • line cursor.Decode(e) 也返回错误。将其结果添加到您的问题中
  • 没有。如果我打印 e 我会看到来自 MongoDB 的有效 BSON 数据
  • 我的意思是函数Decode() 也返回错误。如果不是 nil,则在此处打印错误
  • 是的,你是对的。 Decode(interface{}) errorDecode的定义

标签: mongodb go


【解决方案1】:

较新的“github.com/mongodb/mongo-go-driver”期望对象 ID 定义为

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()

【讨论】:

    【解决方案2】:

    官方的 MongoDB 驱动程序使用 objectid.ObjectID 类型作为 MongoDB ObjectIds。这种类型是:

    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 吗?
    • 我注意到这个结构同时描述了 JSON 和 BSON 序列化。这感觉就像从数据库中“获取”的相同结构然后以 JSON 的形式呈现给用户,无需转换,本质上将您的数据结构直接暴露给客户端。作为 Go 的新手,我真的很好奇这是否真的被认为是好的做法?这是惯用的go吗?
    • 我会留下“这是惯用的吗?”,让专家来回答。您始终可以使用Field int json:"-" 来避免向客户端发送字段
    【解决方案3】:

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

    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"}
    【解决方案4】:

    我得到了

    cannot decode objectID into an array

    所以我改成

    ID interface{} `bson:"_id,omitempty"`

    没有任何问题

    【讨论】:

      猜你喜欢
      • 2019-04-06
      • 1970-01-01
      • 2020-09-26
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多