You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中正确检索MongoDB中的嵌套对象数组?

解决Golang Mongo驱动解码内容字段时的格式异常问题

你在使用Golang Fiber + Mongo驱动开发博客系统时,定义的Post结构体中Content字段为[]interface{},存入MongoDB的是正常的对象数组,但查询解码后Content变成了嵌套数组加Key/Value键值对的格式——这是因为Mongo驱动对无明确类型的interface{}数组解码时,会将每个对象解析为bson.D(即[]bson.E键值对数组),后续JSON序列化时就呈现出异常格式。

解决方案1:定义明确的内容元素结构体

最可靠的方式是为Content数组中的对象定义具体结构体,让Mongo驱动能精准解析类型:

// 定义Content数组的元素结构体
type ContentItem struct {
    Data string `json:"data" bson:"data"`
}

// 修改Post结构体的Content字段类型
type Post struct {
    ID          primitive.ObjectID `json:"_id" bson:"_id,omitempty"`
    Title       *string            `json:"title" bson:"title"`
    Slug        *string            `json:"slug" bson:"slug"`
    Content     []ContentItem      `json:"content" bson:"content,omitempty"` // 替换为明确的结构体数组
    CreatedAt   time.Time          `json:"created_at" bson:"created_at"`
    UpdatedAt   time.Time          `json:"updated_at" bson:"updated_at"`
    PublishedAt *time.Time         `json:"published_at" bson:"published_at"`
}

修改后,驱动会直接将Mongo中的对象数组解码为[]ContentItem,序列化JSON时就能得到和存储时一致的格式。

解决方案2:使用[]bson.M替代[]interface{}

如果无法提前确定Content元素的结构,需要保留泛型特性,可以将Content字段类型改为[]bson.M(Mongo驱动内置的map类型):

type Post struct {
    ID          primitive.ObjectID `json:"_id" bson:"_id,omitempty"`
    Title       *string            `json:"title" bson:"title"`
    Slug        *string            `json:"slug" bson:"slug"`
    Content     []bson.M           `json:"content" bson:"content,omitempty"` // 替换为[]bson.M
    CreatedAt   time.Time          `json:"created_at" bson:"created_at"`
    UpdatedAt   time.Time          `json:"updated_at" bson:"updated_at"`
    PublishedAt *time.Time         `json:"published_at" bson:"published_at"`
}

bson.M本质是map[string]interface{},驱动解码时会将Mongo中的对象解析为该类型,后续JSON序列化时会正常转换为对象数组,不会出现Key/Value的嵌套格式。

验证修改

修改结构体后,原查询方法无需额外调整,直接调用FindOne解码即可得到正确的Content格式:

func GetPostBySlug(slug string) (Post, error) {
    post := Post{}
    filter := bson.M{"slug": slug}

    database, err := Database.GetMongoDatabase()
    if err != nil {
        return post, err
    }

    collection := database.Collection(model_name)
    err = collection.FindOne(ctx, filter).Decode(&post)
    return post, err
}

此时返回的Content字段会和MongoDB中存储的格式一致,为正常的对象数组。

内容的提问来源于stack exchange,提问作者Andrew Rusinas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:24:23