头图

前言

在开发使用 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 将会变得更加强大!


陈明勇
23 声望6 粉丝

一个热爱技术,喜欢专研技术的程序员。