写点什么

效率提升 80%:go-mongox 让复杂的 BSON 数据编写变得简单

作者:陈明勇
  • 2024-04-07
    广东
  • 本文字数:6251 字

    阅读完需:约 21 分钟

效率提升 80%:go-mongox 让复杂的 BSON 数据编写变得简单

前言

在开发使用 MongoDBGo 应用中,我们避免不了要编写 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 数据提供了强大的支持。无论是数据查询、更新,还是执行复杂的聚合操作,开发者都可以在 bsonxqueryupdate 以及 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 做出贡献吧!

如果有您的加入,go-mongox 将会变得更加强大!

发布于: 刚刚阅读数: 7
用户头像

陈明勇

关注

一个热爱技术,喜欢专研技术的程序员。 2021-10-20 加入

公众号:程序员陈明勇

评论

发布
暂无评论
效率提升 80%:go-mongox 让复杂的 BSON 数据编写变得简单_Go_陈明勇_InfoQ写作社区