go?mongox簡(jiǎn)潔高效文檔操作及bson數(shù)據(jù)構(gòu)造流暢技巧
前言
在 Go
語(yǔ)言中使用 MongoDB
官方框架進(jìn)行集合操作時(shí),深深感到構(gòu)建 bson
數(shù)據(jù)是一件非常繁瑣的工作。字段、逗號(hào),括號(hào)等符號(hào)的排列,讓我感覺(jué)仿佛是在進(jìn)行一場(chǎng)拼圖游戲。
因此我在想,有沒(méi)有一個(gè)能讓我絲滑,高效操作 MongoDB
的第三方框架呢,遺憾的是,并沒(méi)有找到符合我預(yù)期的框架,索性我就自己動(dòng)手開(kāi)發(fā)了一個(gè),這就是 go-mongox
框架的由來(lái)。
如果你也有類(lèi)似我的這種感受,相信 go-mongox
框架能給你帶來(lái)不一樣的體驗(yàn)。
go-mongox
go-mongox
基于 泛型 對(duì) MongoDB
官方框架進(jìn)行了二次封裝,它通過(guò)使用鏈?zhǔn)秸{(diào)用的方式,讓我們能夠絲滑地操作文檔。同時(shí),其還提供了多種類(lèi)型的 bson
構(gòu)造器,幫助我們高效的構(gòu)建 bson
數(shù)據(jù)。
倉(cāng)庫(kù)地址:https://github.com/chenmingyong0423/go-mongox
該框架處于初期階段,希望通過(guò)集思廣益的方式,邀請(qǐng)各位開(kāi)發(fā)者共同參與,提出寶貴的建議和意見(jiàn),共同打造一個(gè)更強(qiáng)大、更靈活的框架。期待著您的積極參與和寶貴反饋,共同推動(dòng)go-mongox
不斷進(jìn)步。
功能
- 文檔的
crud
操作 - 聚合操作
- 構(gòu)造
bson
數(shù)據(jù) - ······(敬請(qǐng)期待)
安裝
go get github.com/chenmingyong0423/go-mongox@latest
collection 集合操作
基于泛型的 collection 形態(tài)初始化
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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := newCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection postCollection := mongox.NewCollection[Post](mongoCollection) } // 示例代碼,不是最佳的創(chuàng)建方式 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 }
通過(guò) mongox.NewCollection
函數(shù),我們可以創(chuàng)建一個(gè)基于泛型的 collection
裝飾器。
Creator 創(chuàng)造器
Creator
是一個(gè)創(chuàng)造器,用于執(zhí)行插入相關(guān)的操作。
插入單個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) collection postCollection := mongox.NewCollection[collection.Post](mongoCollection) // 插入一個(gè)文檔 doc := collection.Post{Id: "1", Title: "go-mongox", Author: "陳明勇", Content: "go-mongox,不一樣的體驗(yàn)。"} oneResult, err := postCollection.Creator().InsertOne(context.Background(), doc) if err != nil { panic(err) } fmt.Println(oneResult.InsertedID.(string) == "1") // true // 攜帶 option 參數(shù) oneResult, err = postCollection.Creator().OneOptions(options.InsertOne().SetComment("test")).InsertOne(context.Background(), collection.Post{Id: "2", Title: "go 語(yǔ)言 go-mongox 庫(kù)的使用教程", Author: "陳明勇", Content: "go-mongox 旨在提供更方便和高效的MongoDB數(shù)據(jù)操作體驗(yàn)。"}) if err != nil { panic(err) } fmt.Println(oneResult.InsertedID.(string) == "2") // true }
基于 postCollection
實(shí)例,我們可以通過(guò) Creator()
方法創(chuàng)建一個(gè)創(chuàng)造器,然后進(jìn)行插入操作。
InsertOne
方法與官方的 API
同名,作用是插入一條數(shù)據(jù)。如果我們想要設(shè)置 options
參數(shù),應(yīng)使用 OneOptions
方法。
可以看到,無(wú)論是設(shè)置 options
參數(shù)還是執(zhí)行插入操作,都在一條鏈路上完成,即實(shí)現(xiàn)了鏈?zhǔn)讲僮鳌?/p>
插入多個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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 參數(shù) 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
同名,作用是插入多條數(shù)據(jù)。如果我們想要設(shè)置 options
參數(shù),應(yīng)使用 ManyOptions
方法。
Finder 查詢(xún)器
Finder
是一個(gè)查詢(xún)器,用于執(zhí)行查詢(xún)相關(guān)的操作。
查詢(xún)單個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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) } // 查詢(xún)單個(gè)文檔 post, err := postCollection.Finder().Filter(bsonx.Id("1")).FindOne(context.Background()) if err != nil { panic(err) } fmt.Println(post) // 設(shè)置 *options.FindOneOptions 參數(shù) 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) // - 復(fù)雜條件查詢(xún) // -- 使用 query 包構(gòu)造復(fù)雜的 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
實(shí)例,我們可以通過(guò) Finder()
方法創(chuàng)建一個(gè)查詢(xún)器,然后進(jìn)行查詢(xún)操作。
FindOne
方法與官方的 API
同名,作用是查詢(xún)單個(gè)文檔。我們可以通過(guò) Filter
和 OneOptions
方法分別設(shè)置 查詢(xún)條件 和 options
參數(shù)。
對(duì)于簡(jiǎn)單的查詢(xún)條件,我們可以使用 bsonx
包提供的函數(shù)進(jìn)行構(gòu)造,例如 bsonx.Id("1")
;對(duì)于復(fù)雜的查詢(xún)條件,我們可以使用 query
包提供的 BsonBuilder
構(gòu)造器進(jìn)行構(gòu)造。這兩個(gè)包的用法接下來(lái)會(huì)進(jìn)行詳細(xì)地介紹。
查詢(xún)多個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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) } // 查詢(xún)多個(gè)文檔 // 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) } // 設(shè)置 *options.FindOptions 參數(shù) // 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
同名,作用是查詢(xún)多個(gè)文檔。如果我們想要設(shè)置 options
參數(shù),應(yīng)使用 Options
方法。
在上面的例子中,為了構(gòu)造 $in
查詢(xún)語(yǔ)句,我們使用了 BsonBuilder
提供的方法 InString
。
Updater 更新器
Updater
是一個(gè)更新器,用于執(zhí)行更新相關(guān)的操作。
更新單個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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) } // 更新單個(gè)文檔 // 通過(guò) update 包構(gòu)建 bson 更新語(yǔ)句 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 構(gòu)造更新數(shù)據(jù),并設(shè)置 *options.UpdateOptions,執(zhí)行 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
實(shí)例,我們可以通過(guò) Updater()
方法創(chuàng)建一個(gè)更新器,然后進(jìn)行更新操作。
UpdateOne
方法與官方的 API
同名,作用是更新單個(gè)文檔。我們可以通過(guò) Filter
和 Options
方法分別設(shè)置 文檔匹配的條件 和 options
參數(shù)。
對(duì)于更新操作參數(shù),我們可以使用以下兩個(gè)方法進(jìn)行設(shè)置:
Updates
方法:該方法接收bson
或map
等合法的更新操作語(yǔ)句。上面的例子使用了update
包里的BsonBuilder
對(duì)更新操作語(yǔ)句進(jìn)行構(gòu)造。UpdatesWithOperator
方法:該方法的第一個(gè)參數(shù)為更新操作符,第二個(gè)參數(shù)為預(yù)期更新的數(shù)據(jù)。
更新多個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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) } // 更新多個(gè)文檔 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
同名,作用是更新多個(gè)文檔。
Deleter 刪除器
Deleter
是一個(gè)刪除器,用于執(zhí)行刪除相關(guān)的操作。
刪除單個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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) } // 刪除單個(gè)文檔 deleteResult, err := postCollection.Deleter().Filter(bsonx.Id("1")).DeleteOne(context.Background()) if err != nil { panic(err) } fmt.Println(deleteResult.DeletedCount == 1) // true // 攜帶 option 參數(shù) 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
實(shí)例,我們可以通過(guò) Deleter()
方法創(chuàng)建一個(gè)刪除器,然后進(jìn)行刪除操作。
DeleteOne
方法與官方的 API
同名,作用是刪除單個(gè)文檔。我們可以通過(guò) Filter
和 Options
方法分別設(shè)置 文檔匹配的條件 和 options
參數(shù)。
刪除多個(gè)文檔
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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) } // 刪除多個(gè)文檔 // - 通過(guò) query 包構(gòu)造復(fù)雜的 bson 語(yǔ)句 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
同名,作用是刪除多個(gè)文檔。
Aggregator 聚合器
Aggregator
是一個(gè)聚合器,用于執(zhí)行聚合相關(guān)的操作。
// 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() { // 你需要預(yù)先創(chuàng)建一個(gè) *mongo.Collection 對(duì)象 mongoCollection := collection.NewCollection() // 使用 Post 結(jié)構(gòu)體作為泛型參數(shù)創(chuàng)建一個(gè) 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 包構(gòu)造 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) } // 如果我們通過(guò)聚合操作更改字段的名稱(chēng),那么我們可以使用 AggregationWithCallback 方法,然后通過(guò) callback 函數(shù)將結(jié)果映射到我們預(yù)期的結(jié)構(gòu)體中 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 字段,返回結(jié)果為 []*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
實(shí)例,我們可以通過(guò) Aggregator()
方法創(chuàng)建一個(gè)聚合器,然后進(jìn)行聚合操作。
我們可以通過(guò) Pipeline
和 AggregateOptions
方法分別設(shè)置 pipeline
和 options
參數(shù)。
對(duì)于執(zhí)行聚合操作,有以下兩個(gè)方法:
Aggregate
方法:與與官方的API
同名。AggregateWithCallback
方法:因?yàn)槲覀冊(cè)趧?chuàng)建collection
裝飾器時(shí),使用泛型綁定了一個(gè)結(jié)構(gòu)體,如果我們執(zhí)行聚合操作之后,返回的數(shù)據(jù)與所綁定的結(jié)構(gòu)體映射不上,這時(shí)可以使用該方法將結(jié)果映射到指定的結(jié)構(gòu)里。
Builder 構(gòu)造器
go-mongox
框架提供了以下幾種類(lèi)型的構(gòu)造器:
universal
: 簡(jiǎn)單而又通用的bson
數(shù)據(jù)構(gòu)造函數(shù)。query
: 查詢(xún)構(gòu)造器,用于構(gòu)造查詢(xún)操作所需的bson
數(shù)據(jù)。update
: 更新構(gòu)造器,用于構(gòu)造更新操作所需的bson
數(shù)據(jù)。aggregation
: 聚合操作構(gòu)造器,包含兩種,一種是用于構(gòu)造聚合stage
階段所需的bson
數(shù)據(jù),另一種是用于構(gòu)造除了stage
階段以外的bson
數(shù)據(jù)。
universal 通用構(gòu)造
我們可以使用 bsonx
包里的一些函數(shù)進(jìn)行 bson
數(shù)據(jù)的構(gòu)造,例如 bsonx.M
、bsonx.Id
和 bsonx.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("%#v\n\n", m) // bson.M{"_id": "陳明勇"} id := bsonx.Id("陳明勇") fmt.Printf("%#v\n\n", id) // bson.D{bson.E{Key:"姓名", Value:"陳明勇"}, bson.E{Key:"手機(jī)號(hào)", Value:"1888***1234"}} d := bsonx.D(bsonx.KV("姓名", "陳明勇"), bsonx.KV("手機(jī)號(hào)", "1888***1234")) fmt.Printf("%#v\n\n", d) // bson.E{Key:"姓名", Value:"陳明勇"} e := bsonx.E("姓名", "陳明勇") fmt.Printf("%#v\n\n", e) // bson.A{"陳明勇", "1888***1234"} a := bsonx.A("陳明勇", "1888***1234") fmt.Printf("%#v", a) }
bsonx
包暫時(shí)提供了這些構(gòu)造函數(shù),后面會(huì)持續(xù)添加更多有用的函數(shù)。
特別注意的是,使用 bsonx.D
方法構(gòu)造數(shù)據(jù)時(shí),傳入的參數(shù),需要使用 bsonx.KV
方法進(jìn)行傳遞,目的是強(qiáng)約束 key-value
的類(lèi)型。
query 查詢(xún)構(gòu)造器
query
包可以幫我們構(gòu)造出查詢(xún)相關(guān)的 bson
數(shù)據(jù),例如 $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("%#v\n\n", 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("%#v\n\n", 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("%#v\n\n", 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("%#v\n\n", 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("%#v\n\n", 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 更新構(gòu)造器
update
包可以幫我們構(gòu)造出更新操作相關(guān)的 bson
數(shù)據(jù),例如 $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("%#v\n\n", 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("%#v\n\n", u) // bson.D{bson.E{Key:"$push", Value:bson.M{"scores":95}}} u = update.BsonBuilder().Push(bsonx.M("scores", 95)).Build() fmt.Printf("%#v\n\n", 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 聚合構(gòu)造器
aggregation
包提供了兩個(gè) builder
:
StageBsonBuilder
:用于構(gòu)造stage
階段所需的bson
數(shù)據(jù)BsonBuilder
:用于構(gòu)造除了stage
階段以外的bson
數(shù)據(jù)。
// 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("%#v\n\n", 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("%#v\n\n", 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("%#v\n\n", 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("%#v\n\n", pipeline) // mongo.Pipeline{bson.D{bson.E{Key:"$unwind", Value:"$size"}}} pipeline = aggregation.StageBsonBuilder().Unwind("$size", nil).Build() fmt.Printf("%#v\n\n", 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
包提供的方法不止這些,以上只是列舉出一些典型的例子,還有更多的用法等著你去探索。
小結(jié)
本文對(duì) go-mongox
框架進(jìn)行了詳細(xì)的介紹,它有兩個(gè)核心,一個(gè)是基于泛型的 colletion
形態(tài),另一個(gè)就是 bson
構(gòu)造器了。這兩個(gè)核心是單獨(dú)存在的,你可以使用其中之一,也可以同時(shí)使用。
倉(cāng)庫(kù)地址:https://github.com/chenmingyong0423/go-mongox
該框架處于初期階段,希望通過(guò)集思廣益的方式,邀請(qǐng)各位開(kāi)發(fā)者共同參與,提出寶貴的建議和意見(jiàn),共同打造一個(gè)更強(qiáng)大、更靈活的框架。期待著您的積極參與和寶貴反饋,共同推動(dòng)go-mongox
不斷進(jìn)步。
以上就是go mongox簡(jiǎn)潔高效文檔操作及bson數(shù)據(jù)構(gòu)造流暢技巧的詳細(xì)內(nèi)容,更多關(guān)于go mongox文檔操作bson構(gòu)造的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 提升Go語(yǔ)言開(kāi)發(fā)效率的小技巧實(shí)例(GO語(yǔ)言語(yǔ)法糖)匯總
- 學(xué)會(huì)提升Go語(yǔ)言編碼效率技巧拒絕加班!
- 從錯(cuò)誤中學(xué)習(xí)改正Go語(yǔ)言六個(gè)壞習(xí)慣提高編程技巧
- GoJs中標(biāo)題和縮略圖使用技巧
- Go語(yǔ)言中節(jié)省內(nèi)存技巧方法示例
- Go內(nèi)存節(jié)省技巧簡(jiǎn)單實(shí)現(xiàn)方法
- go語(yǔ)言?xún)?yōu)雅地處理error工具及技巧詳解
- Go語(yǔ)言開(kāi)發(fā)技巧必知的小細(xì)節(jié)提升效率
相關(guān)文章
gorm golang 并發(fā)連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決方法
今天小編就為大家分享一篇gorm golang 并發(fā)連接數(shù)據(jù)庫(kù)報(bào)錯(cuò)的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07Golang?使用os?庫(kù)的?ReadFile()?讀文件最佳實(shí)踐
這篇文章主要介紹了Golang使用os庫(kù)的ReadFile()讀文件最佳實(shí)踐,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法
最近開(kāi)始使用Go/GoLand在import自定義包時(shí)出現(xiàn)各種狀況,下面這篇文章主要給大家介紹了關(guān)于Golang中處理import自定義包出錯(cuò)問(wèn)題的解決辦法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案
這篇文章主要給大家介紹了關(guān)于VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案,VSCode是我們開(kāi)發(fā)go程序的常用工具,最近安裝的時(shí)候遇到了些問(wèn)題,需要的朋友可以參考下2023-07-07Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Golang服務(wù)中context超時(shí)處理的方法詳解
在Go語(yǔ)言中,Context是一個(gè)非常重要的概念,它存在于一個(gè)完整的業(yè)務(wù)生命周期內(nèi),Context類(lèi)型是一個(gè)接口類(lèi)型,在實(shí)際應(yīng)用中,我們可以使用Context包來(lái)傳遞請(qǐng)求的元數(shù)據(jù),本文將給大家介紹Golang服務(wù)中context超時(shí)處理的方法和超時(shí)原因,需要的朋友可以參考下2023-05-05