前语

Go 语言中运用 MongoDB 官方结构进行调集操作时,深深感到构建 bson 数据是一件非常繁琐的工作。字段、逗号,括号等符号的摆放,让我感觉似乎是在进行一场拼图游戏。因而我在想,有没有一个能让我丝滑,高效操作 MongoDB 的第三方结构呢,惋惜的是,并没有找到符合我预期的结构,索性我就自己着手开发了一个,这就是 go-mongox 结构的由来。

假如你也有相似我的这种感触,信任 go-mongox 结构能给你带来不一样的体会。

go-mongox

go-mongox 根据 泛型MongoDB 官方结构进行了二次封装,它经过运用链式调用的办法,让咱们能够丝滑地操作文档。一起,其还供给了多种类型的 bson 结构器,帮助咱们高效的构建 bson 数据。

库房地址github.com/chenmingyon…

该结构处于初期阶段,期望经过群策群力的办法,约请各位开发者一起参加,提出名贵的建议和意见,一起打造一个更强壮、更灵敏的结构。期待着您的积极参加和名贵反应,一起推进go-mongox不断进步。

功能

  • 文档的 crud 操作
  • 聚合操作
  • 结构 bson 数据
  • (敬请期待)

装置

go get github.com/chenmingyong0423/go-mongox@latest

collection 调集操作

根据泛型的 collection 形态初始化

package main
import (
	"context"
	"github.com/chenmingyong0423/go-mongox"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readpref"
)
type Post struct {
	Id      string `bson:"_id"`
	Title   string `bson:"title"`
	Author  string `bson:"author"`
	Content string `bson:"content"`
}
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := newCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[Post](mongoCollection)
}
// 示例代码,不是最佳的创立办法
func newCollection() *mongo.Collection {
	client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(options.Credential{
		Username:   "test",
		Password:   "test",
		AuthSource: "db-test",
	}))
	if err != nil {
		panic(err)
	}
	err = client.Ping(context.Background(), readpref.Primary())
	if err != nil {
		panic(err)
	}
	collection := client.Database("db-test").Collection("test_post")
	return collection
}

经过 mongox.NewCollection 函数,咱们能够创立一个根据泛型的 collection 装修器。

Creator 发明器

Creator 是一个发明器,用于履行刺进相关的操作。

刺进单个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/creator/insert_one.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	// 刺进一个文档
	doc := collection.Post{Id: "1", Title: "go-mongox", Author: "陈明勇", Content: "go-mongox,不一样的体会。"}
	oneResult, err := postCollection.Creator().InsertOne(context.Background(), doc)
	if err != nil {
		panic(err)
	}
	fmt.Println(oneResult.InsertedID.(string) == "1") // true
	// 带着 option 参数
	oneResult, err = postCollection.Creator().OneOptions(options.InsertOne().SetComment("test")).InsertOne(context.Background(), collection.Post{Id: "2", Title: "go 语言 go-mongox 库的运用教程", Author: "陈明勇", Content: "go-mongox 旨在供给更方便和高效的MongoDB数据操作体会。"})
	if err != nil {
		panic(err)
	}
	fmt.Println(oneResult.InsertedID.(string) == "2") // true
}

根据 postCollection 实例,咱们能够经过 Creator() 办法创立一个发明器,然后进行刺进操作。

InsertOne 办法与官方的 API 同名,作用是刺进一条数据。假如咱们想要设置 options 参数,应运用 OneOptions 办法。

能够看到,无论是设置 options 参数还是履行刺进操作,都在一条链路上完成,即完成了链式操作。

刺进多个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/creator/insert_many.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	docs := []collection.Post{
		{Id: "1", Title: "go", Author: "陈明勇", Content: "..."},
		{Id: "2", Title: "mongo", Author: "陈明勇", Content: "..."},
	}
	manyResult, err := postCollection.Creator().InsertMany(context.Background(), docs)
	if err != nil {
		panic(err)
	}
	fmt.Println(len(manyResult.InsertedIDs) == 2) // true
	// 带着 option 参数
	manyResult, err = postCollection.Creator().ManyOptions(options.InsertMany().SetComment("test")).InsertMany(context.Background(), []collection.Post{
		{Id: "3", Title: "go-mongox", Author: "陈明勇", Content: "..."},
		{Id: "4", Title: "builder", Author: "陈明勇", Content: "..."},
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(len(manyResult.InsertedIDs) == 2) // true
}

InsertMany 办法与官方的 API 同名,作用是刺进多条数据。假如咱们想要设置 options 参数,应运用 ManyOptions 办法。

Finder 查询器

Finder 是一个查询器,用于履行查询相关的操作。

查询单个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/finder/find_one.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/query"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	_, err := postCollection.Creator().InsertOne(context.Background(), collection.Post{Id: "1", Title: "go", Author: "陈明勇", Content: "..."})
	if err != nil {
		panic(err)
	}
	// 查询单个文档
	post, err := postCollection.Finder().Filter(bsonx.Id("1")).FindOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(post)
	// 设置 *options.FindOneOptions 参数
	post2, err := postCollection.Finder().
		Filter(bsonx.Id("1")).
		OneOptions(options.FindOne().SetProjection(bsonx.M("content", 0))).
		FindOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(post2)
	// - map 作为 filter 条件
	post3, err := postCollection.Finder().Filter(map[string]any{"_id": "1"}).FindOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(post3)
	// - 杂乱条件查询
	// -- 运用 query 包结构杂乱的 bson: bson.D{bson.E{Key: "title", Value: bson.M{"$eq": "go"}}, bson.E{Key: "author", Value: bson.M{"$eq": "陈明勇"}}}
	post4, err := postCollection.Finder().
		Filter(query.BsonBuilder().Eq("title", "go").Eq("author", "陈明勇").Build()).
		FindOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(post4)
}

根据 postCollection 实例,咱们能够经过 Finder() 办法创立一个查询器,然后进行查询操作。

FindOne 办法与官方的 API 同名,作用是查询单个文档。咱们能够经过 FilterOneOptions 办法分别设置 查询条件options 参数。

关于简略的查询条件,咱们能够运用 bsonx 包供给的函数进行结构,例如 bsonx.Id("1");关于杂乱的查询条件,咱们能够运用 query 包供给的 BsonBuilder结构器进行结构。这两个包的用法接下来会进行具体地介绍。

查询多个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/finder/find.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/query"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	_, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
		{Id: "1", Title: "go", Author: "陈明勇", Content: "..."},
		{Id: "2", Title: "mongo", Author: "陈明勇", Content: "..."},
	})
	if err != nil {
		panic(err)
	}
	// 查询多个文档
	// bson.D{bson.E{Key: "_id", Value: bson.M{"$in": []string{"1", "2"}}}}
	posts, err := postCollection.Finder().Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).Find(context.Background())
	if err != nil {
		panic(err)
	}
	for _, post := range posts {
		fmt.Println(post)
	}
	// 设置 *options.FindOptions 参数
	// bson.D{bson.E{Key: "_id", Value: bson.M{types.In: []string{"1", "2"}}}}
	posts2, err := postCollection.Finder().
		Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).
		Options(options.Find().SetProjection(bsonx.M("content", 0))).
		Find(context.Background())
	if err != nil {
		panic(err)
	}
	for _, post := range posts2 {
		fmt.Println(post)
	}
}

Find 办法与官方的 API 同名,作用是查询多个文档。假如咱们想要设置 options 参数,应运用 Options 办法。

在上面的比如中,为了结构 $in 查询句子,咱们运用了 BsonBuilder 供给的办法 InString

Updater 更新器

Updater 是一个更新器,用于履行更新相关的操作。

更新单个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/updater/update_one.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/update"
	"github.com/chenmingyong0423/go-mongox/types"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	_, err := postCollection.Creator().InsertOne(context.Background(), collection.Post{Id: "1", Title: "go", Author: "陈明勇", Content: "..."})
	if err != nil {
		panic(err)
	}
	// 更新单个文档
	// 经过 update 包构建 bson 更新句子
	updateResult, err := postCollection.Updater().
		Filter(bsonx.Id("1")).
		Updates(update.BsonBuilder().Set(bsonx.M("title", "golang")).Build()).
		UpdateOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(updateResult.ModifiedCount == 1) // true
	// - 运用 map 结构更新数据,并设置 *options.UpdateOptions,履行 upsert 操作
	updateResult2, err := postCollection.Updater().
		Filter(bsonx.Id("2")).
		UpdatesWithOperator(types.Set, map[string]any{"title": "mongo"}).Options(options.Update().SetUpsert(true)).
		UpdateOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(updateResult2.UpsertedID.(string) == "2") // true
}

根据 postCollection 实例,咱们能够经过 Updater() 办法创立一个更新器,然后进行更新操作。

UpdateOne 办法与官方的 API 同名,作用是更新单个文档。咱们能够经过 FilterOptions 办法分别设置 文档匹配的条件options 参数。

关于更新操作参数,咱们能够运用以下两个办法进行设置:

  • Updates 办法:该办法接纳 bsonmap 等合法的更新操作句子。上面的比如运用了 update 包里的 BsonBuilder 对更新操作句子进行结构。
  • UpdatesWithOperator 办法:该办法的第一个参数为更新操作符,第二个参数为预期更新的数据。

更新多个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/updater/update_many.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/query"
	"github.com/chenmingyong0423/go-mongox/builder/update"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	_, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
		{Id: "1", Title: "go", Author: "陈明勇", Content: "..."},
		{Id: "2", Title: "mongo", Author: "陈明勇", Content: "..."},
	})
	if err != nil {
		panic(err)
	}
	// 更新多个文档
	updateResult, err := postCollection.Updater().
		Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).
		Updates(update.BsonBuilder().Set(bsonx.M("title", "golang")).Build()).
		UpdateMany(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(updateResult.ModifiedCount == 2) // true
}

UpdateMany 办法与官方的 API 同名,作用是更新多个文档。

Deleter 删去器

Deleter 是一个删去器,用于履行删去相关的操作。

删去单个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/deleter/delete_one.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	_, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
		{Id: "1", Title: "go", Author: "陈明勇", Content: "..."},
		{Id: "2", Title: "mongo", Author: "陈明勇", Content: "..."},
	})
	if err != nil {
		panic(err)
	}
	// 删去单个文档
	deleteResult, err := postCollection.Deleter().Filter(bsonx.Id("1")).DeleteOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(deleteResult.DeletedCount == 1) // true
	// 带着 option 参数
	deleteResult2, err := postCollection.Deleter().Filter(bsonx.Id("2")).Options(options.Delete().SetComment("test")).DeleteOne(context.Background())
	if err != nil {
		panic(err)
	}
	fmt.Println(deleteResult2.DeletedCount == 1) // true
}

根据 postCollection 实例,咱们能够经过 Deleter() 办法创立一个删去器,然后进行删去操作。

DeleteOne 办法与官方的 API 同名,作用是删去单个文档。咱们能够经过 FilterOptions 办法分别设置 文档匹配的条件options 参数。

删去多个文档

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/deleter/delete_many.go
package main
import (
    "chenmingyong0423/blog/tutorial-code/go-mongox/collection"
    "context"
    "fmt"
    "github.com/chenmingyong0423/go-mongox"
    "github.com/chenmingyong0423/go-mongox/builder/query"
)
func main() {
    // 你需求预先创立一个 *mongo.Collection 目标
    mongoCollection := collection.NewCollection()
    // 运用 Post 结构体作为泛型参数创立一个 collection
    postCollection := mongox.NewCollection[collection.Post](mongoCollection)
    _, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
       {Id: "1", Title: "go", Author: "陈明勇", Content: "..."},
       {Id: "2", Title: "mongo", Author: "陈明勇", Content: "..."},
    })
    if err != nil {
       panic(err)
    }
    // 删去多个文档
    // - 经过 query 包结构杂乱的 bson 句子
    deleteResult, err := postCollection.Deleter().Filter(query.BsonBuilder().InString("_id", []string{"1", "2"}...).Build()).DeleteMany(context.Background())
    if err != nil {
       panic(err)
    }
    fmt.Println(deleteResult.DeletedCount == 2) // true
}

DeleteMany 办法与官方的 API 同名,作用是删去多个文档。

Aggregator 聚合器

Aggregator 是一个聚合器,用于履行聚合相关的操作。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/aggregator/aggregator.go
package main
import (
	"chenmingyong0423/blog/tutorial-code/go-mongox/collection"
	"context"
	"fmt"
	"github.com/chenmingyong0423/go-mongox"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/aggregation"
	"github.com/chenmingyong0423/go-mongox/types"
	"go.mongodb.org/mongo-driver/mongo"
)
func main() {
	// 你需求预先创立一个 *mongo.Collection 目标
	mongoCollection := collection.NewCollection()
	// 运用 Post 结构体作为泛型参数创立一个 collection
	postCollection := mongox.NewCollection[collection.Post](mongoCollection)
	_, err := postCollection.Creator().InsertMany(context.Background(), []collection.Post{
		{Id: "1", Title: "go", Author: "陈明勇", Content: "..."},
		{Id: "2", Title: "mongo", Author: "陈明勇", Content: "..."},
	})
	if err != nil {
		panic(err)
	}
	// 聚合操作
	// - 运用 aggregation 包结构 pipeline
	posts, err := postCollection.
		Aggregator().Pipeline(aggregation.StageBsonBuilder().Project(bsonx.M("content", 0)).Build()).
		Aggregate(context.Background())
	if err != nil {
		panic(err)
	}
	for _, post := range posts {
		fmt.Println(post)
	}
	// 假如咱们经过聚合操作更改字段的名称,那么咱们能够运用 AggregationWithCallback 办法,然后经过 callback 函数将成果映射到咱们预期的结构体中
	type DiffPost struct {
		Id          string `bson:"_id"`
		Title       string `bson:"title"`
		Name        string `bson:"name"` // author → name
		Content     string `bson:"content"`
		Outstanding bool   `bson:"outstanding"`
	}
	result := make([]*DiffPost, 0)
	//  将 author 字段更名为 name,排除 content 字段,添加 outstanding 字段,返回成果为 []*DiffPost
	err = postCollection.Aggregator().
		Pipeline(aggregation.StageBsonBuilder().Project(
			bsonx.D(types.KV("name", "$author"), types.KV("author", 1), types.KV("_id", 1), types.KV("title", 1), types.KV("outstanding", aggregation.BsonBuilder().Eq("$author", "陈明勇").Build()))).Build(),
		).
		AggregateWithCallback(context.Background(), func(ctx context.Context, cursor *mongo.Cursor) error {
			return cursor.All(ctx, &result)
		})
	for _, post := range result {
		fmt.Println(post)
	}
}

根据postCollection实例,咱们能够经过Aggregator()办法创立一个聚合器,然后进行聚合操作。

咱们能够经过PipelineAggregateOptions办法分别设置pipelineoptions参数。

关于履行聚合操作,有以下两个办法:

  • Aggregate 办法:与与官方的API同名。
  • AggregateWithCallback 办法:因为咱们在创立 collection 装修器时,运用泛型绑定了一个结构体,假如咱们履行聚合操作之后,返回的数据与所绑定的结构体映射不上,这时能够运用该办法将成果映射到指定的结构里。

Builder 结构器

go-mongox 结构供给了以下几种类型的结构器:

  • universal: 简略而又通用bson 数据结构函数。
  • query: 查询结构器,用于结构查询操作所需的 bson 数据。
  • update: 更新结构器,用于结构更新操作所需的 bson 数据。
  • aggregation: 聚合操作结构器,包括两种,一种是用于结构聚合 stage 阶段所需的 bson 数据,另一种是用于结构除了 stage 阶段以外的 bson 数据。

universal 通用结构

咱们能够运用 bsonx 包里的一些函数进行 bson 数据的结构,例如 bsonx.Mbsonx.Idbsonx.D 等等。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/universal.go
package main
import (
	"fmt"
	"github.com/chenmingyong0423/go-mongox/bsonx"
)
func main() {
	// bson.M{"名字": "陈明勇"}
	m := bsonx.M("名字", "陈明勇")
	fmt.Printf("%#vnn", m)
	// bson.M{"_id": "陈明勇"}
	id := bsonx.Id("陈明勇")
	fmt.Printf("%#vnn", id)
	// bson.D{bson.E{Key:"名字", Value:"陈明勇"}, bson.E{Key:"手机号", Value:"1888***1234"}}
	d := bsonx.D(bsonx.KV("名字", "陈明勇"), bsonx.KV("手机号", "1888***1234"))
	fmt.Printf("%#vnn", d)
	// bson.E{Key:"名字", Value:"陈明勇"}
	e := bsonx.E("名字", "陈明勇")
	fmt.Printf("%#vnn", e)
	// bson.A{"陈明勇", "1888***1234"}
	a := bsonx.A("陈明勇", "1888***1234")
	fmt.Printf("%#v", a)
}

bsonx 包暂时供给了这些结构函数,后面会继续添加更多有用的函数。

特别注意的是,运用 bsonx.D 办法结构数据时,传入的参数,需求运用 bsonx.KV 办法进行传递,意图是强约束 key-value 的类型。

query 查询结构器

query 包能够帮咱们结构出查询相关的 bson 数据,例如 $in$gt$and 等等。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/query.go
package main
import (
	"fmt"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/query"
)
func main() {
	// bson.D{bson.E{Key:"名字", Value:"陈明勇"}}
	d := query.BsonBuilder().Add(bsonx.KV("名字", "陈明勇")).Build()
	fmt.Printf("%#vnn", d)
	// bson.D{bson.E{Key:"age", Value:bson.D{{Key:"$gt", Value:18}, bson.E{Key:"$lt", Value:25}}}}
	d = query.BsonBuilder().Gt("age", 18).Lt("age", 25).Build()
	fmt.Printf("%#vnn", d)
	//  bson.D{bson.E{Key:"age", Value:bson.D{{Key:"$in", Value:[]int{18, 19, 20}}}}}
	d = query.BsonBuilder().InInt("age", 18, 19, 20).Build()
	fmt.Printf("%#vnn", d)
	// bson.d{bson.E{Key: "$and", Value: []any{bson.D{{Key: "x", Value: bson.D{{Key: "$ne", Value: 0}}}}, bson.D{{Key: "y", Value: bson.D{{Key: "$gt", Value: 0}}}}}}
	d = query.BsonBuilder().And(
		query.BsonBuilder().Ne("x", 0).Build(),
		query.BsonBuilder().Gt("y", 0).Build(),
	).Build()
	fmt.Printf("%#vnn", d)
	// bson.D{bson.E{Key:"qty", Value:bson.D{{Key:"$exists", Value:true}, bson.E{Key:"$nin", Value:[]int{5, 15}}}}}
	d = query.BsonBuilder().Exists("qty", true).NinInt("qty", 5, 15).Build()
	fmt.Printf("%#vnn", d)
	// elemMatch
	// bson.D{bson.E{Key: "result", Value: bson.D{bson.E{Key: "$elemMatch", Value: bson.D{bson.E{Key: "$gte", Value: 80}, bson.E{Key: "$lt", Value: 85}}}}}}
	d = query.BsonBuilder().ElemMatch("result", bsonx.D(bsonx.KV("$gte", 80), bsonx.KV("$lt", 85))).Build()
	fmt.Printf("%#v", d)
}

query 包供给的办法不止这些,以上仅仅列举出一些典型的比如,还有更多的用法等着你去探究。

update 更新结构器

update 包能够帮咱们结构出更新操作相关的 bson 数据,例如 $set$$inc$push 等等。

// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/update.go
package main
import (
	"fmt"
	"github.com/chenmingyong0423/go-mongox/bsonx"
	"github.com/chenmingyong0423/go-mongox/builder/update"
)
func main() {
	// bson.D{bson.E{Key:"$set", Value:bson.M{"name":"陈明勇"}}}
	u := update.BsonBuilder().Set(bsonx.M("name", "陈明勇")).Build()
	fmt.Printf("%#vnn", u)
	// bson.D{bson.E{Key:"$inc", Value:bson.D{bson.E{Key:"orders", Value:1}, bson.E{Key:"ratings", Value:-1}}}}
	u = update.BsonBuilder().Inc(bsonx.D(bsonx.KV("orders", 1), bsonx.KV("ratings", -1))).Build()
	fmt.Printf("%#vnn", u)
	// bson.D{bson.E{Key:"$push", Value:bson.M{"scores":95}}}
	u = update.BsonBuilder().Push(bsonx.M("scores", 95)).Build()
	fmt.Printf("%#vnn", u)
	// bson.D{bson.E{Key:"$unset", Value:bson.D{primitive.E{Key:"quantity", Value:""}, bson.E{Key:"instock", Value:""}}}}
	u = update.BsonBuilder().Unset("quantity", "instock").Build()
	fmt.Printf("%#v", u)
}

update 包供给的办法不止这些,以上仅仅列举出一些典型的比如,还有更多的用法等着你去探究。

aggregation 聚合结构器

aggregation 包供给了两个 builder

  • StageBsonBuilder:用于结构 stage 阶段所需的 bson 数据
  • BsonBuilder:用于结构除了 stage 阶段以外的 bson 数据。
// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/aggregation.go
package main
import (
    "fmt"
    "github.com/chenmingyong0423/go-mongox/bsonx"
    "github.com/chenmingyong0423/go-mongox/builder/aggregation"
    "github.com/chenmingyong0423/go-mongox/builder/query"
    "github.com/chenmingyong0423/go-mongox/types"
)
func main() {
    // bson.D{bson.E{Key:"$gt", Value:[]any{"$qty", 250}}}
    gt := aggregation.BsonBuilder().Gt("$qty", 250).Build()
    fmt.Printf("%#vnn", gt)
    // mongo.Pipeline{bson.D{bson.E{Key:"$project", Value:bson.D{bson.E{Key:"name", Value:1}, bson.E{Key:"age", Value:1}, bson.E{Key:"qtyGt250", Value:bson.D{bson.E{Key:"$gt", Value:[]interface {}{"$qty", 250}}}}}}}}
    pipeline := aggregation.StageBsonBuilder().Project(bsonx.D(bsonx.KV("name", 1), bsonx.KV("age", 1), bsonx.KV("qtyGt250", gt))).Build()
    fmt.Printf("%#vnn", pipeline)
    // bson.D{bson.E{Key:"$or", Value:[]interface {}{bson.D{bson.E{Key:"score", Value:bson.D{bson.E{Key:"$gt", Value:70}, bson.E{Key:"$lt", Value:90}}}}, bson.D{bson.E{Key:"views", Value:bson.D{bson.E{Key:"$gte", Value:90}}}}}}}
    or := aggregation.BsonBuilder().Or(
       query.BsonBuilder().Gt("score", 70).Lt("score", 90).Build(),
       query.BsonBuilder().Gte("views", 90).Build(),
    ).Build()
    fmt.Printf("%#vnn", or)
    // mongo.Pipeline{bson.D{bson.E{Key:"$match", Value:bson.D{bson.E{Key:"$or", Value:[]any{bson.D{bson.E{Key:"score", Value:bson.D{bson.E{Key:"$gt", Value:70}, bson.E{Key:"$lt", Value:90}}}}, bson.D{bson.E{Key:"views", Value:bson.D{bson.E{Key:"$gte", Value:90}}}}}}}}}, bson.D{bson.E{Key:"$group", Value:bson.D{bson.E{Key:"_id", Value:any(nil)}, bson.E{Key:"count", Value:bson.D{bson.E{Key:"$sum", Value:1}}}}}}}
    pipeline = aggregation.StageBsonBuilder().Match(or).Group(nil, bsonx.E("count", aggregation.BsonBuilder().Sum(1).Build())).Build()
    fmt.Printf("%#vnn", pipeline)
    // mongo.Pipeline{bson.D{bson.E{Key:"$unwind", Value:"$size"}}}
    pipeline = aggregation.StageBsonBuilder().Unwind("$size", nil).Build()
    fmt.Printf("%#vnn", pipeline)
    // mongo.Pipeline{bson.D{bson.E{Key:"$unwind", Value:bson.D{bson.E{Key:"path", Value:"$size"}, bson.E{Key:"includeArrayIndex", Value:"arrayIndex"}, bson.E{Key:"preserveNullAndEmptyArrays", Value:true}}}}}
    pipeline = aggregation.StageBsonBuilder().Unwind("$size", &types.UnWindOptions{
       IncludeArrayIndex:          "arrayIndex",
       PreserveNullAndEmptyArrays: true,
    }).Build()
    fmt.Printf("%#v", pipeline)
}

aggregation 包供给的办法不止这些,以上仅仅列举出一些典型的比如,还有更多的用法等着你去探究。

小结

本文对 go-mongox 结构进行了具体的介绍,它有两个核心,一个是根据泛型的 colletion 形态,另一个就是 bson 结构器了。这两个核心是单独存在的,你能够运用其中之一,也能够一起运用。

库房地址:github.com/chenmingyon…

该结构处于初期阶段,期望经过群策群力的办法,约请各位开发者一起参加,提出名贵的建议和意见,一起打造一个更强壮、更灵敏的结构。期待着您的积极参加和名贵反应,一起推进go-mongox不断进步。