golang操作mongo

本文采用mongo-driver/mongo驱动操作数据库

设计mongo插件结构

将代码分为如下结构
model : odm模型,主要是映射为数据库存储的表结构
constants : 存储一些常量
config : mongo的配置信息,比如空闲时长,连接数,超时时间等
mongodb : 实现了mongo的连接和关闭等功能。

目录结构如下
1.png

mongo的连接和断开

在mongodb.go中实现了连接和断开操作
初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var (
DB *Database
)

type Database struct {
Mongo *mongo.Client
}

//初始化
func Init() {
DB = &Database{
Mongo: SetConnect(),
}
}

连接数据库

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
func SetConnect() *mongo.Client {

var retryWrites bool = false

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
clientOptions := options.Client().SetHosts(config.GetConf().MongoConf.Hosts).
SetMaxPoolSize(config.GetConf().MongoConf.MaxPoolSize).
SetHeartbeatInterval(constants.HEART_BEAT_INTERVAL).
SetConnectTimeout(constants.CONNECT_TIMEOUT).
SetMaxConnIdleTime(constants.MAX_CONNIDLE_TIME).
SetRetryWrites(retryWrites)

//设置用户名和密码
username := config.GetConf().MongoConf.Username
password := config.GetConf().MongoConf.Password

if len(username) > 0 && len(password) > 0 {
clientOptions.SetAuth(options.Credential{Username: username, Password: password})
}

client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
fmt.Println(err)
}

// Check the connection
err = client.Ping(context.TODO(), nil)

if err != nil {
fmt.Println(err)
}

fmt.Println("Connected to MongoDB!")

return client
}

关闭数据库

1
2
3
4
5
func Close() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
DB.Mongo.Disconnect(ctx)
}

在model中定义模型

定义的模型加上bson标签,这样可以映射到数据库里了

1
2
3
4
5
6
7
type UserData struct {
Id string `bson:"_id,omitempty" json:"id"`
Name string `bson:"name" json:"name"`
Number int `bson:"number" json:"number"`
Age int `bson:"age" json:"age"`
BirthMonth int `bson:"birthMonth" json:"birthMonth"`
}

在main函数中实现一些demo

在main函数中实现一些demo,包括单条插入,多条插入,单条更新,多条更新,分组查询,分页查询
1 单条插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//单条插入
func insertOne() {
client := mongodb.DB.Mongo
// 获取数据库和集合
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)
userdata := model.UserData{}
userdata.Age = 13
userdata.BirthMonth = 11
userdata.Number = 3
userdata.Name = "zack"
ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
// 插入一条数据
insertOneResult, err := collection.InsertOne(ctx, &userdata)
if err != nil {
fmt.Println("insert one error is ", err)
return
}
log.Println("collection.InsertOne: ", insertOneResult.InsertedID)
//将objectid转换为string
docId := insertOneResult.InsertedID.(primitive.ObjectID)
recordId := docId.Hex()
fmt.Println("insert one ID str is :", recordId)
}

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
//多条插入
func insertMany() {
ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
client := mongodb.DB.Mongo
// 获取数据库和集合
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)
userdata1 := model.UserData{}
userdata1.Age = 20
userdata1.BirthMonth = 11
userdata1.Number = 4
userdata1.Name = "Lilei"

userdata2 := model.UserData{}
userdata2.Age = 20
userdata2.BirthMonth = 12
userdata2.Number = 5
userdata2.Name = "HanMeiMei"

var list []interface{}
list = append(list, &userdata1)
list = append(list, &userdata2)
result, err := collection.InsertMany(ctx, list)
if err != nil {
fmt.Println("insert many error is ", err)
}
fmt.Println("insert many success, res is ", result.InsertedIDs)
}

3 查找单条

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 findOne() {

client := mongodb.DB.Mongo
// 获取数据库和集合
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)
filter := bson.M{"name": "HanMeiMei"}

ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
singleResult := collection.FindOne(ctx, filter)
if singleResult == nil || singleResult.Err() != nil {
fmt.Println("find one error is ", singleResult.Err().Error())
return
}

userData := &model.UserData{}
err := singleResult.Decode(userData)
if err != nil {
fmt.Println("find one failed error is ", err)
return
}

fmt.Println("find one success, res is ", userData)
}

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
26
27
28
29
30
//查询多个结果集,用cursor
func findMany() {
client := mongodb.DB.Mongo
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)

ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
filter := bson.M{"birthMonth": bson.M{"$lte": 12}}

cursor, err := collection.Find(ctx, filter)
if err != nil {
fmt.Println("find res failed , error is ", err)
return
}
defer cursor.Close(context.Background())

result := make(map[string]*model.UserData)
for cursor.Next(context.Background()) {
ud := &model.UserData{}
err := cursor.Decode(ud)
if err != nil {
fmt.Println("decode error is ", err)
continue
}
result[ud.Name] = ud
}

fmt.Println("success is ", result)
return
}

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
//更新
func updateOne() {
client := mongodb.DB.Mongo
collection, _ := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION).Clone()
ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
/*
oid, err := primitive.ObjectIDFromHex(obj.RecordId)
if err != nil {
logging.Logger.Info("convert string from object failed")
return err
}
filter := bson.M{"_id": oid}
*/
filter := bson.M{"name": "zack"}
value := bson.M{"$set": bson.M{
"number": 1024}}

_, err := collection.UpdateOne(ctx, filter, value)
if err != nil {
fmt.Println("update user data failed, err is ", err)
return
}
fmt.Println("update success !")
return
}

6 更新多条

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//更新多条记录
func updateMany() {
client := mongodb.DB.Mongo
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)

ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
var names = []string{"zack", "HanMeiMei"}
filter := bson.M{"name": bson.M{"$in": names}}

value := bson.M{"$set": bson.M{"birthMonth": 3}}
result, err := collection.UpdateMany(ctx, filter, value)
if err != nil {
fmt.Println("update many failed error is ", err)
return
}
fmt.Println("update many success !, result is ", result)
return
}

7 分组查询

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
//分组查询
func findGroup() {
client := mongodb.DB.Mongo
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)

ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()
//复杂查询,先匹配后分组
pipeline := bson.A{
bson.M{
"$match": bson.M{"birthMonth": 3},
},
bson.M{"$group": bson.M{
"_id": bson.M{"birthMonthUid": "$birthMonth"},
"totalCount": bson.M{"$sum": 1},
"nameG": bson.M{"$min": "$name"},
"ageG": bson.M{"$min": "$age"},
},
},

//bson.M{"$sort": bson.M{"time": 1}},
}
fmt.Println("pipeline is ", pipeline)

cursor, err := collection.Aggregate(ctx, pipeline)
fmt.Println("findGroup cursor is ", cursor)
if err != nil {
fmt.Printf("dao.findGroup collection.Aggregate() error=[%s]\n", err)
return
}

for cursor.Next(context.Background()) {
doc := cursor.Current

totalCount, err_2 := doc.LookupErr("totalCount")
if err_2 != nil {
fmt.Printf("dao.findGroup totalCount err_2=[%s]\n", err_2)
return
}

nameData, err_4 := doc.LookupErr("nameG")
if err_4 != nil {
fmt.Printf("dao.findGroup insertDateG err_4=[%s]\n", err_4)
return
}

ageData, err_5 := doc.LookupErr("ageG")
if err_5 != nil {
fmt.Printf("dao.findGroup ageG err_5=[%s]\n", err_5)
continue
}
fmt.Println("totalCount is ", totalCount)
fmt.Println("nameData is ", nameData)
fmt.Println("ageData is ", ageData)
}
}

8 分页查询

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
//分页查询
func limitPage() {
client := mongodb.DB.Mongo
collection := client.Database(constants.DB_DATABASES).Collection(constants.DB_COLLECTION)

ctx, cancel := context.WithTimeout(context.Background(), constants.QUERY_TIME_OUT)
defer cancel()

filter := bson.M{"age": bson.M{"$gte": 0}}

SORT := bson.D{{"number", -1}}
findOptions := options.Find().SetSort(SORT)
//从第1页获取,每次获取10条
skipTmp := int64((1 - 1) * 10)
limitTmp := int64(10)
findOptions.Skip = &skipTmp
findOptions.Limit = &limitTmp
cursor, err := collection.Find(ctx, filter, findOptions)
defer cursor.Close(context.Background())
if err != nil {
fmt.Println("limit page error is ", err)
return
}

for cursor.Next(context.Background()) {
ud := &model.UserData{}
err := cursor.Decode(ud)
if err != nil {
fmt.Println("user data decode error is ", err)
continue
}

fmt.Println("user data is ", ud)

}
}

源码地址

可以下载源码,二次封装放到项目中直接使用
https://github.com/secondtonone1/golang-/tree/master/gomongo

感谢关注公众号

wxgzh.jpg