前言
在开发使用 MongoDB
的 Go
应用中,我们避免不了要编写 BSON
格式的数据。对于简单的 BSON
格式数据,我们可以轻松快捷地进行编写。而面对复杂的 BSON
格式数据,我们可能需要自己构建多层嵌套的文档,这不仅耗时而且容易出错,一次微小的遗漏或错误就可能导致无法获得预期的结果,增加了开发的难度和调试的时间。
在这种背景下,go-mongox
应运而生。go-mongox
是一个基于泛型的库,扩展了 MongoDB
的官方框架。它的功能如下所示:
- 泛型的
MongoDB
集合 - 文档的
CRUD
操作 - 聚合操作
- 内置基本的
Model
结构体,自动化更新默认的field
字段 - 支持
bson
数据的构建 - 支持结构体
tag
校验 - 内置
Hooks
- 支持插件化编程
本篇文章将对 bson 数据构建
这一模块进行详细介绍。
准备好了吗?准备一杯你最喜欢的咖啡或茶,随着本文一探究竟吧。
go-mongox 仓库地址:https://github.com/chenmingyong0423/go-mongox
安装
执行以下命令,在 Go
应用中安装 go-mongox
模块:
go get github.com/chenmingyong0423/go-mongox
构建器
go-mongox
设计了多种不同类型的 BSON
构建器和函数,为我们开发者在不同场景下构建 BSON
数据提供了强大的支持。无论是数据查询、更新,还是执行复杂的聚合操作,开发者都可以在 bsonx
、query
和 update
以及 aggregation
专门的包中找到合适的构建器或函数。这些BSON
构建器和函数不仅优化了代码的编写过程,还显著提高了开发效率,使得处理复杂的 BSON
数据变得既简单又高效。
查询语句构建 - query 包
query
包为构建 MongoDB
查询条件提供了便捷方法。它包括一系列函数和构建器,旨在简化查询条件的构建。对于复杂查询条件,构建器通过链式调用方式,提供了灵活的构建手段;对于简单需求,则可直接利用函数来快速构建查询条件。
简单构建
对于单一的 查询条件,我们直接使用函数进行构建。
// bson.D{bson.E{Key:"_id", Value:"12345678"}}
//{
// "_id": "12345678"
//}
query.Id("12345678")
// bson.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$in", Value:[]string{"陈明勇", "chenmingyong"}}}}}
// {
// "name": {
// "$in": ["陈明勇", "chenmingyong"]
// }
//}
query.In("name", "陈明勇", "chenmingyong")
// bson.D{bson.E{Key:"age", Value:bson.D{bson.E{Key:"$gte", Value:18}}}}
//{
// "age": {
// "$gte": 18
// }
//}
query.Gte("age", 18)
// bson.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$regex", Value:".*cmy.*"}, bson.E{Key:"$options", Value:"i"}}}}
//{
// "name": {
// "$regex": ".*cmy.*",
// "$options": "i"
// }
//}
query.RegexOptions("name", ".*cmy.*", "i")
根据对比可以发现,query
包提供的函数优化了代码的编写过程,提高了开发效率。
更多用法可前往官网文档 query 包 | go-mongox 进行查看。
复杂构建
对于较为复杂的 BSON
格式数据,我们需要使用构建器进行构建。
// bson.D{bson.E{Key:"age", Value:bson.D{bson.E{Key:"$gte", Value:18}, bson.E{Key:"$lte", Value:25}}}, bson.E{Key:"name", Value:bson.D{bson.E{Key:"$in", Value:[]interface {}{"陈明勇", "chenmingyong"}}}}}
//{
// "age": {
// "$gte": 18,
// "$lte": 25
// },
// "name": {
// "$in": ["陈明勇", "chenmingyong"]
// }
//}
query.BsonBuilder().Gte("age", 18).Lte("age", 25).In("name", "陈明勇", "chenmingyong").Build()
// bson.D{bson.E{Key:"lastLogin", Value:bson.D{bson.E{Key:"$gte", Value:time.Date(2024, time.March, 0, 0, 0, 0, 189625000, time.Local)}}}, bson.E{Key:"$or", Value:[]interface {}{bson.D{bson.E{Key:"status", Value:bson.D{bson.E{Key:"$eq", Value:"active"}}}}, bson.D{bson.E{Key:"loginAttempts", Value:bson.D{bson.E{Key:"$gte", Value:5}}}}}}}
//{
// "lastLogin": {
// "$gte": "2024-03-08T00:00:00.189Z"
// },
// "$or": [
// {
// "status": {
// "$eq": "active"
// }
// },
// {
// "loginAttempts": {
// "$gte": 5
// }
// }
// ]
//}
query.BsonBuilder().Gte("lastLogin", time.Now().Add(-30*24*time.Hour)).Or(
query.Eq("status", "active"),
query.Gte("loginAttempts", 5),
).Build()
// bson.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$eq", Value:"陈明勇"}}}, bson.E{Key:"hobbies", Value:bson.D{bson.E{Key:"$elemMatch", Value:primie.D{bson.E{Key:"name", Value:bson.D{bson.E{Key:"$eq", Value:"coding"}}}, bson.E{Key:"level", Value:bson.D{bson.E{Key:"$gte", Value:5}}}}}}}}
//{
// "name": {
// "$eq": "陈明勇"
// },
// "hobbies": {
// "$elemMatch": {
// "name": {
// "$eq": "coding"
// },
// "level": {
// "$gte": 5
// }
// }
// }
//}
query.BsonBuilder().
Eq("name", "陈明勇").
ElemMatch("hobbies", query.BsonBuilder().Eq("name", "coding").Gte("level", 5).Build()).
Build()
通过这些示例,我们可以看到构建器强大之处,通过链式调用的方式来构建复杂的查询语句。这种方式使得代码更加清晰易读,也便于维护和扩展。
更多用法可前往官网文档 query 包 | go-mongox 进行查看。
更新文档构建 - update 包
update
包为构建 MongoDB
更新文档提供了便捷方法。它包括一系列函数和构建器,旨在简化更新文档的构建。对于复杂的更新文档,构建器通过链式调用方式,提供了灵活的构建手段;对于简单需求,则可直接利用函数来快速构建更新文档。
简单构建
对于单一的更新文档,我们直接使用函数进行构建。
// bson.D{bson.E{Key:"$set", Value:bson.D{bson.E{Key:"name", Value:"陈明勇"}}}}
//{
// "$set": {
// "name": "陈明勇"
// }
//}
update.Set("name", "陈明勇")
// bson.D{bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"money", Value:"100000"}}}}
//{
// "$inc": {
// "money": 100000
// }
//}
update.Inc("money", "100000")
// bson.D{bson.E{Key:"$push", Value:bson.D{bson.E{Key:"tags", Value:"golang"}}}}
//{
// "$push": {
// "tags": "golang"
// }
//}
update.Push("tags", "golang")
更多用法可前往官网文档 update 包 | go-mongox 进行查看。
复杂构建
对于较为复杂的更新文档,我们需要使用构建器进行构建。
// bson.D{bson.E{Key:"$set", Value:bson.D{bson.E{Key:"name", Value:"陈明勇"}, bson.E{Key:"age", Value:18}}}}
//{
// "$set": {
// "name": "陈明勇",
// "age": 18
// }
//}
update.BsonBuilder().Set("name", "陈明勇").Set("age", 18).Build()
// bson.D{bson.E{Key:"$set", Value:bson.D{bson.E{Key:"update_at", Value:time.Date(2024, time.April, 7, 3, 13, 23, 958924000, time.Local)}}}, bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"view", Value:1}}}}
//{
// "$set": {
// "update_at": "2024-04-07T00:00:00.958Z"
// },
// "$inc": {
// "view": 1
// }
//}
update.BsonBuilder().Set("update_at", time.Now()).Inc("view", 1).Build()
// bson.D{bson.E{Key:"$push", Value:bson.D{bson.E{Key:"comments", Value:"新评论"}}}, bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"commentCount", Value:}}}
//{
// "$push": {
// "comments": "新评论"
// },
// "$inc": {
// "commentCount": 1
// }
//}
update.BsonBuilder().Push("comments", "新评论").Inc("commentCount", 11).Build()
更多用法可前往官网文档 update 包 | go-mongox 进行查看。
聚合管道阶段和表达式构建 - aggregation 包
aggregation
包提供了方便的方法来构建MongoDB
聚合管道(pipeline)结构。它包括多个函数和构建器,简化了管道构建过程。对于复杂场景,构建器支持链式调用,使得构建过程更加灵活;而对于基础需求,可以直接使用函数快速完成构建。
aggregation
包提供了两种构建器:
aggregation.StageBuilder
:用于轻松构建聚合管道的各个阶段(Pipeline Stages
),如$group
、$match
等。通过aggregation.StageBsonBuilder()
创建一个新的构建器实例,然后调用相应的方法来构建阶段。aggregation.Builder
:用于构建管道阶段内部使用的复杂表达式(Pipeline Expressions
),例如条件逻辑、数学运算等。通过aggregation.BsonBuilder()
创建一个新的构建器实例,然后调用相应的方法来构建表达式。
聚合管道阶段
聚合阶段构建器用于轻松构建聚合管道的各个阶段(Pipeline Stages
),如 $group
、$match
等。
通过 aggregation.StageBsonBuilder()
创建一个新的构建器实例,然后调用相应的方法来构建阶段。
type User struct {
mongox.Model `bson:"inline"`
Name string `bson:"name"`
Age int `bson:"age"`
}
// mongo.Pipeline{bson.D{bson.E{Key:"$group", Value:bson.D{bson.E{Key:"_id", Value:"$age"}, bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}}}}
//[
// {
// "$group": {
// "_id": "$age",
// "count": { "$sum": 1 },
// "names": { "$push": "$name" }
// }
// }
//]
aggregation.StageBsonBuilder().Group("$age",
aggregation.BsonBuilder().Sum("count", 1).Push("names", "$name").Build()...,
).Build()
// mongo.Pipeline{bson.D{bson.E{Key:"$addFields", Value:bson.D{bson.E{Key:"isAdult", Value:bson.D{bson.E{Key:"$gte", Value:[]interface {}{"$age", 18}}}}}}}, bson.D{bson.E{Key:"$replaceWith", Value:bson.D{bson.E{Key:"name", Value:"$name"}, bson.E{Key:"isAdult", Value:"$isAdult"}}}}}
//[
// {
// "$addFields": {
// "isAdult": {
// "$gte": ["$age", 18]
// }
// }
// },
// {
// "$replaceWith": {
// "name": "$name",
// "isAdult": "$isAdult"
// }
// }
//]
aggregation.StageBsonBuilder().
AddFields(aggregation.Gte("isAdult", "$age", 18)).
ReplaceWith(bsonx.NewD().Add("name", "$name").Add("isAdult", "$isAdult").Build()).Build()
// mongo.Pipeline{bson.D{bson.E{Key:"$bucket", Value:bson.D{bson.E{Key:"groupBy", Value:"$age"}, bson.E{Key:"boundaries", Value:[]interface {}{0, 19, 31, 46, +Inf}}, bson.E{Key:"default", Value:"Other"}, bson.E{Key:"output", Value:bson.D{bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}}}}}}
// [
// {
// $bucket: {
// groupBy: "$age", // 指定分组的依据字段
// boundaries: [0, 19, 31, 46, Infinity], // 定义年龄分组的边界
// default: "Other", // 对于不满足任何边界条件的文档,将其分配到一个默认的桶
// output: {
// "count": { $sum: 1 }, // 计算每个桶中的文档数
// "names": { $push: "$name" } // 收集每个桶中所有用户的名字
// }
// }
// }
//]
aggregation.StageBsonBuilder().Bucket(
"$age",
[]any{0, 19, 31, 46, math.Inf(1)},
&types.BucketOptions{
DefaultKey: "Other",
Output: aggregation.BsonBuilder().Sum("count", 1).Push("names", "$name").Build(),
},
).Build()
更多用法可前往官网文档 聚合阶段构建器 | go-mongox 进行查看。
聚合表达式
聚合表达式构建器用于轻松构建聚合管道的各个表达式(Expressions
),如 $add
, $subtract
等。
通过 aggregation.BsonBuilder()
创建一个新的构建器实例,然后调用相应的方法来构建表达式。
简单构建
对于单一的表达式,我们直接使用函数进行构建。
// bson.D{bson.E{Key:"isAdult", Value:bson.D{bson.E{Key:"$gte", Value:[]interface {}{"$age", 18}}}}}
//{
// "isAdult": {
// "$gte": ["$age", 18]
// }
//}
aggregation.Gte("isAdult", "$age", 18)
// bson.D{bson.E{Key:"birthYear", Value:bson.D{bson.E{Key:"$subtract", Value:[]interface {}{2024, "$age"}}}}}
//{
// "birthYear": {
// "$subtract": [2024, "$age"]
// }
//}
aggregation.Subtract("birthYear", 2024, "$age")
// bson.D{bson.E{Key:"age", Value:bson.D{bson.E{Key:"$gt", Value:[]interface {}{18}}}}}
//{
// "age": {
// "$gt": 18
// }
//}
aggregation.Gt("age", 18)
更多用法可前往官网文档 聚合表达式构建器 | go-mongox 进行查看。
复杂构建
对于较为复杂的表达式,我们需要使用构建器进行构建。
// bson.D{bson.E{Key:"isAdult", Value:bson.D{bson.E{Key:"$gte", Value:[]interface {}{"$age", 18}}}}, bson.E{Key:"birthYear", Value:bson.D{bson.E{Key:"$subtract", Value:[]interface {}{2024, "$age"}}}}}
//{
// "isAdult": {
// "$gte": ["$age", 18]
// },
// "birthYear": {
// "$subtract": [2024, "$age"]
// }
//}
aggregation.BsonBuilder().
Gte("isAdult", "$age", 18).
Subtract("birthYear", 2024, "$age").Build()
// bson.D{bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}
//{
// "count": {
// "$sum": 1
// },
// "names": {
// "$push": "$name"
// }
//}
aggregation.BsonBuilder().Sum("count", 1).Push("names", "$name").Build()
// bson.D{bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}, bson.E{Key:"averageAge", Value:bson.D{bson.E{Key:"$avg", Value:"$age"}}}, bson.E{Key:"names", Value:bson.D{bson.E{Key:"$push", Value:"$name"}}}}
//{
// "count": {
// "$sum": 1
// },
// "averageAge": {
// "$avg": "$age"
// },
// "names": {
// "$push": "$name"
// }
//}
aggregation.BsonBuilder().
Sum("count", 1).
Avg("averageAge", "$age").
Push("names", "$name").Build()
更多用法可前往官网文档 聚合表达式构建器 | go-mongox 进行查看。
bsonx 包:简化 BSON 数据的构建
bsonx
提供提供了一系列便捷的函数和构建器去构建 BSON
数据,旨在简化 BSON
数据的构建过程。
构建器
目前 bsonx
包只提供了 bson.D
数据的构建器 DBuilder
。
d := bsonx.NewD().Add("name", "Mingyong Chen").Add("name", "Burt")
函数
通过函数简化 BSON
数据的构建过程。
m := bsonx.M("name", "陈明勇")
e := bsonx.E("name", "陈明勇")
d := bsonx.D("name", "陈明勇")
a := bsonx.A("Mingyong Chen", "陈明勇")
更多用法可前往官网文档 bsonx 包 | go-mongox 进行查看。
小结
本文对 go-mongox
库中 bson 数据构建
这一模块进行详细介绍。go-mongox
设计了多种不同类型的 BSON
构建器和函数,为我们 Go
开发者在不同场景下构建 BSON
数据提供了强大的支持。
为 go-mongox 做出贡献吧!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。