
bson几个类型的区别
🧩 一、基本概念
BSON(Binary JSON)是 MongoDB 使用的数据格式,类似于 JSON,但支持更多数据类型(如 ObjectId、Date 等)。
Go 驱动提供了几个类型来表示 BSON 结构:
| 类型 | 全称 | 含义 | 是否有序 |
|---|---|---|---|
bson.M | Map | map[string]interface{} | ❌ 无序(Go 的 map 无序) |
bson.D | Document | []bson.E,有序的键值对列表 | ✅ 有序 |
bson.E | Element | 单个键值对 {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.D 或 bson.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.D | bson.M |
|---|---|---|
| 是否有序 | ✅ 是 | ❌ 否 |
| 写法是否繁琐 | ⚠️ 稍微繁琐(要写 Key: Value:) | ✅ 简洁(像 JSON) |
| 适用场景 | 聚合管道、需要顺序的结构 | 查询、插入、更新等普通操作 |
| 性能 | 稍慢(slice 操作) | 稍快(map 查找) |
| 可读性 | 一般 | 好 |
✅ 四、使用建议(最佳实践)
| 场景 | 推荐类型 |
|---|---|
查询条件(filter) | ✅ bson.M |
更新操作(update) | ✅ bson.M |
| 插入文档 | ✅ bson.M |
聚合管道(pipeline) | ✅ bson.D(推荐)或 bson.M(简单场景) |
| 需要字段顺序的结构 | ✅ bson.D |
构造嵌套条件(如 $and, $or) | ✅ bson.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,顺序安全。

