golang官方MongoDB数据库驱动插件库mongo-go-driver的使用

Golang官方MongoDB数据库驱动插件库mongo-go-driver的使用

MongoDB Gopher

MongoDB官方支持的Go语言驱动程序。

要求

  • Go 1.19或更高版本。我们旨在支持Go的最新版本。
  • 运行驱动程序测试套件需要Go 1.23或更高版本。
  • MongoDB 4.0及更高版本。

安装

推荐使用Go模块在项目中安装依赖:

go get go.mongodb.org/mongo-driver/v2/mongo

使用示例

基本连接

import (
    "context"
    "time"

    "go.mongodb.org/mongo-driver/v2/mongo"
    "go.mongodb.org/mongo-driver/v2/mongo/options"
    "go.mongodb.org/mongo-driver/v2/mongo/readpref"
)

// 创建客户端连接
client, _ := mongo.Connect(options.Client().ApplyURI("mongodb://localhost:27017"))

// 确保断开连接
defer func() {
    if err = client.Disconnect(ctx); err != nil {
        panic(err)
    }
}()

// 检查连接
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

_ = client.Ping(ctx, readpref.Primary())

插入文档

import (
    "go.mongodb.org/mongo-driver/v2/bson"
)

// 获取集合
collection := client.Database("testing").Collection("numbers")

// 插入文档
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

res, _ := collection.InsertOne(ctx, bson.D{{"name", "pi"}, {"value", 3.14159}})
id := res.InsertedID

查询文档

// 查询多个文档
ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

cur, err := collection.Find(ctx, bson.D{})
if err != nil {
    log.Fatal(err)
}

defer cur.Close(ctx)
for cur.Next(ctx) {
    var result bson.D
    if err := cur.Decode(&result); err != nil {
        log.Fatal(err)
    }
    // 处理结果...
}

if err := cur.Err(); err != nil {
    log.Fatal(err)
}

// 查询单个文档
var result struct {
    Value float64
}

filter := bson.D{{"name", "pi"}}
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

err = collection.FindOne(ctx, filter).Decode(&result)
if errors.Is(err, mongo.ErrNoDocuments) {
    // 没有找到记录的处理
} else if err != nil {
    log.Fatal(err)
}

网络压缩

网络压缩可以减少MongoDB和应用程序之间的带宽需求。Go驱动程序支持以下压缩算法:

  1. Snappy (snappy): MongoDB 3.4及更高版本可用
  2. Zlib (zlib): MongoDB 3.6及更高版本可用
  3. Zstandard (zstd): MongoDB 4.2及更高版本可用

可以通过连接字符串参数或使用ClientOptions.SetCompressors启用压缩:

// 通过连接字符串设置压缩
opts := options.Client().ApplyURI("mongodb://localhost:27017/?compressors=snappy,zlib,zstd")
client, _ := mongo.Connect(opts)

// 或通过ClientOptions设置
opts := options.Client().SetCompressors([]string{"snappy", "zlib", "zstd"})
client, _ := mongo.Connect(opts)

完整示例

package main

import (
    "context"
    "errors"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/v2/bson"
    "go.mongodb.org/mongo-driver/v2/mongo"
    "go.mongodb.org/mongo-driver/v2/mongo/options"
    "go.mongodb.org/mongo-driver/v2/mongo/readpref"
)

func main() {
    // 创建客户端连接
    client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        log.Fatal(err)
    }

    // 确保断开连接
    defer func() {
        if err = client.Disconnect(context.TODO()); err != nil {
            log.Fatal(err)
        }
    }()

    // 检查连接
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    
    if err := client.Ping(ctx, readpref.Primary()); err != nil {
        log.Fatal(err)
    }

    // 获取集合
    collection := client.Database("test").Collection("numbers")

    // 插入文档
    ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    res, err := collection.InsertOne(ctx, bson.D{{"name", "pi"}, {"value", 3.14159}})
    if err != nil {
        log.Fatal(err)
    }
    log.Println("Inserted ID:", res.InsertedID)

    // 查询文档
    var result struct {
        Value float64 `bson:"value"`
    }
    
    filter := bson.D{{"name", "pi"}}
    ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    
    err = collection.FindOne(ctx, filter).Decode(&result)
    if errors.Is(err, mongo.ErrNoDocuments) {
        log.Println("No document found")
    } else if err != nil {
        log.Fatal(err)
    }
    
    log.Println("Found value:", result.Value)
}

反馈与贡献

  • 获取帮助请访问MongoDB社区论坛
  • 报告新功能和错误请访问JIRA项目页面
  • 贡献指南请参考项目文档

更多关于golang官方MongoDB数据库驱动插件库mongo-go-driver的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang官方MongoDB数据库驱动插件库mongo-go-driver的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用mongo-go-driver操作MongoDB

mongo-go-driver是MongoDB官方提供的Go语言驱动程序,提供了全面的MongoDB操作功能。下面我将介绍其基本用法和常见操作示例。

安装

首先安装mongo-go-driver:

go get go.mongodb.org/mongo-driver/mongo

基本连接

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readpref"
)

func main() {
	// 设置连接选项
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
	
	// 连接到MongoDB
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		log.Fatal(err)
	}
	
	// 检查连接
	err = client.Ping(ctx, readpref.Primary())
	if err != nil {
		log.Fatal(err)
	}
	
	fmt.Println("Connected to MongoDB!")
	
	// 断开连接
	defer func() {
		if err = client.Disconnect(ctx); err != nil {
			log.Fatal(err)
		}
	}()
}

CRUD操作

1. 插入文档

type Person struct {
	Name    string
	Age     int
	City    string
	Hobbies []string
}

// 获取集合
collection := client.Database("testdb").Collection("people")

// 插入单个文档
person := Person{"张三", 30, "北京", []string{"游泳", "读书"}}
insertResult, err := collection.InsertOne(ctx, person)
if err != nil {
	log.Fatal(err)
}
fmt.Println("Inserted a single document: ", insertResult.InsertedID)

// 插入多个文档
persons := []interface{}{
	Person{"李四", 25, "上海", []string{"跑步", "音乐"}},
	Person{"王五", 28, "广州", []string{"旅游", "摄影"}},
}
insertManyResult, err := collection.InsertMany(ctx, persons)
if err != nil {
	log.Fatal(err)
}
fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)

2. 查询文档

// 查询单个文档
var result Person
err = collection.FindOne(ctx, bson.M{"name": "张三"}).Decode(&result)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Found a single document: %+v\n", result)

// 查询多个文档
cursor, err := collection.Find(ctx, bson.M{"age": bson.M{"$gt": 25}})
if err != nil {
	log.Fatal(err)
}
defer cursor.Close(ctx)

var people []Person
if err = cursor.All(ctx, &people); err != nil {
	log.Fatal(err)
}
fmt.Println("Found multiple documents:")
for _, p := range people {
	fmt.Printf("%+v\n", p)
}

3. 更新文档

// 更新单个文档
filter := bson.M{"name": "张三"}
update := bson.M{
	"$set": bson.M{
		"age": 31,
		"city": "深圳",
	},
}
updateResult, err := collection.UpdateOne(ctx, filter, update)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Matched %v documents and updated %v documents.\n", 
	updateResult.MatchedCount, updateResult.ModifiedCount)

// 更新多个文档
updateManyResult, err := collection.UpdateMany(
	ctx,
	bson.M{"age": bson.M{"$gt": 25}},
	bson.M{"$inc": bson.M{"age": 1}},
)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Matched %v documents and updated %v documents.\n", 
	updateManyResult.MatchedCount, updateManyResult.ModifiedCount)

4. 删除文档

// 删除单个文档
deleteResult, err := collection.DeleteOne(ctx, bson.M{"name": "王五"})
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Deleted %v documents\n", deleteResult.DeletedCount)

// 删除多个文档
deleteManyResult, err := collection.DeleteMany(ctx, bson.M{"age": bson.M{"$gt": 30}})
if err != nil {
	log.Fatal(err)
}
fmt.Printf("Deleted %v documents\n", deleteManyResult.DeletedCount)

高级操作

事务

session, err := client.StartSession()
if err != nil {
	log.Fatal(err)
}
defer session.EndSession(ctx)

err = mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error {
	if err = session.StartTransaction(); err != nil {
		return err
	}
	
	// 执行事务操作
	if _, err = collection.InsertOne(sc, Person{"赵六", 35, "杭州", nil}); err != nil {
		session.AbortTransaction(sc)
		return err
	}
	
	if _, err = collection.UpdateOne(
		sc,
		bson.M{"name": "张三"},
		bson.M{"$set": bson.M{"age": 32}},
	); err != nil {
		session.AbortTransaction(sc)
		return err
	}
	
	return session.CommitTransaction(sc)
})

if err != nil {
	log.Fatal(err)
}

聚合查询

matchStage := bson.D{{"$match", bson.D{{"age", bson.D{{"$gt", 25}}}}}}
groupStage := bson.D{
	{"$group", bson.D{
		{"_id", "$city"},
		{"total", bson.D{{"$sum", 1}}},
		{"averageAge", bson.D{{"$avg", "$age"}}},
	}},
}

cursor, err := collection.Aggregate(ctx, mongo.Pipeline{matchStage, groupStage})
if err != nil {
	log.Fatal(err)
}
defer cursor.Close(ctx)

var results []bson.M
if err = cursor.All(ctx, &results); err != nil {
	log.Fatal(err)
}
for _, result := range results {
	fmt.Printf("City: %v, Count: %v, Avg Age: %v\n", 
		result["_id"], result["total"], result["averageAge"])
}

最佳实践

  1. 连接池管理:客户端会自动管理连接池,通常一个应用只需要一个客户端实例
  2. 上下文使用:所有操作都应使用context来控制超时和取消
  3. BSON处理:使用bson标签定义结构体字段与MongoDB字段的映射关系
  4. 错误处理:检查所有操作返回的错误
  5. 资源释放:确保关闭游标和会话等资源

mongo-go-driver提供了丰富的功能,可以满足大多数MongoDB操作需求。更多高级用法可以参考官方文档。

回到顶部