如何使用Go语言和MongoDB
MongoDB是一个开源的NoSQL数据库。它是一个文档导向的数据库,使用类似JSON的结构称为BSON来存储文档(即键值对)。MongoDB提供了集合的概念来对文档进行分组。在本文中,我们将讨论如何使用Golang连接MongoDB。
先决条件: 您需要安装MongoDB,并在默认端口(即27017)上启动它。
安装: 包mongo为Go提供了一个MongoDB Driver API,可用于与MongoDB API交互。使用以下命令安装mongo包。
go get go.mongodb.org/mongo-driver/mongo
包上下文(context): 上下文包是一个包含截止时间、取消信号和其他请求范围的值的上下文类型,可以跨API边界和进程之间传递。
连接Go驱动MongoDB
现在,要连接Go驱动MongoDB,您需要按照以下步骤操作:
- 使用mongo.Connect函数创建mongo.Client。mongo.Client处理与MongoDB的连接。
- mongo.Client具有称为Ping的方法,成功连接后返回pong。
- 最后,使用mongo.Client.Disconnect关闭数据库连接。
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
// 这是一个用户定义的关闭资源的方法。
// 此方法关闭mongoDB连接并取消上下文。
func close(client *mongo.Client, ctx context.Context,
cancel context.CancelFunc){
// 取消上下文的CancelFunc
defer cancel()
// client提供关闭mongoDB连接的方法。
defer func(){
// client.Disconnect方法也有截止时间。
// 返回错误信息,如果有的话。
if err := client.Disconnect(ctx); err != nil{
panic(err)
}
}()
}
// 这是一个用户定义的方法,返回mongo.Client、context.Context、context.CancelFunc和error。
// mongo.Client将用于进一步的数据库操作。
// context.Context将用于为过程设置截止时间。
// context.CancelFunc将用于取消上下文和与其关联的资源。
func connect(uri string)(*mongo.Client, context.Context,
context.CancelFunc, error) {
// 上下文将用于为过程设置截止时间,这里
// 截止时间将为30秒。
ctx, cancel := context.WithTimeout(context.Background(),
30 * time.Second)
// mongo.Connect返回mongo.Client方法
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
return client, ctx, cancel, err
}
// 这是一个用户定义的方法,接受mongo.Client和context.Context。
// 该方法用于对mongoDB进行ping,如果有任何错误就返回错误信息。
func ping(client *mongo.Client, ctx context.Context) error{
// mongo.Client具有用于ping mongoDB的Ping方法,Ping方法截止时间将由cxt确定
// 如果出现错误,则Ping方法返回错误,然后可以处理该错误。
if err := client.Ping(ctx, readpref.Primary()); err != nil {
return err
}
fmt.Println("连接成功")
return nil
}
func main(){
// 从connect方法获取Client、Context、CancelFunc和
// err信息。
client, ctx, cancel, err := connect("mongodb://localhost:27017")
if err != nil
{
panic(err)
}
// 当主函数被返回时,释放资源。
defer close(client, ctx, cancel)
// 使用Ping方法ping mongoDB。
ping(client, ctx)
}
输出:
插入文档
要插入文档,您需要遵循以下步骤:
- 使用mongo.Connect函数创建mongo.Client。mongo.Client处理与MongoDB的连接。
- mongo.Client。Database返回指向数据库的指针类型。
- 指向数据库的指针具有集合选择集合以使用的方法。
- 集合类型提供了两种将文档插入MongoDB的方法。
- 即 Collection.InsertOne() 方法可以将一个文档插入到数据库中。
- 即 Collection.InsertMany() 方法可以插入文档列表。
- 最后使用mongo.Client.Disconnect关闭数据库连接。
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
//这是一个自定义的方法,用于关闭资源。
//此方法关闭mongoDB连接并取消context。
func close(client *mongo.Client, ctx context.Context,
cancel context.CancelFunc){
defer cancel()
defer func() {
if err := client.Disconnect(ctx); err != nil {
panic(err)
}
}()
}
//这是一个用户定义的方法,返回mongo.Client、context.Context、context.CancelFunc和error。
//mongo.Client将用于进一步的数据库操作。
//context.Context将用于设置进程的最后期限。
//context.CancelFunc将用于取消context和关联的资源。
func connect(uri string)
(*mongo.Client, context.Context, context.CancelFunc, error) {
ctx, cancel := context.WithTimeout(context.Background(),
30 * time.Second)
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
return client, ctx, cancel, err
}
//insertOne是一个用户定义的方法,用于插入
//文档到集合中,返回InsertOne的结果
//和错误(如果有)。
func insertOne
(client *mongo.Client, ctx context.Context, dataBase, col string, doc interface{})
(*mongo.InsertOneResult, error) {
//使用Client.Database方法和Database.Collection方法选择数据库和集合
collection := client.Database(dataBase).Collection(col)
//InsertOne接受两个类型上下文的参数
//和空接口
result, err := collection.InsertOne(ctx, doc)
return result, err
}
//insertMany是一个用户定义的方法,用于插入
//文档到集合,返回InsertMany的结果和错误(如果有)。
func insertMany
(client *mongo.Client, ctx context.Context, dataBase, col string, docs []interface{})
(*mongo.InsertManyResult, error) {
//使用Client.Database方法和Database.Collection方法选择数据库和集合
collection := client.Database(dataBase).Collection(col)
//InsertMany接受两个类型上下文的参数
//和空接口
result, err := collection.InsertMany(ctx, docs)
return result, err
}
func main() {
//从connect方法获取Client、Context、CancelFunc和err。
client, ctx, cancel, err := connect("mongodb://localhost:27017")
if err != nil {
panic(err)
}
//在返回主要功能时释放资源。
defer close(client, ctx, cancel)
//创建一个interface类型的对象来存储
//bson值,我们将插入到数据库中。
var document interface{}
document = bson.D{
{"rollNo", 175},
{"maths", 80},
{"science", 90},
{"computer", 95},
}
//insertOne接受客户端、上下文、数据库
//名称集合名称和一个将插入集合的接口。
//insertOne返回一个错误和一个结果
//插入单个文档到集合中。
insertOneResult, err := insertOne(client, ctx, "gfg",
"marks", document)
//处理错误
if err != nil {
panic(err)
}
//打印文档的插入id,
//如果已插入则为真。
fmt.Println("InsertOne的结果")
fmt.Println(insertOneResult.InsertedID)
//现在将插入多个文档到
//集合。创建一个类型为slice的对象
//多个接口来存储文档
var documents []interface{}
//存储到interface列表中。
documents = []interface{}{
bson.D{
{"rollNo", 153},
{"maths", 65},
{"science", 59},
{"computer", 70},
},
bson.D{
{"rollNo", 162},
{"maths", 90},
{"science", 95},
{"computer", 98},
},
bson.D{
{"rollNo", 184},
{"maths", 70},
{"science", 75},
{"computer", 80},
},
}
//insertMany接受客户端、上下文、数据库
//名称和集合名称以及将插入的文档的interface切片。
//insertMany返回一个错误和InsertMany的结果。
insertManyResult, err := insertMany(client, ctx, "gfg",
"marks", documents)
//处理错误
if err != nil {
panic(err)
}
//打印插入文档的总数以及插入id的个数,
//如果已插入,则为真。
fmt.Println("InsertMany的结果")
fmt.Println("插入的文档总数为:", len(documents))
fmt.Println("插入的ID数量:", len(insertManyResult.InsertedIDs))
}
{
bson.D{
{"rollNo", 101},
{"maths", 75},
{"science", 80},
{"computer", 55},
},
bson.D{
{"rollNo", 162},
{"maths", 86},
{"science", 80},
{"computer", 69},
},
}
// insertMany insert a list of documents into
// the collection. insertMany accepts client,
// context, database name collection name
// and slice of interface. returns error
// if any and result of multi document insertion.
insertManyResult, err := insertMany(client, ctx, "gfg",
"marks", documents)
// handle the error
if err != nil {
panic(err)
}
fmt.Println("Result of InsertMany")
// print the insertion ids of the multiple
// documents, if they are inserted.
for id := range insertManyResult.InsertedIDs {
fmt.Println(id)
}
}
输出:
删除文档
要删除文档,需要按照以下步骤进行:
- 使用mongo.Connect函数创建mongo.Client。mongo.Client处理与MongoDB的连接。
- mongo.Client.Database返回指向数据库的指针类型。
- 数据库指针具有collection方法,可选择要使用的集合。
- 集合提供两种方法来删除集合中的文档。
- DeleteOne() 函数删除匹配查询的单个文档。
- DeleteMany() 函数删除与查询匹配的所有文档。
- 最后,使用mongo.Client.Disconnect关闭数据库连接。
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)
// This is a user defined method to close resources.
// This method closes mongoDB connection and cancel context.
func close(client *mongo.Client, ctx context.Context,
cancel context.CancelFunc) {
defer cancel()
defer func() {
if err := client.Disconnect(ctx); err != nil {
panic(err)
}
}()
}
// This is a user defined method that returns
// mongo.Client, context.Context,
//context.CancelFunc and error.
// mongo.Client will be used for further
// database operation. context.Context will be
// used set deadlines for process.
// context.CancelFunc will be used to cancel
// context and resource associated with it.
func connect(uri string) (*mongo.Client, context.Context,
context.CancelFunc, error) {
ctx, cancel := context.WithTimeout(context.Background(),
30 * time.Second)
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
return client, ctx, cancel, err
}
// deleteOne is a user defined function that delete,
// a single document from the collection.
// Returns DeleteResult and an error if any.
func deleteOne(client *mongo.Client, ctx context.Context,
dataBase, col string, query interface{})
(result *mongo.DeleteResult, err error) {
// select document and collection
collection := client.Database(dataBase).Collection(col)
// query is used to match a document from the collection.
result, err = collection.DeleteOne(ctx, query)
return
}
// deleteMany is a user defined function that delete,
// multiple documents from the collection.
// Returns DeleteResult and an error if any.
func deleteMany(client *mongo.Client, ctx context.Context,
dataBase, col string, query interface{})
(result *mongo.DeleteResult, err error) {
// select document and collection
collection := client.Database(dataBase).Collection(col)
// query is used to match documents from the collection.
result, err = collection.DeleteMany(ctx, query)
return
}
func main() {
// get Client, Context, CancelFunc and err from connect method.
client, ctx, cancel, err := connect("mongodb://localhost:27017")
if err != nil {
panic(err)
}
// free resource when main function is returned
defer close(client, ctx, cancel)
// This query delete document when the maths
// field is greater than 60
query := bson.D{
{"maths", bson.D{{"gt", 60}}},
}
// Returns result of deletion and error
result, err := deleteOne(client, ctx, "gfg", "marks", query)
// print the count of affected documents
fmt.Println("No.of rows affected by DeleteOne()")
fmt.Println(result.DeletedCount)
// This query deletes documents that has
// science field greater that 0
query = bson.D{
{"science", bson.D{{"gt", 0}}},
}
// Returns result of deletion and error
result, err = deleteMany(client, ctx, "gfg", "marks", query)
// print the count of affected documents
fmt.Println("No.of rows affected by DeleteMany()")
fmt.Println(result.DeletedCount)
}
输出:
图 1.5
替换文档
要替换文档,您需要按照以下步骤进行:
- 使用mongo.Connect函数创建mongo.Client。mongo.Client处理与MongoDB的连接。
- mongo.Client.Database返回一个指向数据库的指针类型。
- 数据库指针具有用于选择要使用的集合的collection方法。
- 集合提供了一种方法来替换集合中的文档。
ReplaceOne() 函数替换匹配查询的单个文档。 - 最后使用mongo.Client.Disconnect来关闭数据库连接。
/*
ReplaceOne()函数将除了_id外的所有现有字段替换为指定的字段和值。
如果多个文档与传递给ReplaceOne()的查询过滤器匹配,则该方法选择并替换
第一个匹配的文档。如果没有文档与查询过滤器匹配,则替换操作失败。
*/
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// 这是一个用户定义的方法,用于关闭资源。
// 该方法关闭mongoDB连接和取消上下文。
func close(client *mongo.Client, ctx context.Context,
cancel context.CancelFunc) {
defer cancel()
defer func() {
if err := client.Disconnect(ctx); err != nil {
panic(err)
}
}()
}
// 这是一个用户定义的方法,用于返回mongo.Client、context.Context、
// context.CancelFunc和错误。
// mongo.Client将用于后续的数据库操作。
// context.Context将用于设置流程的截止日期。
// context.CancelFunc将用于取消上下文和与之相关联的资源。
func connect(uri string) (*mongo.Client, context.Context,
context.CancelFunc, error) {
ctx, cancel := context.WithTimeout(context.Background(),
30*time.Second)
client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
return client, ctx, cancel, err
}
func main() {
// 从connect方法获取Client、Context、CancelFunc和err。
uri := "mongodb://localhost:27017"
client, ctx, cancel, err := connect(uri)
if err != nil {
panic(err)
}
// 当主函数返回时释放资源
defer close(client, ctx, cancel)
// 选择数据库和集合
collection := client.Database("dataBase").Collection("col")
// 用于选择要替换的文档的过滤对象。
filter := bson.D{{"subjectId", 5}}
//替换文档
replacementDoc := bson.D{{"subjectId", 1}, {"subject", "数学"}}
//返回替换文档的结果和错误
result, err := collection.ReplaceOne(ctx, filter, replacementDoc)
//处理错误
if err != nil {
panic(err)
}
//打印受影响的文档数量
fmt.Println("No:of documents replaced")
fmt.Println(result.ModifiedCount)
}