0%

go操作mongodb

说明

  • 本次主要在win10, go 1.20.4下,利用go 操作mongodb

安装启动

  • 打开地址下载安装包
  • 解压后目录如下,添加两个文件夹data和logs文件夹,用来存储mongodb的数据和日志文件
1
2
3
4
5
6
7
8
9
D:\app\mongodb-win32-x86_64-windows-6.0.6>tree
卷 项目盘 的文件夹 PATH 列表
卷序列号为 8C07-3198
D:.
├─bin
├─data
│ ├─diagnostic.data
│ └─journal
└─logs
  • 启动服务
1
D:\app\mongodb-win32-x86_64-windows-6.0.6\bin>mongod.exe --dbpath D:\app\mongodb-win32-x86_64-windows-6.0.6\data --logpath D:\app\mongodb-win32-x86_64-windows-6.0.6\logs\mongodb.log
  • 启动成功后data目录下会自动生成MongoDB数据库的一些信息,logs目录下存的则是日志文件,文件内容是启动信息

  • 安装连接工具mongodb compass,连接mongodb,地址是本地127.0.0.1,默认端口是27017

image-20230712171639801

  • 默认连接没有用户名和密码,需要进行设置
  • 点击底部菜单,输入use admin

image-20230712180544757

  • 然后输入
1
2
3
4
5
6
7
8
db.createUser({
user: 'admin', // 用户名
pwd: '123456', // 密码
roles:[{
role: 'root', // 角色---超级管理员才可以使用该角色
db: 'admin' // 数据库
}]
})

image-20230712180758846

  • 其他常用语句
1
2
3
4
5
6
7
8
9

> show dbs
admin 132.00 KiB
config 108.00 KiB
local 72.00 KiB
user 40.00 KiB
>db.auth("admin","123456") -- 授权
{ ok: 1 }

  • mongodb compass 中为admin数据库中加入users的collection

image-20230712194613916

代码编写

服务端代码

  • 初始化项目
1
2
3
4
cd E:\proj\gowork
mkdir studyMongoDB
cd studyMongoDB
go mod init example.com/studyMongoDB
  • 用vscode 打开文件夹,安装依赖
1
2
3
go get -u github.com/gin-gonic/gin
go get go.mongodb.org/mongo-driver/mongo

  • 编写测试代码
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//main.go

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"
"go.mongodb.org/mongo-driver/mongo/readpref"
)

type Student struct {
Id int32
Name string
Age int
}

// pool 连接池模式
func ConnectToDB(uri, name string, timeout time.Duration, num uint64) (*mongo.Database, error) {
// 设置连接超时时间
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// 通过传进来的uri连接相关的配置
o := options.Client().ApplyURI(uri)
// 设置最大连接数 - 默认是100 ,不设置就是最大 max 64
o.SetMaxPoolSize(num)
// 发起链接
client, err := mongo.Connect(ctx, o)
if err != nil {
fmt.Println(err)
return nil, err
}
// 判断服务是不是可用
if err = client.Ping(context.Background(), readpref.Primary()); err != nil {
log.Fatal(err)
return nil, err
}
// 返回 client
return client.Database(name), nil
}

func main() {

toDB, err := ConnectToDB("mongodb://admin:123456@localhost:27017", "admin", time.Duration(2), 50)
fmt.Println(err)
if err != nil {
fmt.Println(err)
fmt.Println(toDB)
return
}
fmt.Println("sussces")
doc := Student{Name: "刘刘", Age: 18, Id: 1}

coll := toDB.Collection("users")
objId, err := coll.InsertOne(context.TODO(), doc)
fmt.Println(objId)
if err != nil {
return
}
fmt.Println("新增成功")
var one Student
filter := bson.D{{"id", 1}}
var ctx context.Context
var cancel func()
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err = coll.FindOne(ctx, filter).Decode(&one)
if err == mongo.ErrNoDocuments {
// Do something when no record was found
fmt.Println("record does not exist")
} else if err != nil {
log.Fatal(err)
}
fmt.Println(one)

}

  • 运行结果
1
2
3
4
5
6
7
PS E:\proj\gowork\studyMongoDb> go run .\main.go
<nil>
sussces
&{ObjectID("64ae992a5063fc95642035ed")}
新增成功
{1 刘刘 18}
PS E:\proj\gowork\studyMongoDb>

gin和mongodb

  • dbs\db.go为连接数据库代码
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
package dbs

import (
"context"
"fmt"
"log"
"time"

"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
)

var (
Client *mongo.Client // database 话柄
Collection *mongo.Collection // collection 话柄
)

// pool 连接池模式
func ConnectToDB(uri, name string) {

cb := context.Background()
// 设置连接超时时间
ctx1, cancel := context.WithTimeout(cb, time.Duration(2))
defer cancel()
// 通过传进来的uri连接相关的配置
o := options.Client().ApplyURI(uri)
// 设置最大连接数 - 默认是100 ,不设置就是最大 max 64
o.SetMaxPoolSize(50)
// 发起链接
client, err := mongo.Connect(ctx1, o)
if err != nil {
fmt.Println(err)
return
}
// 判断服务是不是可用
if err = client.Ping(cb, readpref.Primary()); err != nil {
log.Fatal(err)
return
}
// 默认连接的数据库
_db := client.Database(name)

Client = client
// 默认连接集合为users
Collection = _db.Collection("users")
}
  • models/user.go 操作实体类
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package models

import (
"context"
"fmt"
"log"

"example.com/studyMongoDb/dbs"
"go.mongodb.org/mongo-driver/bson"
)

type User struct {
Key string `json:"key"`
Name string `json:"name"`
Password string `json:"password"`
Id int `json:"id"`
}


func (u *User) GetList(ctx context.Context) (users []User, err1 error) {
cur, err := dbs.Collection.Find(ctx, bson.D{})
if err != nil {
log.Fatal(err)
return
}
if err := cur.Err(); err != nil {
log.Fatal(err)
return
}
err = cur.All(ctx, &users)
if err != nil {
log.Fatal(err)
return
}
cur.Close(ctx)
return

}

func (u *User) Query() (user []User, err1 error) {
cb := context.Background()
fil := bson.M{"key": u.Key}
// 模糊查询
// bson.M{"Name": primitive.Regex{Pattern: u.name}}
cur, err := dbs.Collection.Find(cb, fil)
// dbs.Collection.FindOne(cb, fil).Decode(&user)
if err != nil {
log.Fatal(err)
return
}
if err := cur.Err(); err != nil {
log.Fatal(err)
return
}
err = cur.All(cb, &user)
if err != nil {
log.Fatal(err)
return
}
cur.Close(cb)
return

}

func (u *User) Add() (err error) {
objId, err1 := dbs.Collection.InsertOne(context.TODO(), &u)
if err1 != nil {
fmt.Println("insert into error:", err)

}
fmt.Println("录入数据成功,", objId)
return
}
func (u *User) EditOne() (err1 error) {
fil := bson.M{"key": u.Key}
update := bson.M{"$set": u}
// .update({条件},{修改后的数据})
updateResult, err := dbs.Collection.UpdateOne(context.Background(), fil, update)
if err != nil {
log.Fatal(err)
}
log.Println("collection.UpdateOne:", updateResult)
return
}

func (u *User) Delete() (err1 error) {
fil := bson.M{"key": u.Key}
deleteResult, err := dbs.Collection.DeleteOne(context.Background(), fil)
if err != nil {
log.Fatal(err)
}
log.Println("collection.DeleteOne:", deleteResult)
return
}

  • api\users.go 调用model层代码
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package api

import (
"context"
"fmt"
"net/http"

"example.com/studyMongoDb/models"
"github.com/gin-gonic/gin"
)

func UserAdd(c *gin.Context) {
var user models.User
if c.Bind(&user) == nil { //把客户端格式传过来的数据绑定到结构体user中去
fmt.Println("data=", user)
err := user.Add() // 调用model层的对应方法
if err != nil {

c.JSON(http.StatusOK, gin.H{
"msg": "新增失败",
"code": -1,
})

} else {
c.JSON(http.StatusOK, gin.H{
"msg": "新增成功",
"code": 1,
})
}
} else {
c.JSON(400, gin.H{"JSON=== status": "binding JSON error!"})
}
}

func UserList(c *gin.Context) {
var user models.User
if c.Bind(&user) == nil { //把客户端格式传过来的数据绑定到结构体user中去
users, err := user.GetList(context.Background()) // 调用model层的对应方法
if err != nil {

c.JSON(http.StatusOK, gin.H{
"msg": "获取列表失败",
"code": -1,
})

} else {
c.JSON(http.StatusOK, gin.H{
"msg": "获取列表成功",
"code": 1,
"users": users,
})
}
} else {
c.JSON(400, gin.H{"JSON=== status": "binding JSON error!"})
}
}

func UserEditOne(c *gin.Context) {
var user models.User
if c.Bind(&user) == nil {
err := user.EditOne()
if err != nil {

c.JSON(http.StatusOK, gin.H{
"msg": "编辑失败",
"code": -1,
})

} else {
c.JSON(http.StatusOK, gin.H{
"msg": "编辑成功",
"code": 1,
})
}
} else {
c.JSON(400, gin.H{"JSON=== status": "binding JSON error!"})
}
}

func UserDelete(c *gin.Context) {
var user models.User
if c.Bind(&user) == nil {
err := user.Delete()
if err != nil {

c.JSON(http.StatusOK, gin.H{
"msg": "删除失败",
"code": -1,
})

} else {
c.JSON(http.StatusOK, gin.H{
"msg": "删除成功",
"code": 1,
})
}
} else {
c.JSON(400, gin.H{"JSON=== status": "binding JSON error!"})
}
}
func UserQuery(c *gin.Context, key string) {
user := models.User{
Key: key,
}
if c.Bind(&user) == nil {
user, err := user.Query()
if err != nil {

c.JSON(http.StatusOK, gin.H{
"msg": "查询失败",
"code": -1,
})

} else {
c.JSON(http.StatusOK, gin.H{
"msg": "查询成功",
"code": 1,
"user": user,
})
}
} else {
c.JSON(400, gin.H{"JSON=== status": "binding JSON error!"})
}
}

  • routers/router.go 路由层,调用api层的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package routers

import (
"example.com/studyMongoDb/api"
"github.com/gin-gonic/gin"
)

func InitRouter() *gin.Engine {

router := gin.Default()
router.POST("/UserAdd", api.UserAdd)
router.GET("/UserList", api.UserList)
router.POST("/UserEditOne", api.UserEditOne)
router.POST("/UserDelete", api.UserDelete)
router.GET("/UserQuery/:key", func(c *gin.Context) {
key := c.Param("key")
api.UserQuery(c, key)
})

return router
}

  • main.go 代码入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"context"

"example.com/studyMongoDb/dbs"
"example.com/studyMongoDb/routers"
)

func main() {

dbs.ConnectToDB("mongodb://admin:123456@localhost:27017", "admin")
router := routers.InitRouter()
router.Run(":8000")
// 优雅关闭连接
defer dbs.Client.Disconnect(context.TODO())

}

  • 运行main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS E:\proj\gowork\studyMongoDb> go run .\main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)

[GIN-debug] POST /UserAdd --> example.com/studyMongoDb/api.UserAdd (3 handlers)
[GIN-debug] GET /UserList --> example.com/studyMongoDb/api.UserList (3 handlers)
[GIN-debug] POST /UserEditOne --> example.com/studyMongoDb/api.UserEditOne (3 handlers)
[GIN-debug] POST /UserDelete --> example.com/studyMongoDb/api.UserDelete (3 handlers)
[GIN-debug] GET /UserQuery/:key --> example.com/studyMongoDb/routers.InitRouter.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8000

客户端代码

  • 测试的客户端代码,使用python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests

data ={"name": "test111", "password": "1123456", "id": 2, "key": "t_key2"}
resp = requests.post("http://127.0.0.1:8000/UserAdd", json=data)
print(resp.text)


data ={"name": "test1131", "password": "123456811", "id": 1112, "key": "t_key1"}
resp = requests.post("http://127.0.0.1:8000/UserEditOne", json=data)
print(resp.text)
#
data ={"key": "t_key1"}
resp = requests.post("http://127.0.0.1:8000/UserDelete", json=data)
print(resp.text)


resp = requests.get("http://127.0.0.1:8000/UserQuery/t_key2/")
print(resp.text)

resp = requests.get("http://127.0.0.1:8000/UserList")
print(resp.text)