Preface
existGo
Use in languageMongoDB
When the official framework performs collection operations, I deeply feel the constructionbson
Data is a very tedious task. The arrangement of symbols such as fields, commas, brackets, etc. makes me feel like I'm playing a puzzle game.
So I was wondering if there is one that can make me silky and efficiently operate?MongoDB
As for the third-party framework, unfortunately, I didn’t find a framework that suits my expectations, so I simply developed one by myself, which isgo-mongox
The origin of the framework.
If you have a similar feeling to me, I believego-mongox
The framework can bring you a different experience.
go-mongox
go-mongox
based onGenericsrightMongoDB
The official framework is secondary encapsulated, which allows us to operate documents silkily by using chain calls. At the same time, it also provides a variety of typesbson
Constructor helps us build efficientlybson
data.
Warehouse address:/chenmingyong0423/go-mongox
The framework is in its early stages. We hope to invite all developers to participate in the brainstorming way, put forward valuable suggestions and opinions, and jointly create a stronger and more flexible framework. Looking forward to your active participation and valuable feedback to promote it togethergo-mongox
Continuous progress.
Function
- Documentary
crud
operate - Aggregation operation
- Structure
bson
data - ······ (Stay tuned)
Install
go get /chenmingyong0423/go-mongox@latest
collection operation
Generic-based collection morphology initialization
package main import ( "context" "/chenmingyong0423/go-mongox" "/mongo-driver/mongo" "/mongo-driver/mongo/options" "/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() { // You need to pre-create a * object mongoCollection := newCollection() // Create a collection using the Post structure as a generic parameter postCollection := [Post](mongoCollection) } // Sample code is not the best way to create itfunc newCollection() * { client, err := ((), ().ApplyURI("mongodb://localhost:27017").SetAuth({ Username: "test", Password: "test", AuthSource: "db-test", })) if err != nil { panic(err) } err = ((), ()) if err != nil { panic(err) } collection := ("db-test").Collection("test_post") return collection }
passFunction, we can create a generic-based
collection
Decorators.
Creator Creator
Creator
is a creator for performing insert-related operations.
Insert a single document
// /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" "/chenmingyong0423/go-mongox" "/mongo-driver/mongo/options" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) // Insert a document doc := {Id: "1", Title: "go-mongox", Author: "Chen Mingyong", Content: "go-mongox, a different experience."} oneResult, err := ().InsertOne((), doc) if err != nil { panic(err) } (.(string) == "1") // true // Carry option parameters oneResult, err = ().OneOptions(().SetComment("test")).InsertOne((), {Id: "2", Title: "Tutorial for using go-mongox library in go language", Author: "Chen Mingyong", Content: "go-mongox is designed to provide a more convenient and efficient MongoDB data operation experience."}) if err != nil { panic(err) } (.(string) == "2") // true }
based onpostCollection
Instance, we can useCreator()
Method creates a creator and then performs an insert operation.
InsertOne
Methods and officialAPI
The same name is used to insert a piece of data. If we want to set itoptions
Parameters should be usedOneOptions
method.
You can see that, no matter the settingsoptions
Both parameters or insertion operations are completed on one link, that is, chain operations are implemented.
Insert multiple documents
// /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" "/chenmingyong0423/go-mongox" "/mongo-driver/mongo/options" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) docs := []{ {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}, {Id: "2", Title: "mongo", Author: "Chen Mingyong", Content: "..."}, } manyResult, err := ().InsertMany((), docs) if err != nil { panic(err) } (len() == 2) // true // Carry option parameters manyResult, err = ().ManyOptions(().SetComment("test")).InsertMany((), []{ {Id: "3", Title: "go-mongox", Author: "Chen Mingyong", Content: "..."}, {Id: "4", Title: "builder", Author: "Chen Mingyong", Content: "..."}, }) if err != nil { panic(err) } (len() == 2) // true }
InsertMany
Methods and officialAPI
The same name is used to insert multiple pieces of data. If we want to set itoptions
Parameters should be usedManyOptions
method.
Finder query
Finder
is a queryer used to perform query-related operations.
Query a single document
// /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" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/query" "/mongo-driver/mongo/options" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertOne((), {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}) if err != nil { panic(err) } // Query a single document post, err := ().Filter(("1")).FindOne(()) if err != nil { panic(err) } (post) // Set * Parameters post2, err := (). Filter(("1")). OneOptions(().SetProjection(("content", 0))). FindOne(()) if err != nil { panic(err) } (post2) // - map as filter condition post3, err := ().Filter(map[string]any{"_id": "1"}).FindOne(()) if err != nil { panic(err) } (post3) // - Complex condition query // -- Use the query package to construct complex bson: {{Key: "title", Value: {"$eq": "go"}}, {Key: "author", Value: {"$eq": "Chen Mingyong"}}} post4, err := (). Filter(().Eq("title", "go").Eq("author", "Chen Mingyong").Build()). FindOne(()) if err != nil { panic(err) } (post4) }
based onpostCollection
Instance, we can useFinder()
Method creates a queryer and then performs query operations.
FindOne
Methods and officialAPI
The same name is used to query a single document. We can passFilter
andOneOptions
Methods are set separatelyQuery criteriaandoptions
Parameters.
For simple query conditions, we can usebsonx
The functions provided by the package are constructed, for example("1")
;For complex query conditions, we can usequery
Package providedBsonBuilder
The constructor is constructed. The usage of these two packages will be introduced in detail next.
Query multiple documents
// /chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/finder/ package main import ( "chenmingyong0423/blog/tutorial-code/go-mongox/collection" "context" "fmt" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/query" "/mongo-driver/mongo/options" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertMany((), []{ {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}, {Id: "2", Title: "mongo", Author: "Chen Mingyong", Content: "..."}, }) if err != nil { panic(err) } // Query multiple documents // {{Key: "_id", Value: {"$in": []string{"1", "2"}}}} posts, err := ().Filter(().InString("_id", []string{"1", "2"}...).Build()).Find(()) if err != nil { panic(err) } for _, post := range posts { (post) } // Set * Parameters // {{Key: "_id", Value: {: []string{"1", "2"}}}} posts2, err := (). Filter(().InString("_id", []string{"1", "2"}...).Build()). Options(().SetProjection(("content", 0))). Find(()) if err != nil { panic(err) } for _, post := range posts2 { (post) } }
Find
Methods and officialAPI
The same name is used to query multiple documents. If we want to set itoptions
Parameters should be usedOptions
method.
In the above example, in order to construct$in
We used the query statementBsonBuilder
Methods providedInString
。
Updater updater
Updater
is an updater used to perform update-related operations.
Update a single document
// /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" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/update" "/chenmingyong0423/go-mongox/types" "/mongo-driver/mongo/options" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertOne((), {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}) if err != nil { panic(err) } // Update a single document // Build bson update statements through the update package updateResult, err := (). Filter(("1")). Updates(().Set(("title", "golang")).Build()). UpdateOne(()) if err != nil { panic(err) } ( == 1) // true // - Use map construct to update data, set *, and perform upsert operation updateResult2, err := (). Filter(("2")). UpdatesWithOperator(, map[string]any{"title": "mongo"}).Options(().SetUpsert(true)). UpdateOne(()) if err != nil { panic(err) } (.(string) == "2") // true }
based onpostCollection
Instance, we can useUpdater()
Method creates an updater and then performs an update operation.
UpdateOne
Methods and officialAPI
The same name is to update a single document. We can passFilter
andOptions
Methods are set separatelyDocument matching criteriaandoptions
Parameters.
For updating operation parameters, we can set it using the following two methods:
-
Updates
Method: This method receivesbson
ormap
and other legal update operation statements. The above example is usedupdate
The one in the bagBsonBuilder
Construct the update operation statement. -
UpdatesWithOperator
Method: The first parameter of this method is the update operator, and the second parameter is the expected updated data.
Update multiple documents
// /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" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/query" "/chenmingyong0423/go-mongox/builder/update" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertMany((), []{ {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}, {Id: "2", Title: "mongo", Author: "Chen Mingyong", Content: "..."}, }) if err != nil { panic(err) } // Update multiple documents updateResult, err := (). Filter(().InString("_id", []string{"1", "2"}...).Build()). Updates(().Set(("title", "golang")).Build()). UpdateMany(()) if err != nil { panic(err) } ( == 2) // true }
UpdateMany
Methods and officialAPI
The same name is to update multiple documents.
Deleter deleter
Deleter
It is a deleter used to perform deletion-related operations.
Delete a single document
// /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" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/bsonx" "/mongo-driver/mongo/options" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertMany((), []{ {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}, {Id: "2", Title: "mongo", Author: "Chen Mingyong", Content: "..."}, }) if err != nil { panic(err) } // Delete a single document deleteResult, err := ().Filter(("1")).DeleteOne(()) if err != nil { panic(err) } ( == 1) // true // Carry option parameters deleteResult2, err := ().Filter(("2")).Options(().SetComment("test")).DeleteOne(()) if err != nil { panic(err) } ( == 1) // true }
based onpostCollection
Instance, we can useDeleter()
Method creates a deleter and then performs a delete operation.
DeleteOne
Methods and officialAPI
The same name is used to delete a single document. We can passFilter
andOptions
Methods are set separatelyDocument matching criteriaandoptions
Parameters.
Delete multiple documents
// /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" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/builder/query" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertMany((), []{ {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}, {Id: "2", Title: "mongo", Author: "Chen Mingyong", Content: "..."}, }) if err != nil { panic(err) } // Delete multiple documents // - Construct complex bson statements through query package deleteResult, err := ().Filter(().InString("_id", []string{"1", "2"}...).Build()).DeleteMany(()) if err != nil { panic(err) } ( == 2) // true }
DeleteMany
Methods and officialAPI
The same name is used to delete multiple documents.
Aggregator aggregator
Aggregator
is an aggregator used to perform aggregation-related operations.
// /chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/collection/aggregator/ package main import ( "chenmingyong0423/blog/tutorial-code/go-mongox/collection" "context" "fmt" "/chenmingyong0423/go-mongox" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/aggregation" "/chenmingyong0423/go-mongox/types" "/mongo-driver/mongo" ) func main() { // You need to pre-create a * object mongoCollection := () // Create a collection using the Post structure as a generic parameter postCollection := [](mongoCollection) _, err := ().InsertMany((), []{ {Id: "1", Title: "go", Author: "Chen Mingyong", Content: "..."}, {Id: "2", Title: "mongo", Author: "Chen Mingyong", Content: "..."}, }) if err != nil { panic(err) } // Aggregation operation // - Use the aggregation package to construct pipeline posts, err := postCollection. Aggregator().Pipeline(().Project(("content", 0)).Build()). Aggregate(()) if err != nil { panic(err) } for _, post := range posts { (post) } // If we change the name of the field through the aggregation operation, then we can use the AggregationWithCallback method and then map the result to our expected structure via the callback function 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) // Rename the author field to name, exclude the content field, add outstanding field, and return the result as []*DiffPost err = (). Pipeline(().Project( (("name", "$author"), ("author", 1), ("_id", 1), ("title", 1), ("outstanding", ().Eq("$author", "Chen Mingyong").Build()))).Build(), ). AggregateWithCallback((), func(ctx , cursor *) error { return (ctx, &result) }) for _, post := range result { (post) } }
based onpostCollection
Instance, we can useAggregator()
Method creates an aggregator and then performs an aggregation operation.
We can passPipeline
andAggregateOptions
Methods are set separatelypipeline
andoptions
Parameters.
For performing an aggregation operation, there are two methods:
-
Aggregate
Method: With officialAPI
The same name. -
AggregateWithCallback
Method: Because we are creatingcollection
When decorator, a structure is bound by using generics. If after performing the aggregation operation, the returned data cannot be mapped to the bound structure, you can use this method to map the result to the specified structure.
Builder constructor
go-mongox
The framework provides the following types of constructors:
-
universal
: Simple and universalbson
Data constructor. -
query
: Query constructor, used to construct the required query operationsbson
data. -
update
: Update constructor, used to construct the required update operationbson
data. -
aggregation
: Aggregation operation constructor, including two types, one is used to construct aggregationstage
What is required in the stagebson
The other type of data is used for construction in addition tostage
Outside the stagebson
data.
universal construction
We can usebsonx
Some functions in the package are performedbson
Data structure, for example、
and
etc.
// /chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/ package main import ( "fmt" "/chenmingyong0423/go-mongox/bsonx" ) func main() { // {"Name": "Chen Mingyong"} m := ("Name", "Chen Mingyong") ("%#v\n\n", m) // {"_id": "Chen Mingyong"} id := ("Chen Mingyong") ("%#v\n\n", id) // {{Key:"Name", Value:"Chen Mingyong"}, {Key:"Cell phone number", Value:"1888***1234"}} d := (("Name", "Chen Mingyong"), ("Phone number", "1888***1234")) ("%#v\n\n", d) // {Key:"Name", Value:"Chen Mingyong"} e := ("Name", "Chen Mingyong") ("%#v\n\n", e) // {"Chen Mingyong", "1888***1234"} a := ("Chen Mingyong", "1888***1234") ("%#v", a) }
bsonx
The package provides these constructors temporarily, and more useful functions will be added later.
Pay special attention to usingWhen constructing data, the parameters passed in need to be used
The method is passed on, with the purpose of strong constraints
key-value
Type of .
query query constructor
query
Package can help us construct query-relatedbson
Data, for example$in
、$gt
、$and
etc.
// /chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/ package main import ( "fmt" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/query" ) func main() { // {{Key:"Name", Value:"Chen Mingyong"}} d := ().Add(("Name", "Chen Mingyong")).Build() ("%#v\n\n", d) // {{Key:"age", Value:{{Key:"$gt", Value:18}, {Key:"$lt", Value:25}}}} d = ().Gt("age", 18).Lt("age", 25).Build() ("%#v\n\n", d) // {{Key:"age", Value:{{Key:"$in", Value:[]int{18, 19, 20}}}}} d = ().InInt("age", 18, 19, 20).Build() ("%#v\n\n", d) // {{Key: "$and", Value: []any{{{Key: "x", Value: {{Key: "$ne", Value: 0}}}}, {{Key: "y", Value: {{Key: "$gt", Value: 0}}}}}} d = ().And( ().Ne("x", 0).Build(), ().Gt("y", 0).Build(), ).Build() ("%#v\n\n", d) // {{Key:"qty", Value:{{Key:"$exists", Value:true}, {Key:"$nin", Value:[]int{5, 15}}}}} d = ().Exists("qty", true).NinInt("qty", 5, 15).Build() ("%#v\n\n", d) // elemMatch // {{Key: "result", Value: {{Key: "$elemMatch", Value: {{Key: "$gte", Value: 80}, {Key: "$lt", Value: 85}}}}}} d = ().ElemMatch("result", (("$gte", 80), ("$lt", 85))).Build() ("%#v", d) }
query
The package provides more than these methods. The above is just a list of typical examples, and there are more usages waiting for you to explore.
update update constructor
update
Package can help us construct update operations relatedbson
Data, for example$set
、$$inc
、$push
etc.
// /chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/ package main import ( "fmt" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/update" ) func main() { // {{Key:"$set", Value:{"name":"Chen Mingyong"}}} u := ().Set(("name", "Chen Mingyong")).Build() ("%#v\n\n", u) // {{Key:"$inc", Value:{{Key:"orders", Value:1}, {Key:"ratings", Value:-1}}}} u = ().Inc((("orders", 1), ("ratings", -1))).Build() ("%#v\n\n", u) // {{Key:"$push", Value:{"scores":95}}} u = ().Push(("scores", 95)).Build() ("%#v\n\n", u) // {{Key:"$unset", Value:{{Key:"quantity", Value:""}, {Key:"instock", Value:""}}}} u = ().Unset("quantity", "instock").Build() ("%#v", u) }
update
The package provides more than these methods. The above is just a list of typical examples, and there are more usages waiting for you to explore.
aggregation aggregation constructor
aggregation
The package provides twobuilder
:
-
StageBsonBuilder
: used for constructionstage
What is required in the stagebson
data -
BsonBuilder
: used in structure in addition tostage
Outside the stagebson
data.
// /chenmingyong0423/blog/blob/master/tutorial-code/go-mongox/builder/ package main import ( "fmt" "/chenmingyong0423/go-mongox/bsonx" "/chenmingyong0423/go-mongox/builder/aggregation" "/chenmingyong0423/go-mongox/builder/query" "/chenmingyong0423/go-mongox/types" ) func main() { // {{Key:"$gt", Value:[]any{"$qty", 250}}} gt := ().Gt("$qty", 250).Build() ("%#v\n\n", gt) // {{{Key:"$project", Value:{{Key:"name", Value:1}, {Key:"age", Value:1}, {Key:"qtyGt250", Value:{{Key:"$gt", Value:[]interface {}{"$qty", 250}}}}}}}} pipeline := ().Project((("name", 1), ("age", 1), ("qtyGt250", gt))).Build() ("%#v\n\n", pipeline) // {{Key:"$or", Value:[]interface {}{{{Key:"score", Value:{{Key:"$gt", Value:70}, {Key:"$lt", Value:90}}}}, {{Key:"views", Value:{{Key:"$gte", Value:90}}}}}}} or := ().Or( ().Gt("score", 70).Lt("score", 90).Build(), ().Gte("views", 90).Build(), ).Build() ("%#v\n\n", or) // {{{Key:"$match", Value:{{Key:"$or", Value:[]any{{{Key:"score", Value:{{Key:"$gt", Value:70}, {Key:"$lt", Value:90}}}}, {{Key:"views", Value:{{Key:"$gte", Value:90}}}}}}}}}, {{Key:"$group", Value:{{Key:"_id", Value:any(nil)}, {Key:"count", Value:{{Key:"$sum", Value:1}}}}}}} pipeline = ().Match(or).Group(nil, ("count", ().Sum(1).Build())).Build() ("%#v\n\n", pipeline) // {{{Key:"$unwind", Value:"$size"}}} pipeline = ().Unwind("$size", nil).Build() ("%#v\n\n", pipeline) // {{{Key:"$unwind", Value:{{Key:"path", Value:"$size"}, {Key:"includeArrayIndex", Value:"arrayIndex"}, {Key:"preserveNullAndEmptyArrays", Value:true}}}}} pipeline = ().Unwind("$size", &{ IncludeArrayIndex: "arrayIndex", PreserveNullAndEmptyArrays: true, }).Build() ("%#v", pipeline) }
aggregation
The package provides more than these methods. The above is just a list of typical examples, and there are more usages waiting for you to explore.
summary
This article is aboutgo-mongox
The framework has been introduced in detail. It has two cores, one is based on generics.colletion
The other form isbson
The constructor is here. These two cores exist separately, you can use one of them or both.
Warehouse address:/chenmingyong0423/go-mongox
The framework is in its early stages. We hope to invite all developers to participate in the brainstorming way, put forward valuable suggestions and opinions, and jointly create a stronger and more flexible framework. Looking forward to your active participation and valuable feedback to promote it togethergo-mongox
Continuous progress.
The above is the detailed content of go mongox's simple and efficient document operation and smooth bson data construction techniques. For more information about go mongox's document operation bson structure, please pay attention to my other related articles!