Skip to content
鼓励作者:欢迎打赏犒劳

bson几个类型的区别

🧩 一、基本概念

BSON(Binary JSON)是 MongoDB 使用的数据格式,类似于 JSON,但支持更多数据类型(如 ObjectId、Date 等)。

Go 驱动提供了几个类型来表示 BSON 结构:

类型全称含义是否有序
bson.MMapmap[string]interface{}❌ 无序(Go 的 map 无序)
bson.DDocument[]bson.E,有序的键值对列表✅ 有序
bson.EElement单个键值对 {Key: "name", Value: "Alice"}-

📌 二、详细说明

1. bson.E:单个键值对(Element)

go
bson.E{Key: "name", Value: "Alice"}
  • 表示一个 BSON 元素(键值对)。
  • bson.D 的基本组成单位。

用途:主要用于构建 bson.D,不单独使用。


2. bson.D:有序文档(Ordered Document)

go
bson.D{
    {Key: "name", Value: "Alice"},
    {Key: "age", Value: 30},
    {Key: "city", Value: "Beijing"},
}
  • 是一个 有序的键值对切片[]bson.E)。
  • 字段顺序会被保留。

使用场景

  • 聚合管道($group$sort 等阶段顺序很重要)
  • 需要保证字段顺序的场景(如某些索引创建、某些聚合操作)
  • 当你希望明确控制字段顺序时

📌 例子:聚合管道必须用 bson.Dbson.M,但推荐 bson.D 保证顺序

go
pipeline := []bson.M{
    {"$match": bson.D{{"status", "A"}, {"date", bson.D{{"$gte", "2024-01-01"}}}}},
    {"$group": bson.D{{"_id", "$cust_id"}, {"total", bson.D{{"$sum", "$amount"}}}}},
}

⚠️ 注意:虽然 bson.M 也可以用,但由于 map 无序,某些复杂聚合可能出错。


3. bson.M:无序映射(Map)

go
bson.M{
    "name": "Alice",
    "age":  30,
    "city": "Beijing",
}
  • map[string]interface{} 的别名。
  • 字段顺序不保证(Go 的 map 遍历顺序是随机的)。

使用场景

  • 一般查询条件(find, update, delete
  • 插入文档(字段顺序不重要)
  • 简单的聚合阶段(如 $match
  • 大多数日常操作

📌 例子:查询条件

go
filter := bson.M{
    "status": "active",
    "age":    bson.M{"$gt": 18},
    "tags":   bson.M{"$in": []string{"go", "mongodb"}},
}
collection.Find(ctx, filter)

🆚 三、bson.D vs bson.M 对比

特性bson.Dbson.M
是否有序✅ 是❌ 否
写法是否繁琐⚠️ 稍微繁琐(要写 Key: Value:✅ 简洁(像 JSON)
适用场景聚合管道、需要顺序的结构查询、插入、更新等普通操作
性能稍慢(slice 操作)稍快(map 查找)
可读性一般

✅ 四、使用建议(最佳实践)

场景推荐类型
查询条件(filterbson.M
更新操作(updatebson.M
插入文档bson.M
聚合管道(pipelinebson.D(推荐)或 bson.M(简单场景)
需要字段顺序的结构bson.D
构造嵌套条件(如 $and, $orbson.M 更方便

🎯 五、实际例子对比

1. 查询:查找 age > 25 且 status = "A"

go
// ✅ 推荐:用 bson.M
filter := bson.M{
    "age":    bson.M{"$gt": 25},
    "status": "A",
}

2. 聚合:按 name 分组,求 count

go
// ✅ 推荐:用 bson.D 保证顺序清晰
pipeline := []bson.D{
    {
        {Key: "$group", Value: bson.D{
            {Key: "_id", Value: "$name"},
            {Key: "count", Value: bson.D{{Key: "$sum", Value: 1}}},
        }},
    },
}

// 也可以用 bson.M(但顺序不保证)
pipeline := []bson.M{
    {
        "$group": bson.M{
            "_id":   "$name",
            "count": bson.M{"$sum": 1},
        },
    },
}

“bson.M 不保证顺序” 指的是 BSON 文档内部字段的排列顺序不固定,而不是聚合阶段的执行顺序。所以没一点影响!!!!!

🔔 虽然 bson.M 在这个例子中也能工作,但为了可读性和一致性,聚合推荐用 bson.D


✅ 总结

类型含义何时使用
bson.E{Key: "k", Value: v}单个键值对构成 bson.D 的元素
bson.D{bson.E,bson.E}有序文档聚合管道、需要顺序的结构
bson.M{"a": 1, "b": 2}无序映射查询、插入、更新等通用操作

🔧 一句话口诀

  • 日常操作用 bson.M,简单快捷;
  • 聚合管道用 bson.D,顺序安全。

如有转载或 CV 的请标注本站原文地址