mongodb学习笔记(2)go语言操作mongodb

1、安装驱动包

1.1安装mongoDB Go驱动包

1
go get github.com/mongodb/mongo-go-driverl

1.2通过go连接MongoDB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main
 
import (
    "context"
    "fmt"
    "log"
 
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)
 
func main() {
    // 设置客户端连接配置
    clientOptions := options.Client().ApplyURI("mongodb://127.0.0.1:27017")
 
    // 连接到MongoDB
    Client, err := mongo.Connect(context.TODO(), clientOptions)
    if err != nil {
        log.Fatal(err)
    }
 
    defer func(){
        // 断开连接
        err = Client.Disconnect(context.TODO())
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Connection to MongoDB closed.")
    }()
 
    // 检查连接
    err = Client.Ping(context.TODO(), nil)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Connected to MongoDB!")
}

1.3连接池模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import (
    "context"
    "time"
 
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)
 
func ConnectToDB(uri, name string, timeout time.Duration, num uint64) (*mongo.Database, error) {
    ctx, cancel := context.WithTimeout(context.Background(), timeout)
    defer cancel()
    o := options.Client().ApplyURI(uri)
    o.SetMaxPoolSize(num)
    client, err := mongo.Connect(ctx, o)
    if err != nil {
        return nil, err
    }
 
    return client.Database(name), nil
}

  

2、BSON

2.1概述

MongoDB中的JSON文档存储在名为BSON(二进制编码的JSON)的二进制表示中。与其他将JSON数据存储为简单字符串和数字的数据库不同,BSON编码扩展了JSON表示,使其包含额外的类型,如int、long、date、浮点数和decimal128。这使得应用程序更容易可靠地处理、排序和比较数据。

连接MongoDB的Go驱动程序中有两大类型表示BSON数据:DRaw

类型D家族被用来简洁地构建使用本地Go类型的BSON对象。这对于构造传递给MongoDB的命令特别有用。D家族包括四类:

    • D:一个BSON文档。这种类型应该在顺序重要的情况下使用,比如MongoDB命令。
    • M:一张无序的map。它和D是一样的,只是它不保持顺序。
    • A:一个BSON数组。
    • E:D里面的一个元素。

2.2导入包

要使用BSON,需要先导入下面的包:

1
import "go.mongodb.org/mongo-driver/bson"

 

3、CRUD

3.1概述

下面以user和video这两个结构体来演示mongodb的CRUD,它们的结构如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type User struct {
    UserId        int64   `bson:"user_id"`
    Username      string  `bson:"username"`
    FollowCount   int64   `bson:"follow_count"`   // 关注数
    FollowerCount int64   `bson:"follower_count"` // 粉丝数
    Follows       []int64 `bson:"follows"`        // 关注列表
    Followers     []int64 `bson:"followers"`      // 粉丝列表
    PublishList   []int64 `bson:"publish_list"`   // 发布视频列表
    FavoriteList  []int64 `bson:"favorite_list"// 点赞列表
}
 
type Video struct {
    VideoId       int64     `bson:"video_id"`
    UserId        int64     `bson:"user_id"`
    PlayUrl       string    `bson:"play_url"`
    CoverUrl      string    `bson:"cover_url"`
    FavoriteCount int64     `bson:"favorite_count"`
    Favorites     []int64   `bson:"favorites"`
    CommentCount  int64     `bson:"comment_count"`
    Comments      []Comment `bson:"comments, inline"`
    PublishDate   time.Time `bson:"publish_date"`
    Title         string    `bson:"title"`
}

3.2插入元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//插入单个数据
func InsertOneVideo(Client *mongo.Client){
    coll := Client.Database("tiktok").Collection("video")
    video:=Video{
        VideoId:       10,
        UserId:        1,
        PlayUrl:       "https://www.w3schools.com/html/movie.mp4",
        CoverUrl:      "https://cdn.pixabay.com/photo/2016/03/27/18/10/bear-1283347_1280.jpg",
        FavoriteCount: 0,
        CommentCount:  0,
        Favorites:     []int64{},
        Comments:      []Comment{},
        PublishDate:   time.Now(),
        Title:         "video10",
    }
    result, err := coll.InsertOne(context.TODO(), video)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(result)
}
 
//插入多个数据
func InsertVideos(Client *mongo.Client){
    t := time.Now()
    var vs []interface{}
    for i:=0;i<10;i++{
        mm, _ := time.ParseDuration(strconv.Itoa(i*60)+"m")
        video:=Video{
            VideoId:       int64(i),
            UserId:        int64(i),
            PlayUrl:       "https://www.w3schools.com/html/movie.mp4",
            CoverUrl:      "https://cdn.pixabay.com/photo/2016/03/27/18/10/bear-1283347_1280.jpg",
            FavoriteCount: 0,
            CommentCount:  0,
            Favorites:     []int64{},
            Comments:      []Comment{},
            PublishDate:   t.Add(mm),
            Title:         "video"+strconv.Itoa(i),
        }
        vs=append(vs,video)
    }
    collection := Client.Database("tiktok").Collection("video")
    insertManyResult, err := collection.InsertMany(context.TODO(), vs)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Inserted multiple documents: ", insertManyResult.InsertedIDs)
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
//查询到匹配数据则修改,否则就插入
func UpdateOrInsert(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"username", "Amy"}}
    update := bson.D{{"$set", bson.D{{"username", Susan}}}}
    opts := options.Update().SetUpsert(true)
    result, err := coll.UpdateOne(context.TODO(), filter, update, opts)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Number of documents updated: %v\n", result.ModifiedCount)
    fmt.Printf("Number of documents upserted: %v\n", result.UpsertedCount)
}

3.3删除元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//删除一条文档
func DeleteOneVideo(Client *mongo.Client){
    coll := Client.Database("tiktok").Collection("video")
    filter := bson.D{{"VideoId", "10"}}
    result, err := coll.DeleteOne(context.TODO(), filter)
    if err != nil {
        panic(err)
    }
    fmt.Println(result)
}
 
//删除多条文档
func DeleteVideos(Client *mongo.Client){
    coll := Client.Database("tiktok").Collection("video")
    filter := bson.D{{"VideoId", bson.D{{"$gt", 9}}}}
    results, err := coll.DeleteMany(context.TODO(), filter)
    if err != nil {
        panic(err)
    }
    fmt.Println(results)
}

3.4更新文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//更新多条文档
func UpdateManyUsers(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"UserId", bson.D{{"$gt", 5}}}}
    update := bson.D{{"$mul", bson.D{{"FollowCount", 1}}}}
    result, err := coll.UpdateMany(context.TODO(), filter, update)
    if err != nil {
        panic(err)
    }
    fmt.Println(result)
}
 
//查询到匹配数据则修改,否则就插入
func UpdateOrInsert(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"username", "Amy"}}
    update := bson.D{{"$set", bson.D{{"username", Susan}}}}
    opts := options.Update().SetUpsert(true)
    result, err := coll.UpdateOne(context.TODO(), filter, update, opts)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Number of documents updated: %v\n", result.ModifiedCount)
    fmt.Printf("Number of documents upserted: %v\n", result.UpsertedCount)
}

 

1
2
3
4
5
6
7
8
9
10
11
12
//替换文档
func ReplaceVideo(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"user_id", 10}}
    replacement := bson.D{{"user_id", "10"}, {"username", "david"}}
    result, err := coll.ReplaceOne(context.TODO(), filter, replacement)
    if err!=nil{
        panic(err)
    }
    fmt.Printf("Documents matched: %v\n", result.MatchedCount)
    fmt.Printf("Documents replaced: %v\n", result.ModifiedCount)
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//向数组添加元素
func Add(client *mongo.Client, id, videoId int64){
    collection := client.Database("tiktok").Collection("user")
    query := bson.M{"user_id": id}
    update := bson.M{"$push": bson.M{"favorite_list": videoId}}
    result, err := collection.UpdateOne(context.TODO(), query, update)
    if err != nil {
        panic(err)
    }
    fmt.Println("更新用户信息的结果",result)
 
    collection = client.Database("tiktok").Collection("video")
    //更新点赞列表
    query = bson.M{"video_id": videoId}
    update = bson.M{"$push": bson.M{"favorites": id}}
    result, err = collection.UpdateOne(context.TODO(), query, update)
    if err != nil {
        panic(err)
    }
    fmt.Println("更新用户信息的结果",result)
}
 
//从数组删除指定元素
func Reduce(client *mongo.Client, id, videoId int64){
    collection := client.Database("tiktok").Collection("user")
    query := bson.M{"user_id": id}
    update := bson.M{"$pull": bson.M{"favorite_list": videoId}}
    result, err := collection.UpdateOne(context.TODO(), query, update)
    if err != nil {
        panic(err)
    }
    fmt.Println("更新用户信息的结果",result)
 
    collection = client.Database("tiktok").Collection("video")
    //更新点赞列表
    query = bson.M{"video_id": videoId}
    update = bson.M{"$pull": bson.M{"favorites": id}}
    result, err = collection.UpdateOne(context.TODO(), query, update)
    if err != nil {
        panic(err)
    }
    fmt.Println("更新用户信息的结果",result)
}

  

3.5查询文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//查询的单个文档
func QueryUserByID(client *mongo.Client, id int64) User {
    collection := client.Database("tiktok").Collection("user")
    filter := bson.D{{"user_id", id}}
    var result User
    err := collection.FindOne(context.TODO(), filter).Decode(&result)
    if err != nil {
        log.Println(err)
    }
    fmt.Printf("根据Id查询用户的结果: %+v\n", result)
    return result
}
 
//查询多个文档
func QueryVideosByTime(Client *mongo.Client, t time.Time)([]*Video, error){
    // 将选项传递给Find()
    findOptions := options.Find()
    findOptions.SetLimit(30)    //设置一次查询的最大数量
 
    // 把bson.D{{}}作为一个filter来匹配所有文档
    collection := Client.Database("tiktok").Collection("video")
    sort := bson.D{{"publish_date", -1}}
    findOptions.SetSort(sort)
    cur, err := collection.Find(context.TODO(), bson.M{"publish_date": bson.M{"$gte": t}}, findOptions)
    if err != nil {
        log.Fatal(err)
        return results,err
    }
 
    // 查找多个文档返回一个光标
    // 遍历游标允许我们一次解码一个文档
    for cur.Next(context.TODO()) {
        // 创建一个值,将单个文档解码为该值
        var elem Video
        err := cur.Decode(&elem)
        if err != nil {
            log.Fatal(err)
            return results,err
        }
        results = append(results, &elem)
    }
 
    if err := cur.Err(); err != nil {
        log.Fatal(err)
        return results,err
    }
 
    // 完成后关闭游标
    cur.Close(context.TODO())
    //fmt.Printf("Found multiple documents (array of pointers): %#v,%d\n", results,len(results))
    for i:=0;i<len(results);i++{
        fmt.Println(results[i].PublishDate)
    }
    return results,err
}

 

4、批量操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//批量操作
func Bulk(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    models := []mongo.WriteModel{
        mongo.NewInsertOneModel().SetDocument(bson.D{{"user_id", "11"}, {"username", "jack11"}}),
        mongo.NewInsertOneModel().SetDocument(bson.D{{"user_id", "12"}, {"username", "jack12"}}),
        mongo.NewReplaceOneModel().SetFilter(bson.D{{"user_id", "11"}}).
            SetReplacement(bson.D{{"user_id", 11},{"username", "Amy"}}),
        mongo.NewUpdateManyModel().SetFilter(bson.D{{"user_id", bson.D{{"$lt", 7}}}}).
            SetUpdate(bson.D{{"$inc", bson.D{{"follows", 3}}}}),
        mongo.NewDeleteManyModel().SetFilter(bson.D{{"follows", 9}}),
    }
    opts := options.BulkWrite().SetOrdered(false)//设置插入的顺序是否按照models的顺序
    results, err := coll.BulkWrite(context.TODO(), models, opts)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Number of documents inserted: %d\n", results.InsertedCount)
    fmt.Printf("Number of documents replaced or updated: %d\n", results.ModifiedCount)
    fmt.Printf("Number of documents deleted: %d\n", results.DeletedCount)
}

 

 5、复合操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//复合操作:查找和删除
func FindAndDelete(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"user_id", 11}}
    var deletedDoc bson.D
    err := coll.FindOneAndDelete(context.TODO(), filter).Decode(&deletedDoc)
    if err != nil {
        panic(err)
    }
    fmt.Println(deletedDoc)
}
 
//复合操作:查找和更新
func FindAndUpdate(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"user_id", 12}}
    update := bson.D{{"$set", bson.D{{"followers", 9}}}}
    opts := options.FindOneAndUpdate().SetReturnDocument(options.After)
    var updatedDoc bson.D
    err := coll.FindOneAndUpdate(context.TODO(), filter, update, opts).Decode(&updatedDoc)
    if err != nil {
        panic(err)
    }
    fmt.Println(updatedDoc)
}
 
//复合操作:查找和替换
func FindAndReplace(client *mongo.Client){
    coll := client.Database("tiktok").Collection("user")
    filter := bson.D{{"user_id", 12}}
    replacement := bson.D{{"user_id", 12}, {"username", "bomb"}}
    var previousDoc bson.D
    err := coll.FindOneAndReplace(context.TODO(), filter, replacement).Decode(&previousDoc)
    if err != nil {
        panic(err)
    }
    fmt.Println(previousDoc)
}

  

 6、事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 取消关注
func UnFollowRelation(ctx context.Context, followee int64, follower int64) error {
    userColl := MongoCli.Database("tiktok").Collection("user")
 
    // 定义事务
    callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
        // 是否关注
        err := userColl.FindOne(sessCtx, bson.D{{"user_id", followee}, {"followers", bson.D{{"$all", bson.A{follower}}}}}).Err()
        if err != nil {
            if err == mongo.ErrNoDocuments {
                return nil, errors.New("the user is not followed")
            }
            log.Printf("%v\n", err)
            return nil, err
        }
 
        filter := bson.D{{"user_id", followee}}
        update := bson.D{
            {"$inc", bson.D{{"follower_count", -1}}},
            {"$pull", bson.D{{"followers", follower}}},
        }
        if updateResult, err := userColl.UpdateOne(sessCtx, filter, update); err != nil {
            return nil, err
        } else if updateResult.MatchedCount == 0 {
            return nil, errors.New("no followee was found")
        }
        filter = bson.D{{"user_id", follower}}
        update = bson.D{
            {"$inc", bson.D{{"follow_count", -1}}},
            {"$pull", bson.D{{"follows", followee}}},
        }
        if updateResult, err := userColl.UpdateOne(sessCtx, filter, update); err != nil {
            return nil, err
        } else if updateResult.MatchedCount == 0 {
            return nil, errors.New("no follower was found")
        }
        return nil, nil
    }
 
    // 开启会话
    session, err := MongoCli.StartSession()
    if err != nil {
        log.Printf("ERROR: fail to start mongo session. %v\n", err)
        return err
    }
    defer session.EndSession(ctx)
 
    // 执行事务
    _, err = session.WithTransaction(ctx, callback)
    if err != nil {
        log.Printf("ERROR: fail to UnFollowRelation. %v\n", err)
        return err
    }
    return nil
}

  

 

 

 

 

 

 

 

参考:Go语言操作mongoDB | 李文周的博客 (liwenzhou.com)

 参考:Context — Go (mongodb.com)

posted @   ☞@_@  阅读(394)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
历史上的今天:
2021-06-05 go语言学习笔记五(数组和切片)
点击右上角即可分享
微信分享提示