golang-mongodb
0、结构体
type Student struct { // _id 不用带入 Name string Age int }
1、连接
驱动 :github.com/mongodb/mongo-go-driver
1、普通连接
client , err := mongo.Connect( context.TODO(), options.Client().ApplyURI("mongodb://192.168.6.249:27017")) if err != nil { fmt.Printf("mongodb connect failed, err : %s\n", err) return } defer func() { if err = client.Disconnect(context.TODO()); err != nil { fmt.Printf("mongodb disconnect failed, err : %s\n", err) return } }()
2、连接池连接
2、插入
1、插入单条
collection := client.Database("erp").Collection("Student") // 插入一条 s1 := Student{Age: 12, Name: "hello"} insertResult, err := collection.InsertOne(context.TODO(), s1) if err != nil { fmt.Printf("insert mongodb failed , err : %s\n", err) return }
fmt.Println("insert a single document: ", insertResult)
2、插入多条
s2 := Student{Age: 13, Name: "world"} insertDocs := []interface{}{s1, s2} many, err := collection.InsertMany(context.TODO(), insertDocs) fmt.Println(many) // &{[ObjectID("62fefa56a4e8957a0d611caf") ObjectID("62fefa56a4e8957a0d611cb0")]}
3、删除
1、单个删除
// 删除单个文档 [有多条也仅仅只删除一条] deleteResult1, err := collection.DeleteOne(context.TODO(), bson.M{"age": 12}) if err != nil { fmt.Printf("delete one doc failed, err : %s\n", err) return } fmt.Printf("delete %v doc", deleteResult1.DeletedCount) // 删除文档的个数
2、删除多个
// 删除所有文档
_, err = collection.DeleteMany(context.TODO(), bson.M{})
if err != nil {
fmt.Printf("delete many doc failed, err : %s\n", err)
return
}
3、先查询,后删除 FindOneAndDelete
var stu1 Student
collection.FindOneAndDelete(context.TODO(), bson.M{"_id": objectIDHex("62ff34aca744197ad42a3413")})
.Decode(&stu1)
fmt.Printf("one = %+v", stu1)
4、查询
0、根据 _id 查询
func objectIDHex(s string) primitive.ObjectID { oid, _ := primitive.ObjectIDFromHex(s) return oid }
var stu Student
collection := client.Database("erp").Collection("Student")
collection.FindOne(context.TODO(), bson.M{"_id": objectIDHex("62ff34aca744197ad42a3413")}).Decode(&stu)
fmt.Printf("one = %+v", stu)
1、单个查询
FindOne
var stu Student filter := bson.M{"age": 13} collection.FindOne(context.TODO(), filter).Decode(&stu) fmt.Printf("stu ==> %+v\n", stu)
2、多个查询
Find
// 查询多个文档 findOptions := options.Find() findOptions.SetLimit(3) var results []*Student // 把 bson.D{{}} 作为一个 filter 来匹配所有文档 cur, err :=collection.Find(context.TODO(), bson.D{{}}, findOptions) if err != nil { fmt.Printf("find mongodb failed, err : %s\n", err) return } // 查找多个文档返回一个光标 // 遍历游标允许我们一次解码一个文档 for cur.Next(context.TODO()) { // 创建一个值,将单个文档解码为该值 var stu Student err := cur.Decode(&stu) if err != nil { fmt.Printf("mongodb decode, err : %s\n", err) return } results = append(results, &stu) } defer cur.Close(context.TODO()) for _, v := range results { fmt.Printf("%v\n", v) }
5、修改
1 修改单条
UpdateOne
// 修改 filter = bson.M{"name": "world1", "age" : 13} update := bson.D{{"$inc", bson.D{{"age" , 1}}}} updateResult, err := collection.UpdateOne(context.TODO(), filter, update) fmt.Printf("ModifiedCount = %v, MatchedCount = %v,", updateResult.ModifiedCount, updateResult.MatchedCount,)
2 修改多条
UpdateMany
// 修改 filter = bson.M{"name": "world", "age" : 13} update := bson.D{{"$inc", bson.D{{"age" , 1}}}} updateResult, err := collection.UpdateMany(context.TODO(), filter, update) fmt.Printf("ModifiedCount = %v, MatchedCount = %v,", updateResult.ModifiedCount, updateResult.MatchedCount,)
3 修改字段的值 $set
filter := bson.M{"name": "hello", "age" : 12} many, err := collection.UpdateMany(context.TODO(), filter,
bson.M{"$set" : bson.M{"name" : "zhansan"}, "$inc" : bson.M{"age" : 1}})
4 字段的值增加 $inc
collection := client.Database("erp").Collection("Student")
filter := bson.M{"name": "hello", "age" : 13}
collection.UpdateMany(context.TODO(), filter, bson.M{"$inc": bson.M{"age" : -1}})
5 从数组中增加一个元素 push($push)
filter := bson.M{"name": "zhansan", "age" : 13} collection.UpdateMany(context.TODO(), filter, bson.M{"$push": bson.M{"tags" : "Golang"}})
# 如果字段 tags 存在,在tags 数组中添加进去
# 如果字段 tags 不存在,加入一个字段 tags , 并且把 Golang 存进去
6 从数组中删除一个元素 pull($pull)
filter := bson.M{"name": "zhansan", "age" : 13} collection.UpdateMany(context.TODO(), filter, bson.M{"$pull": bson.M{"tags" : "Golang"}})
# 不会删除字段,中字段的数组中删除一个元素
7 先查找,后替换 FindOneAndReplace
var stu, stu1 Student
collection.FindOneAndReplace(context.TODO(), bson.M{"_id": objectIDHex("62ff1b1d840c01f2575560c8")},
bson.M{"age" : 27}).Decode(&stu1)
fmt.Printf("one = %+v", stu1)
仅仅修改 age 的值
8 先查找,后修改 FindOneAndUpdate
collection.FindOneAndUpdate(context.TODO(), bson.M{"_id": objectIDHex("62ff1b1d840c01f2575560c8")},
bson.M{"$set" : bson.M{"age" : 66}}).Decode(&stu1)
fmt.Printf("one = %+v", stu1) // 输出是修改之前的值
6、count 统计数量
CountDocuments
collection := client.Database("erp").Collection("Student") var count int64 if count, err = collection.CountDocuments(context.TODO(), bson.M{"age" : 200}); err != nil { fmt.Printf("") } fmt.Println("count==>", count)
7、单条件查询
1、等于 $eq
collection.Find(context.TODO(), bson.M{"age": 13})
2、不等于 $ne
collection.Find(context.TODO(), bson.M{"age": bson.M{"$ne":13}})
3、小于 $lt
collection.Find(context.TODO(), bson.M{"age": bson.M{"$lt":13}})
4、小于等于 $lte
collection.Find(context.TODO(), bson.M{"age": bson.M{"$lte":13}})
5、大于
collection.Find(context.TODO(), bson.M{"age": bson.M{"$gt": 13}})
6、大于等于 $gte
collection.Find(context.TODO(), bson.M{"age": bson.M{"$gte":13}})
7、in 在数组中 $in
collection.Find(context.TODO(), bson.M{"age": bson.M{"$in": []int{0, 13}}})
8、not in 不在数组中 $nin
collection.Find(context.TODO(), bson.M{"age": bson.M{"$nin": []int{0, 12, 13, 14}}})
9、exists 是否包含这个键($exists)
collection.Find(context.TODO(), bson.M{"age1": bson.M{"$exists": true}})
10、查询键为 null 的字段 [键存在,值为空],也可以查询 nil
cur, err := collection.Find(context.TODO(),
bson.M{"name": bson.M{"$in": []interface{}{""} , "$exists": true}})
11、模糊查询 [暂时不会]
8、关于数组
1 、size 数组长度
collection.Find(context.TODO(), bson.M{"tags": bson.M{"$size": 3}}) tags 字段数组长度为3
2、all 查询数组中包含所有值的匹配(不区分顺序,只看包含不包含)
// mongo tag 字段同时包括 mongodb 和 database
collection.Find(context.TODO(), bson.M{"tags": bson.M{"$all": []string{"mongodb", "database"}}})
3、满足特定的索引下条件
// 数组索引从0开始,我们匹配第二项就用tags.1作为键
filter := bson.M{"tags.0" : "mongodb"}
4、精确查找,数量,顺序都要满足
bson.M{"tags": []string{"数学", "大学数学", "高等数学"}}
5、针对数组中的子文档
bson.M{"author.name": "纪涵"}
8、多条件查询
1、and
collection.Find(context.TODO(),
bson.M{"age" : 12, "name" : "hello", "age1" : bson.M{"$gt" : 2, "$lt" : 4}})
2、or
c.Find(bson.M{"$or": []bson.M{bson.M{"name": "Jimmy Kuu"}, bson.M{"age": 31}}}).All(&users)
9、sort limit 和 skip
findOptions := options.Find()
findOptions.SetLimit(100)
findOptions.SetSkip(20)
findOptions.SetProjection(bson.M{"name" : 0})
findOptions.SetSort(bson.D{{Key : "name" , Value: 1}})
filter := bson.M{"tags.0" : "mongodb"}
var results []*Student
cur, err :=collection.Find(context.TODO(), filter, findOptions)
10、其他函数
1、distinct 去重
filter := bson.M{"name" : bson.M{"$in" : []string{"world", "world1"}}} distinct, err := collection.Distinct(context.TODO(), "name", filter) fmt.Println(len(distinct))
11、聚合操作
1、概念
$sum 计算总和
$avg 计算平均值
$min 获取集合中所有文档对应值得最小值
$max 获取集合中所有文档对应值得最大值
$push 将值加入一个数组中,不会判断是否有重复的值
$addToSet 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。
$first 根据资源文档的排序获取第一个文档数据。
$last 根据资源文档的排序获取最后一个文档数据
2、管道的概念
$project 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit 用来限制MongoDB聚合管道返回的文档数
$skip 在聚合管道中跳过指定数量的文档,并返回余下的文档
$unwind 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
$group 将集合中的文档分组,可用于统计结果
$sort 将输入文档排序后输出
demo1 : group 分组,统计每个名字出现的次数,大于2次的
pipeline := `[
"$group": { "_id": "$name", "numTimes": { "$sum": 1 } }},
{"$match" : {"numTimes" : {"$gt" : 2}}}
]`
opt := options.Aggregate()
cursor ,err := collection.Aggregate(context.TODO(),MongoPipeline(pipeline),opt)
if err != nil {
log.Fatal(err)
}
var results []bson.M
if err = cursor.All(context.TODO(), &results); err != nil {
log.Fatal(err)
}
for _, result := range results {
fmt.Printf(
"name %v appears %v times\n",
result["_id"],
result["numTimes"])
}
}
func MongoPipeline(str string) mongo.Pipeline {
var pipeline = []bson.D{}
str = strings.TrimSpace(str)
if strings.Index(str, "[") != 0 {
var doc bson.D
bson.UnmarshalExtJSON([]byte(str), false, &doc)
pipeline = append(pipeline, doc)
} else {
bson.UnmarshalExtJSON([]byte(str), false, &pipeline)
}
return pipeline
}
demo2 : 或者
pipelint := mongo.Pipeline{ {{Key : "$group", Value : bson.D{ {Key : "_id", Value : "$name"}, {Key : "numTimes", Value: bson.D{{Key: "$sum", Value : 1}}} }}}, {{Key : "$match", Value : bson.D{{Key : "numTimes", Value: bson.D{{Key : "$gt", Value : 2}}}}}}, } opt := options.Aggregate() cursor ,err := collection.Aggregate(context.TODO(),pipelint,opt) if err != nil { log.Fatal(err) } var results []bson.M if err = cursor.All(context.TODO(), &results); err != nil { log.Fatal(err) } for _, result := range results { fmt.Printf( "name %v appears %v times\n", result["_id"], result["numTimes"]) }
dem03 :对于结构体数组
pipeline := ` [{ "$match": { "favoritesList.book": "Journey to the West" } }, { "$project": { "_id": 0, "favoritesList": 1 } }, { "$unwind": { "path": "$favoritesList" } }, { "$match": { "favoritesList.book": "Journey to the West" } }]` collection = client.Database(dbName).Collection(collectionFavorites) opts := options.Aggregate() if cur, err = collection.Aggregate(ctx, MongoPipeline(pipeline), opts); err != nil { t.Fatal(err) } defer cur.Close(ctx) total := 0 for cur.Next(ctx) { total++ }
func MongoPipeline(str string) mongo.Pipeline {
var pipeline = []bson.D{}
str = strings.TrimSpace(str)
if strings.Index(str, "[") != 0 {
var doc bson.D
bson.UnmarshalExtJSON([]byte(str), false, &doc)
pipeline = append(pipeline, doc)
} else {
bson.UnmarshalExtJSON([]byte(str), false, &pipeline)
}
return pipeline
}
demo4 : reduce的写法
pipeline := `[ { "$match": { "favoritesList.book": "Journey to the West" } }, { "$project": { "_id": 0, "favoritesList": 1 } }, { "$redact": { "$cond": { "if": { "$or": [ { "$eq": ["$book", "Journey to the West"] }, { "$not": "$book" } ] }, "then": "$$DESCEND", "else": "$$PRUNE" } } }, { "$unwind": { "path": "$favoritesList" } } ]`
pipeline := `[
{
"$match": {
"favoritesList.book": "Journey to the West"
}
}, {
"$project": {
"favoritesList": {
"$filter": {
"input": "$favoritesList",
"as": "favorite",
"cond": {
"$eq": ["$$favorite.book", "Journey to the West"]
}
}
},
"_id": 0
}
}, {
"$unwind": {
"path": "$favoritesList"
}
}
]`
dem5 : lookup
pipeline := ` [{ "$group": { "_id": { "dealer": "$dealer", "style": "$style" }, "brand": { "$addToSet": "$brand" }, "count": { "$sum": 1 } } }, { "$lookup": { "as": "dealer", "from": "dealers", "let": { "dealerId": "$_id.dealer" }, "pipeline": [{ "$match": { "$expr": { "$eq": [ "$_id", "$$dealerId" ] } } }, { "$project": { "_id": 0, "name": 1 } }] } }]`
demo6: group
pipeline := ` [{ "$group": { "_id": "$style", "brand": { "$addToSet": "$brand" }, "count": { "$sum": 1 } } }]`
demo7 : 数组
pipeline := ` [{ "$match": { "favoritesList": { "$elemMatch": { "city": "London", "book": "Journey to the West" } } } }, { "$project": { "favoritesList": { "$filter": { "input": "$favoritesList", "as": "favorite", "cond": { "$eq": ["$$favorite.book", "Journey to the West"] } } }, "_id": 0, "email": 1 } }, { "$unwind": { "path": "$favoritesList" } }]`
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端