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)上创建索引可以极大提高查询速度。
posted @ 2026-04-21 19:28  干炸小黄鱼  阅读(7)  评论(0)    收藏  举报