Golang连接操作MongoDB基础处理

目录

一、各步骤操作

下面查询使用到的bson.M和bson.D差不多,只要区别在于M内部元素是无序的map,D是有序的切片

连接数据库

go 复制代码
func connectDB(ctx context.Context) {
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		return
	}
	// 测试一下连通性
	if err := client.Ping(ctx, nil); err != nil {
		return
	}
	// 关闭
	defer func() { _ = client.Disconnect(ctx) }()

	// 获取MongoDB数据库集合对象。learn数据库,test_data集合
	collection := client.Database("learn").Collection("test_data")
	return
}

插入数据

go 复制代码
func insertData(ctx context.Context, collection *mongo.Collection) {
	// 集合插入一条数据
	insertResult, err := collection.InsertOne(ctx, bson.M{"name": "植物大战僵尸", "age": 18, "class": "初一", "lastTime": time.Now().Format("2006-01-02 15:04:05")})
	if err != nil {
		println("插入失败", err.Error())
		return
	}
	println("插入数据的文档id为:", insertResult.InsertedID)
}

查询多条数据

go 复制代码
func findData(ctx context.Context, collection *mongo.Collection, filter interface{}, opts ...*options.FindOptions) {
	// 查找数据,获得游标
	cursor, err := collection.Find(ctx, filter, opts...)
	if err != nil {
		println("查询失败", err.Error())
		return
	}
	// 关闭游标
	defer func() { _ = cursor.Close(ctx) }()

	for cursor.Next(ctx) {
		// 查询一条数据,并映射数据到 bson 格式中
		var result TestData
		if err := cursor.Decode(&result); err != nil {
			println("解析数据失败", err.Error())
			return
		}
		fmt.Printf("找到多条数据,内容为: %+v\n", result)
	}
}

删除数据

go 复制代码
func deleteOne(ctx context.Context, collection *mongo.Collection) {
	// 查询条件
	filter := bson.D{{"name", "植物大战僵尸"}, {"age", 19}}
	// 集合删除数据
	deleteResult, err := collection.DeleteMany(ctx, filter)
	if err != nil {
		println("删除失败", err.Error())
		return
	}
	println("删除数据的数量为:", deleteResult.DeletedCount)
}

分组查询数据

go 复制代码
func groupData(ctx context.Context, collection *mongo.Collection) {
	filter := mongo.Pipeline{
		// 先查找age字段大于等于9
		bson.D{{"$match", bson.D{{"age", bson.D{{"$gte", 9}}}}}},
		// 对gender字段分组(_id是固定的),然后对分组下的englishScore字段求平均值作为一个字段,且取出分组下年龄最大值
		bson.D{{"$group", bson.M{"_id": "$gender", "英语成绩平均数": bson.M{"$avg": "$englishScore"}, "最大年龄": bson.M{"$max": "$age"}}}},
	}
	showInfoCursor, err := collection.Aggregate(ctx, filter)
	if err != nil {
		println("分组查询失败", err.Error())
		return
	}
	// 关闭游标
	defer func() { _ = showInfoCursor.Close(ctx) }()

	for showInfoCursor.Next(ctx) {
		// 查询一条数据,并映射数据到 bson 格式中
		var result bson.M
		if err := showInfoCursor.Decode(&result); err != nil {
			println("解析数据失败", err.Error())
			return
		}
		fmt.Printf("找到多条数据,内容为: %+v\n", result)
	}
}

二、总代码

go 复制代码
package main

import (
	"context"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"time"
)

// TestData 文档数据结构
type TestData struct {
	Name         string    `bson:"name"`         // 姓名
	Age          int       `bson:"age"`          // 年龄
	Gender       int32     `bson:"gender"`       // 性别 1男2女
	LastTime     time.Time `bson:"lastTime"`     // 下课时间
	Class        string    `bson:"class"`        // 班级
	EnglishScore float32   `bson:"englishScore"` // 英语成绩
}

func main() {
	ctx := context.TODO()
	// 连接MongoDB
	mongoClient, err := connectDB(ctx)
	if err != nil {
		println("连接失败了", err.Error())
		return
	}
	defer func() { _ = mongoClient.Disconnect(ctx) }()

	// 获取MongoDB数据库集合对象
	collection := mongoClient.Database("learn").Collection("test_data")

	// 插入数据
	//insertData(ctx, collection)
	insertSomeData(ctx, collection)

	// 查询数据
	//findOneData(ctx, collection)
	findSomeData(ctx, collection)

	// 更新字段信息
	//updateOne(ctx, collection)
	//updateSome(ctx, collection)

	// 删除一条文档
	//deleteOne(ctx, collection)

	// 使用各种条件语句,查询多条数据
	//findDataCondition(ctx, collection)

	// 分组查询
	//groupData(ctx, collection)
}

// 连接数据库
func connectDB(ctx context.Context) (*mongo.Client, error) {
	clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		return nil, err
	}
	if err := client.Ping(ctx, nil); err != nil {
		return nil, err
	}
	return client, nil
}

// 插入一条数据
func insertData(ctx context.Context, collection *mongo.Collection) {
	// 集合插入一条数据
	insertResult, err := collection.InsertOne(ctx, bson.M{"name": "植物大战僵尸", "age": 18, "class": "初一", "lastTime": time.Now().Format("2006-01-02 15:04:05")})
	if err != nil {
		println("插入失败", err.Error())
		return
	}
	println("插入数据的文档id为:", insertResult.InsertedID)
}

// 插入多条数据
func insertSomeData(ctx context.Context, collection *mongo.Collection) {
	var data = []TestData{
		{Name: "张三", Age: 8, Gender: 1, LastTime: time.Date(2024, 4, 8, 3, 0, 0, 0, time.UTC), Class: "高一", EnglishScore: 60.5},
		{Name: "李三文", Age: 9, Gender: 2, LastTime: time.Date(2024, 4, 8, 4, 0, 0, 0, time.UTC), Class: "高三", EnglishScore: 59.7},
		{Name: "李三武", Age: 10, Gender: 1, LastTime: time.Date(2024, 4, 8, 5, 0, 0, 0, time.UTC), Class: "高一", EnglishScore: 86.2},
		{Name: "李四", Age: 11, Gender: 2, LastTime: time.Date(2024, 4, 8, 6, 0, 0, 0, time.UTC), Class: "高二", EnglishScore: 37.0},
		{Name: "王五", Age: 12, Gender: 1, LastTime: time.Date(2024, 4, 8, 7, 0, 0, 0, time.UTC), Class: "高一", EnglishScore: 27.8},
	}
	var insertData []interface{}
	for _, datum := range data {
		insertData = append(insertData, datum)
	}
	// 集合插入多条数据
	insertResult, err := collection.InsertMany(ctx, insertData)
	if err != nil {
		println("插入失败", err.Error())
		return
	}
	fmt.Printf("插入数据的文档id为:%+v", insertResult.InsertedIDs)
}

// 查找一条数据
func findOneData(ctx context.Context, collection *mongo.Collection) {
	// 查询条件
	filter := bson.M{"name": "张三"}

	// 查询一条数据,并映射数据到结构体中
	var result TestData
	if err := collection.FindOne(ctx, filter).Decode(&result); err != nil {
		println("查询失败", err.Error())
		return
	}
	fmt.Printf("找到一条数据,内容为: %+v\n", result)

	// name字段值为张三,获取数量
	countNumber, err := collection.CountDocuments(ctx, filter)
	if err != nil {
		println("查询数量失败", err.Error())
		return
	}
	println("数量为:", countNumber)
}

// 查找数据,使用各种条件语句
// bson.M和bson.D差不多,只要区别在于bson.M内部元素是无序的
func findDataCondition(ctx context.Context, collection *mongo.Collection) {
	var opt *options.FindOptions
	// class的值为高一,且age的值大于10
	filter := bson.D{{"class", "高一"}, {"age", bson.D{{"$gt", 10}}}}
	// class的值为高一,且age的值小于9
	//filter := bson.D{{"class", "高一"}, {"age", bson.D{{"$lt", 10}}}}
	// class的值为高一,且age的值大于等于10
	//filter := bson.D{{"class", "高一"}, {"age", bson.D{{"$gte", 10}}}}
	// class的值为高一,且age的值大于等于10,同时age的值小于等于18
	//filter := bson.D{{"class", "高一"}, {"age", bson.D{{"$gte", 10}, {"$lte", 18}}}}
	// class的值为高一,且age的值不等于10
	//filter := bson.D{{"class", "高一"}, {"age", bson.D{{"$ne", 10}}}}
	// name模糊匹配以李字符开头的字符串
	// options:【i代表不区分大小写,s代表允许点字符匹配所有的字符包括换行符,x代表忽略所有空白字符,m代表匹配包含有换行符的场景同时允许使用锚(^开头$结尾)】
	//filter := bson.M{"name": bson.M{"$regex": "^李", "$options": "m"}}
	// name字段值为李四,且指定只返回class列
	//filter := bson.D{{"name", "李四"}}
	//opt = options.Find().SetProjection(bson.D{{"class", 1}})
	// gender字段值为1,且根据englishScore字段排序,值为1从小到大,值为-1从大到小
	//filter := bson.D{{"gender", 1}}
	//opt = options.Find().SetSort(bson.D{{"englishScore", -1}})
	// name字段值为王者,且只返回一条数据
	//filter := bson.D{{"gender", 1}}
	//opt = options.Find().SetLimit(1)
	// name字段值为王者,分页查询
	//filter := bson.D{{"gender", 1}}
	//opt = options.Find().SetSort(bson.D{{"englishScore", 1}}).SetSkip(1).SetLimit(1)
	// class字段值为高一,or条件查找age为8或者gender值为1
	//filter := bson.D{{"class", "高一"}, {"$or", []bson.D{bson.D{{"age", 8}}, bson.D{{"gender", 1}}}}}
	// name字段值为张三或者李四
	//filter := bson.D{{"name", bson.D{{"$in", []string{"张三", "李四"}}}}}
	// lastTime字段时间区间范围查询,lastTime保存在数据库的类型必须为Date
	//filter := bson.M{"lastTime": bson.M{
	//	"$gte": time.Date(2024, 4, 8, 3, 0, 0, 0, time.UTC),
	//	"$lte": time.Date(2024, 4, 8, 5, 0, 0, 0, time.UTC),
	//}}

	findData(ctx, collection, filter, opt)
}

// 查找多行数据底层封装
func findData(ctx context.Context, collection *mongo.Collection, filter interface{}, opts ...*options.FindOptions) {
	// 查找数据,获得游标
	cursor, err := collection.Find(ctx, filter, opts...)
	if err != nil {
		println("查询失败", err.Error())
		return
	}
	// 关闭游标
	defer func() { _ = cursor.Close(ctx) }()

	for cursor.Next(ctx) {
		// 查询一条数据,并映射数据到 bson 格式中
		var result TestData
		if err := cursor.Decode(&result); err != nil {
			println("解析数据失败", err.Error())
			return
		}
		fmt.Printf("找到多条数据,内容为: %+v\n", result)
	}
}

// 查找多条数据
func findSomeData(ctx context.Context, collection *mongo.Collection) {
	findData(ctx, collection, bson.D{{"name", "王者"}})
}

// 更新一条数据
func updateOne(ctx context.Context, collection *mongo.Collection) {
	// 查询条件
	filter := bson.D{{"name", "植物大战僵尸"}, {"age", 18}}
	// 更新的字段和值信息
	updateData := bson.D{{"$set", bson.D{{"class", "初二"}}}}
	// 集合更新一条数据
	updateResult, err := collection.UpdateOne(ctx, filter, updateData)
	if err != nil {
		println("更新失败", err.Error())
		return
	}
	println("更新数据的文档id为:", updateResult.UpsertedID, ",匹配数量:", updateResult.MatchedCount, ",修改数量:", updateResult.ModifiedCount)
}

// 更新多条数据
func updateSome(ctx context.Context, collection *mongo.Collection) {
	// 查询条件
	filter := bson.D{{"name", "植物大战僵尸"}}
	// 更新的字段和值信息
	updateData := bson.D{{"$set", bson.D{{"class", "六年级"}}}}
	// 集合更新一条数据
	updateResult, err := collection.UpdateMany(ctx, filter, updateData)
	if err != nil {
		println("更新失败", err.Error())
		return
	}
	println("更新数据的文档id为:", updateResult.UpsertedID, ",匹配数量:", updateResult.MatchedCount, ",修改数量:", updateResult.ModifiedCount)
}

// 删除数据
func deleteOne(ctx context.Context, collection *mongo.Collection) {
	// 查询条件
	filter := bson.D{{"name", "植物大战僵尸"}, {"age", 19}}
	// 集合删除数据
	deleteResult, err := collection.DeleteMany(ctx, filter)
	if err != nil {
		println("删除失败", err.Error())
		return
	}
	println("删除数据的数量为:", deleteResult.DeletedCount)
}

// 对数据分组查询
func groupData(ctx context.Context, collection *mongo.Collection) {
	filter := mongo.Pipeline{
		// 先查找age字段大于等于9
		bson.D{{"$match", bson.D{{"age", bson.D{{"$gte", 9}}}}}},
		// 对gender字段分组(_id是固定的),然后对分组下的englishScore字段求平均值作为一个字段,且取出分组下年龄最大值
		bson.D{{"$group", bson.M{"_id": "$gender", "英语成绩平均数": bson.M{"$avg": "$englishScore"}, "最大年龄": bson.M{"$max": "$age"}}}},
	}
	showInfoCursor, err := collection.Aggregate(ctx, filter)
	if err != nil {
		println("分组查询失败", err.Error())
		return
	}
	// 关闭游标
	defer func() { _ = showInfoCursor.Close(ctx) }()

	for showInfoCursor.Next(ctx) {
		// 查询一条数据,并映射数据到 bson 格式中
		var result bson.M
		if err := showInfoCursor.Decode(&result); err != nil {
			println("解析数据失败", err.Error())
			return
		}
		fmt.Printf("找到多条数据,内容为: %+v\n", result)
	}
}
相关推荐
Clown953 小时前
go-zero(十) 数据缓存和Redis使用
redis·缓存·golang
蚂蚁在飞-4 小时前
一个高度可扩展的 Golang ORM 库【GORM】
数据库·oracle·golang
hummhumm5 小时前
第33章 - Go语言 云原生开发
java·开发语言·后端·python·sql·云原生·golang
凡人的AI工具箱6 小时前
40分钟学 Go 语言高并发:【实战】并发安全的配置管理器(功能扩展)
开发语言·后端·安全·架构·golang
桃园码工7 小时前
3-测试go-redis+redsync实现分布式锁 --开源项目obtain_data测试
redis·分布式·golang
zybsjn9 小时前
MongoDB 和 Redis 是两种不同类型的数据库比较
数据库·redis·mongodb
树獭叔叔9 小时前
2K字速通MongoDB
数据库·后端·mongodb
懒是一种态度9 小时前
Golang调用MongoDB的表自动增长的 ID 永久保存在 MongoDB 中,并且每次获取的 ID 是基于上次的结果
数据库·mongodb
zybsjn9 小时前
深入解读 MongoDB 查询耗时:Execution 和 Fetching 阶段详解
数据库·mongodb
zyxzyx6669 小时前
MongoDB快速入门
数据库·mongodb