驱动安装
bash
复制代码
go get go.mongodb.org/mongo-driver/mongo
基础连接示例
go
复制代码
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
// 设置客户端选项
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017").SetConnectTimeout(10 * time.Second)
// 连接MongoDB
client, err := mongo.Connect(context.Background(), clientOptions)
if err != nil {
log.Fatal(err)
}
defer func() {
if err = client.Disconnect(context.Background()); err != nil {
log.Fatal(err)
}
}()
fmt.Println("成功连接到MongoDB!")
}
标题数据库操作
- 创建数据库和集合
go
复制代码
db := client.Database("mydb")
usersColl := db.Collection("users")
- 文档定义(结构体)
go
复制代码
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Username string `bson:"username" json:"username"`
Email string `bson:"email" json:"email"`
CreatedAt time.Time `bson:"createdAt" json:"created_at"`
}
CRUD操作
- 插入文档
go
复制代码
insertResult, err := usersColl.InsertOne(
context.Background(),
User{
Username: "john_doe",
Email: "[email protected]",
CreatedAt: time.Now(),
},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("插入ID: %v\n", insertResult.InsertedID)
- 查询文档
go
复制代码
filter := bson.D{{"username", "john_doe"}}
var results []User
cursor, err := usersColl.Find(context.Background(), filter)
if err != nil {
log.Fatal(err)
}
defer cursor.Close(context.Background())
if err = cursor.All(context.Background(), &results); err != nil {
log.Fatal(err)
}
fmt.Printf("找到%d个用户:\n", len(results))
for _, user := range results {
fmt.Printf("- %s (%s)\n", user.Username, user.Email)
}
- 更新文档
go
复制代码
updateFilter := bson.D{{"username", "john_doe"}}
update := bson.D{{"$set", bson.D{{"email", "[email protected]"}}}}
result, err := usersColl.UpdateOne(
context.Background(),
updateFilter,
update,
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("匹配到%d个文档,更新%d个\n", result.MatchedCount, result.UpdatedCount)
- 删除文档
go
复制代码
deleteResult, err := usersColl.DeleteOne(
context.Background(),
bson.D{{"username", "john_doe"}},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("删除%d个文档\n", deleteResult.DeletedCount)
聚合操作
go
复制代码
pipeline := mongo.Pipeline{
{{"$match", bson.D{{"status", "active"}}}},
{{"$group", bson.D{
{"_id", bson.D{{"department", "$department"}}},
{"total", bson.D{{"$sum", 1}}},
}}},
}
var results []bson.M
cursor, err := usersColl.Aggregate(context.Background(), pipeline)
if err != nil {
log.Fatal(err)
}
defer cursor.Close(context.Background())
if err = cursor.All(context.Background(), &results); err != nil {
log.Fatal(err)
}
fmt.Println("部门用户统计:")
for _, doc := range results {
fmt.Printf("%s: %d人\n", doc["_id"].(string), doc["total"].(int32))
}
事务处理
go
复制代码
session, err := client.StartSession()
if err != nil {
log.Fatal(err)
}
defer session.EndSession(context.Background())
txOptions := options.Transaction().SetReadConcern(readconcern.Majority()).SetWriteConcern(writeconcern.Majority())
err = session.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) error {
// 在事务中执行多个操作
_, err := usersColl.InsertOne(sessCtx, User{Username: "alice"})
if err != nil {
return err
}
_, err = ordersColl.InsertOne(sessCtx, Order{UserID: "alice", Total: 100})
if err != nil {
return err
}
return nil
}, txOptions)
if err != nil {
log.Fatal("事务失败:", err)
} else {
fmt.Println("事务成功")
}
高级功能
- 索引管理
go
复制代码
indexModel := mongo.IndexModel{
Keys: bson.D{{"username", 1}},
}
_, err = usersColl.Indexes().CreateOne(
context.Background(),
indexModel,
)
if err != nil {
log.Fatal(err)
}
fmt.Println("索引创建成功")
- 分页查询
go
复制代码
pageSize := 10
pageNumber := 2
filter := bson.D{}
sort := bson.D{{"createdAt", -1}}
optionsFind := options.Find().
SetLimit(int64(pageSize)).
SetSkip(int64((pageNumber-1)*pageSize)).
SetSort(sort)
cursor, err := usersColl.Find(context.Background(), filter, optionsFind)
// 处理游标...
错误处理
go
复制代码
func safeMongoOp(ctx context.Context, op func() (interface{}, error)) (interface{}, error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
result, err := op()
if err != nil {
return nil, fmt.Errorf("mongo operation failed: %w", err)
}
return result, nil
}
连接池配置
go
复制代码
clientOptions := options.Client().
ApplyURI("mongodb://localhost:27017").
SetMaxPoolSize(100).
SetMinPoolSize(10).
SetConnectTimeout(10 * time.Second).
SetSocketTimeout(30 * time.Second)
资源清理
go
复制代码
// 使用defer确保资源释放
cursor, err := collection.Find(ctx, filter)
if err != nil {
// 处理错误
}
defer cursor.Close(ctx)
性能优化建议
- 使用批量操作(InsertMany/UpdateMany)
- 合理使用索引
- 限制查询结果集大小
- 使用投影(Projection)减少数据传输
- 适当使用缓存机制
测试
go
复制代码
setupTestDB(t)
// 测试插入
user := User{Username: "test_user"}
insertResult, _ := collection.InsertOne(context.Background(), user)
// 测试查询
filter := bson.D{{"username", "test_user"}}
var foundUser User
err := collection.FindOne(context.Background(), filter).Decode(&foundUser)
// 清理测试数据
_, _ = collection.DeleteOne(context.Background(), bson.D{{"_id", insertResult.InsertedID}})
简单完整例子
go
复制代码
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// 定义数据结构体
type User struct {
Name string `bson:"name"`
Email string `bson:"email"`
Age int `bson:"age"`
}
func main() {
// 1. 连接 MongoDB
client, err := mongo.Connect(
context.TODO(),
options.Client().ApplyURI("mongodb://localhost:27017"),
)
if err != nil {
log.Fatal("连接失败:", err)
}
defer client.Disconnect(context.TODO()) // 确保关闭连接
// 2. 选择数据库和集合
db := client.Database("testdb")
collection := db.Collection("users")
// 3. 插入文档
user := User{Name: "张三", Email: "[email protected]", Age: 28}
insertResult, err := collection.InsertOne(context.TODO(), user)
if err != nil {
log.Fatal("插入失败:", err)
}
fmt.Printf("插入ID: %v\n", insertResult.InsertedID)
// 4. 查询文档
filter := bson.D{{"name", "张三"}}
var result User
err = collection.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
log.Fatal("查询失败:", err)
}
fmt.Printf("查询结果: %+v\n", result)
// 5. 更新文档
update := bson.D{{"$set", bson.D{{"age", 30}}}}
updateResult, err := collection.UpdateOne(
context.TODO(),
filter,
update,
)
if err != nil {
log.Fatal("更新失败:", err)
}
fmt.Printf("更新数量: %d\n", updateResult.ModifiedCount)
// 6. 删除文档
deleteResult, err := collection.DeleteOne(context.TODO(), filter)
if err != nil {
log.Fatal("删除失败:", err)
}
fmt.Printf("删除数量: %d\n", deleteResult.DeletedCount)
}```