go如何使用mongodb
MongoDB 是目前最流行的文档型数据库(NoSQL 的一种)。与传统的关系型数据库(如 MySQL)不同,它不存储行和列,而是存储类似 JSON 的二进制格式文档(BSON)。
这种特性使得 MongoDB 非常适合处理数据结构多变、高并发读写、海量数据的场景。
📚 MongoDB 核心概念普及
将 MongoDB 的概念与 MySQL 做了一个对照表:
| MySQL 概念 | MongoDB 概念 | 说明 |
|---|---|---|
| 数据库 (Database) | 数据库 (Database) | 数据的容器,概念一致。 |
| 表 (Table) | 集合 (Collection) | 类似于表,但不需要预先定义列结构。 |
| 行 (Row) | 文档 (Document) | 一条具体的数据,格式为 BSON(类似 JSON)。 |
| 列 (Column) | 字段 (Field) | 文档中的键值对。 |
| 主键 (Primary Key) | _id | 每个文档必须有一个 _id,如果没有,MongoDB 会自动生成。 |
MongoDB 的主要特点:
- 模式自由 (Schema-less):同一个集合中的文档可以有不同的字段和结构。
- 高性能:支持丰富的索引(包括地理空间索引)。
- 高可用:原生支持副本集,主节点挂掉会自动选举新主节点。
- 易扩展:支持分片,可以轻松实现水平扩展以应对海量数据。
💻 Go 语言操作 MongoDB 实战
在 Go 中使用 MongoDB,官方推荐的驱动是 go.mongodb.org/mongo-driver/mongo。
1. 准备工作
首先,初始化你的 Go 模块并安装驱动:
go mod init my-mongo-app
go get go.mongodb.org/mongo-driver/mongo
2. 完整代码示例 (CRUD)
下面是一个完整的 Go 程序,演示了如何连接数据库,并进行增、删、改、查操作。
场景:我们要管理一个名为 users 的集合,存储用户信息。
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"
)
// 定义数据结构(可选,也可以用 bson.M 直接操作)
type User struct {
Name string `bson:"name"`
Email string `bson:"email"`
Age int `bson:"age"`
}
func main() {
// 1. 连接 MongoDB
// 默认本地连接地址是 mongodb://localhost:27017
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
// 设置超时时间
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// 建立连接
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
// 检查连接是否成功 (Ping)
if err := client.Ping(ctx, nil); err != nil {
log.Fatal(err)
}
fmt.Println("✅ 已连接到 MongoDB!")
// 选择数据库和集合
collection := client.Database("testDB").Collection("users")
// --- 2. 插入数据 (Create) ---
fmt.Println("--- 开始插入数据 ---")
user1 := User{Name: "Alice", Email: "alice@example.com", Age: 25}
user2 := User{Name: "Bob", Email: "bob@example.com", Age: 30}
// 插入单条
insertResult, err := collection.InsertOne(ctx, user1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("插入单条成功, ID: %v\n", insertResult.InsertedID)
// 插入多条
users := []interface{}{user2, bson.M{"name": "Charlie", "email": "charlie@example.com", "age": 28}}
insertManyResult, err := collection.InsertMany(ctx, users)
if err != nil {
log.Fatal(err)
}
fmt.Printf("插入多条成功, ID列表: %v\n", insertManyResult.InsertedIDs)
// --- 3. 查询数据 (Read) ---
fmt.Println("--- 开始查询数据 ---")
// 查询单个文档 (查找名字为 Alice 的用户)
var result User
filter := bson.M{"name": "Alice"}
err = collection.FindOne(ctx, filter).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
fmt.Println("未找到文档")
} else {
log.Fatal(err)
}
} else {
fmt.Printf("找到用户: %+v\n", result)
}
// 查询多个文档 (查找年龄大于 26 的用户)
fmt.Println("查找年龄 > 26 的用户:")
findFilter := bson.M{"age": bson.M{"$gt": 26}} // $gt 表示 greater than
cursor, err := collection.Find(ctx, findFilter)
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var u User
if err := cursor.Decode(&u); err != nil {
log.Fatal(err)
}
fmt.Printf(" -> %s (%d岁)\n", u.Name, u.Age)
}
// --- 4. 更新数据 (Update) ---
fmt.Println("--- 开始更新数据 ---")
// 将 Bob 的年龄更新为 31
updateFilter := bson.M{"name": "Bob"}
updateData := bson.M{"$set": bson.M{"age": 31}} // $set 操作符
updateResult, err := collection.UpdateOne(ctx, updateFilter, updateData)
if err != nil {
log.Fatal(err)
}
fmt.Printf("匹配了 %d 个文档,更新了 %d 个文档\n", updateResult.MatchedCount, updateResult.ModifiedCount)
// --- 5. 删除数据 (Delete) ---
fmt.Println("--- 开始删除数据 ---")
// 删除 Charlie
deleteFilter := bson.M{"name": "Charlie"}
deleteResult, err := collection.DeleteOne(ctx, deleteFilter)
if err != nil {
log.Fatal(err)
}
fmt.Printf("删除了 %d 个文档\n", deleteResult.DeletedCount)
fmt.Println("✅ 操作完成!")
}
🔑 关键知识点解析
1. 连接字符串
- 本地连接:
mongodb://localhost:27017 - 带认证连接:
mongodb://username:password@localhost:27017/?authSource=admin
2. 常用操作符
在 bson.M 中,MongoDB 的操作符通常以 $ 开头:
- 查询比较:
$gt(大于),$lt(小于),$in(包含),$eq(等于) - 更新操作:
$set(设置字段),$inc(自增数值),$unset(删除字段)
3. 结构体标签 (Tags)
在定义 Go 结构体时,使用 bson:"字段名" 标签可以指定映射关系。
type User struct {
Name string `bson:"username"` // 数据库中存储为 username
}
4. 游标 (Cursor)
查询多条数据时,Find 方法返回一个游标。记得在遍历结束后调用 defer cursor.Close(ctx) 来释放资源。
🚀 进阶提示
- 聚合管道 (Aggregation):MongoDB 强大的地方在于聚合,类似于 SQL 的
GROUP BY。在 Go 中使用collection.Aggregate(),配合$match,$group,$project等阶段进行复杂数据分析。 - 索引:在查询频繁的字段(如
email)上创建索引可以极大提高查询速度。

浙公网安备 33010602011771号