目录
一、各步骤操作
下面查询使用到的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)
}
}