Golang"驱动"MongoDB-快速入门("快码加鞭")

网友投稿 793 2022-11-03

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

Golang"驱动"MongoDB-快速入门("快码加鞭")

背景:  2019年3月,MongoDB官方Golang驱动已经正式发布V1.0.0 GA版本(GenerallyAvailable),本篇为MongoDB-Go驱动快速入门代码示例,包含以下主要内容:

MongoDB Go驱动安装使用Go驱动连接MongoDB在Go中使用BSON对象MongoDB CRUD(增删改查)操作

准备: 本地运行MongoDB数据库或者使用MongoDB Atlas创建免费创建500MB在线数据库(https://mongodb.com/cloud/atlas/register)

MongoDB Go驱动安装

该驱动由多个go包组成,在go项目中,你可以使用以下命令安装驱动

go get go.mongodb.org/mongo-driver

创建代码框架

创建main.go文件,导入bson, mongo, mongo/options包

package mainimport ( "context" "fmt" "log" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options")// You will be using this Trainer type later in the program, 下面申明Trainer"教练员"结构体type Trainer struct { Name string Age int City string}func main() { // Rest of the code will go here 这里先占位}

使用Go驱动连接MongoDB

导入依赖包后,你可以使用mongo.Connect()方法连接数据库.该方法必须传入一个上下文context对象和选项options.ClientOptions对象,该选项可用于设置连接字符串, 写策略write concerns, 套接字超时socket timeouts等参数,更多选项请参考文档:https://godoc.org/go.mongodb.org/mongo-driver/mongo/options

在主函数func main()中添加以下代码:

// Set client options 设置客户端选项,如这里的连接字符串clientOptions := options.Client().ApplyURI("mongodb://data:27017")// Connect to MongoDB 连接数据库,返回客户端对象clientclient, err := mongo.Connect(context.TODO(), clientOptions)if err != nil { log.Fatal(err)}// Check the connection 连通性检查err = client.Ping(context.TODO(), nil)if err != nil { log.Fatal(err)}fmt.Println("Connected to MongoDB!")

连通性检查通过后,添加如下代码,得到一个关于test数据库和trainers集合的控制器handler,下面的案例都会使用到这个控制器对象

collection := client.Database("test").Collection("trainers")

注意: 最佳实践是使用连接池,可以不用频繁关闭连接,每个查询复用连接池中的连接即可,当然在你不使用查询时,你也可以手动执行以下代码关闭连接(必要,防止内存泄漏)

err = client.Disconnect(context.TODO())if err != nil { log.Fatal(err)}fmt.Println("Connection to MongoDB closed.")

在Go中使用BSON对象

BSON对象Binary-encoded JSON(以二进制编码的JSON对象),是存储在MongoDB中的二进制格式的JSON文档对象.不像其他数据库将JSON数据存储为字符串和数字.BSON对象扩展了JSON类型,如整型int,长整型long,日期date,浮点数指针floating point,小数decimal128, 这些使得数据排序和比较更容易.Go驱动有两种BSON数据对象,D类型和Raw类型.

D类型"家族"使用原生Go类型构建BSON对象,常用于构造MongoDB命令,D家族包含以下四种类型:

D: 一个BSON文档,该类型应该用于有序数据的场景,如MongoDB命令M: 一个非排序的映射map,除了保护排序之外,其他和D类型一致A:  一个BSON数组E:  属于D类型中内嵌的一个单一元素single element

下面是一个D类型的过滤文档filter document,可用于查找name字段是Alice或者Bob的文档:

bson.D{{ "name", bson.D{{ "$in", bson.A{"Alice", "Bob"} }}}}

Raw家族用于验证字节切片[]bytes, 使用Lookup()方法可以从Raw中查询单个元素.Raw适用于不需要频繁的将BSON反序列化为其他类型的场景, 所以本篇咱们都是使用的D类型.

CRUD增删改查操作

插入文档

//插入文档,首先创建多个教练员结构体ash := Trainer{"Ash", 10, "Pallet Town"}misty := Trainer{"Misty", 10, "Cerulean City"}brock := Trainer{"Brock", 15, "Pewter City"}//使用InsertOne方法插入单个文档insertResult, err := collection.InsertOne(context.TODO(), ash)if err != nil { log.Fatal(err)}fmt.Println("Inserted a single document: ", insertResult.InsertedID)//使用InsertMany插入多个文档,该方法接收教练员切片作为参数trainers := []interface{}{misty, brock}insertManyResult, err := collection.InsertMany(context.TODO(), trainers)if err != nil { log.Fatal(err)}fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)

更新文档

//需要先构造一个匹配文档的D对象filter := bson.D{{"name", "Ash"}}//inc为递增,这里将名为Ash的教练员年龄+1update := bson.D{ {"$inc", bson.D{ {"age", 1}, }},}updateResult, err := collection.UpdateOne(context.TODO(), filter, update)if err != nil { log.Fatal(err)}fmt.Printf("Matched %v documents and updated %v documents.\n", updateResult.MatchedCount, updateResult.ModifiedCount)

查找单个文档

//查找文档// create a value into which the result can be decoded 需要先申明一个教练员结构var result Trainer//FindOne方法接收一个过滤器对象,依然使用上面的Ash教练员,然后将查询结果解码到一个可解码的对象地址(指针类型)err = collection.FindOne(context.TODO(), filter).Decode(&result)if err != nil { log.Fatal(err)}fmt.Printf("Found a single document: %+v\n", result)

查找多个文档

//查找多个文档// Pass these options to the Find methodfindOptions := options.Find()findOptions.SetLimit(2) //设置查询结果限制为2个// Here's an array in which you can store the decoded documents 申明结果为一个教练员切片指针var results []*Trainer// Passing bson.D{{}} as the filter matches all documents in the collection, 查询后得到一个游标对象curcur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions)if err != nil { log.Fatal(err)}// Finding multiple documents returns a cursor// Iterating through the cursor allows us to decode documents one at a time 遍历游标对象for cur.Next(context.TODO()) { // create a value into which the single document can be decoded var elem Trainer err := cur.Decode(&elem) if err != nil { log.Fatal(err) } results = append(results, &elem) //将单个查询结果添加到教练员切片中}if err := cur.Err(); err != nil { log.Fatal(err)}// Close the cursor once finished 游标用完后需要关闭,防止内存泄漏cur.Close(context.TODO())fmt.Printf("Found multiple documents (array of pointers): %+v\n", results)

删除单个文档

//删除单个对象使用collection.DeleteOne(),如删除Ash教练员deleteOneResult, err := collection.DeleteOne(context.TODO(), filter)if err != nil { log.Fatal(err)}fmt.Printf("Deleted %v documents in the trainers collection\n", deleteOneResult.DeletedCount)

删除多个文档

//DeleteMany删除多个文档,空D对象bson.D{{}}作为过滤参数表示删除所有文档集, 也可以使用collection.Drop()删除整个文档集合deleteResult, err := collection.DeleteMany(context.TODO(), bson.D{{}})if err != nil { log.Fatal(err)}fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult.DeletedCount)

最后记得关闭连接

//最后记得关闭连接,防止内存泄漏err = client.Disconnect(context.TODO())if err != nil { log.Fatal(err)}fmt.Println("Connection to MongoDB closed.")

完整代码请参考:https://github.com/tfogo/mongodb-go-tutorial

或:

package mainimport ( "context" "fmt" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "log")// You will be using this Trainer type later in the program, 下面申明Trainer"教练员"结构体type Trainer struct { Name string Age int City string}func main() { // Rest of the code will go here 这里先占位 Set client options 设置客户端选项,如这里的连接字符串 clientOptions := options.Client().ApplyURI("mongodb://data:27017") // Connect to MongoDB 连接数据库,返回客户端对象client client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } // Check the connection 连通性检查 err = client.Ping(context.TODO(), nil) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") collection := client.Database("test").Collection("trainers") //bson.D{{ "name", bson.D{{ "$in", bson.A{"Alice", "Bob"} }} }} 插入文档,首先创建多个教练员结构体 ash := Trainer{"Ash", 10, "Pallet Town"} misty := Trainer{"Misty", 10, "Cerulean City"} brock := Trainer{"Brock", 15, "Pewter City"} //使用InsertOne方法插入单个文档 insertResult, err := collection.InsertOne(context.TODO(), ash) if err != nil { log.Fatal(err) } fmt.Println("Inserted a single document: ", insertResult.InsertedID) //使用InsertMany插入多个文档,该方法接收教练员切片作为参数 trainers := []interface{}{misty, brock} insertManyResult, err := collection.InsertMany(context.TODO(), trainers) if err != nil { log.Fatal(err) } fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs) //更新文档 需要先构造一个匹配文档的D对象 filter := bson.D{{"name", "Ash"}} //inc为递增,这里将名为Ash的教练员年龄+1 update := bson.D{ {"$inc", bson.D{ {"age", 1}, }}, } updateResult, err := collection.UpdateOne(context.TODO(), filter, update) if err != nil { log.Fatal(err) } fmt.Printf("Matched %v documents and updated %v documents.\n", updateResult.MatchedCount, updateResult.ModifiedCount) //查找文档 create a value into which the result can be decoded 需要先申明一个教练员结构 var result Trainer //FindOne方法接收一个过滤器对象,依然使用上面的Ash教练员,然后将查询结果解码到一个可解码的对象地址(指针类型) err = collection.FindOne(context.TODO(), filter).Decode(&result) if err != nil { log.Fatal(err) } fmt.Printf("Found a single document: %+v\n", result) //查找多个文档 Pass these options to the Find method findOptions := options.Find() findOptions.SetLimit(2) //设置查询结果限制为2个 Here's an array in which you can store the decoded documents 申明结果为一个教练员切片指针 var results []*Trainer // Passing bson.D{{}} as the filter matches all documents in the collection, 查询后得到一个游标对象cur cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions) if err != nil { log.Fatal(err) } // Finding multiple documents returns a cursor Iterating through the cursor allows us to decode documents one at a time 遍历游标对象 for cur.Next(context.TODO()) { // create a value into which the single document can be decoded var elem Trainer err := cur.Decode(&elem) if err != nil { log.Fatal(err) } results = append(results, &elem) //将单个查询结果添加到教练员切片中 } if err := cur.Err(); err != nil { log.Fatal(err) } // Close the cursor once finished 游标用完后需要关闭,防止内存泄漏 cur.Close(context.TODO()) fmt.Printf("Found multiple documents (array of pointers): %+v\n", results) //删除文档 删除单个对象使用collection.DeleteOne(),如删除Ash教练员 deleteOneResult, err := collection.DeleteOne(context.TODO(), filter) if err != nil { log.Fatal(err) } fmt.Printf("Deleted %v documents in the trainers collection\n", deleteOneResult.DeletedCount) //DeleteMany删除多个文档,空D对象bson.D{{}}作为过滤参数表示删除所有文档集, 也可以使用collection.Drop()删除整个文档集合 deleteResult, err := collection.DeleteMany(context.TODO(), bson.D{{}}) if err != nil { log.Fatal(err) } fmt.Printf("Deleted %v documents in the trainers collection\n", deleteResult.DeletedCount) //最后记得关闭连接,防止内存泄漏 err = client.Disconnect(context.TODO()) if err != nil { log.Fatal(err) } fmt.Println("Connection to MongoDB closed.")}

更多文档

MongoDB Go驱动官方文档GoDoc:

https://godoc.org/go.mongodb.org/mongo-driver

其他查询,如聚合Aggregate:https://godoc.org/go.mongodb.org/mongo-driver/mongo#Collection.Aggregate

会话Session:https://godoc.org/go.mongodb.org/mongo-driver/mongo#Session

相关资源

MongoDB Go Driver Tutorial: https://mongodb.com/blog/post/mongodb-go-driver-tutorial

Golang and MongoDB: https://mongodb.com/golang

END-已结束

上一篇:软件测试培训之安装测试
下一篇:软件测试培训之客户端测试注意点
相关文章

 发表评论

暂时没有评论,来抢沙发吧~