Go 实现 CRUD 操作

miomiora大约 4 分钟MongoDBGoMongoDB数据库

怎么忍得住不用 Go 来试试的,选用的包为 github.com/mongodb/mongo-go-driver

预备

在正式开始之前,有一个东西在这个包中是必须得了解的,那就是 bson 以下是官方注释

类型说明示例
bson.DBSON文档的有序表示,在需要顺序的场合比较重要,也就是 MongoDB 的命令bson.D{{"foo", "bar"}, {"hello","world"}, {"pi", 3.14159}}
bson.E主要作为bson.D的一个元素,通常在一个D中跟使用bson.E{"foo", "bar"}
bson.MBSON文档的无序表示map[string]interface{}bson.M{"foo": "bar", "hello": "world", "pi": 3.14159}
bson.ABSON文档数组的有序表示bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}}
// 下面go使用到的结构体
type User struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

连接

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
defer func() {
	if err = client.Disconnect(ctx); err != nil {
		panic(err)
	}
}()

选择集合

collection := client.Database("miodb").Collection("user")

  • 插入单条数据
InsertOne(ctx context.Context, document interface{}, opts ...*options.InsertOneOptions) (*InsertOneResult, error)

示例:因为传参的 documentinterface{} 的数据类型,直接用结构体就可以了,用 bson 构建文档数据也可以

res, err := collection.InsertOne(ctx, User{"miomiora1", 19})
fmt.Println(res.InsertedID)
  • 插入多条数据
InsertMany(ctx context.Context, documents []interface{}, opts ...*options.InsertManyOptions) (*InsertManyResult, error)

插入多条数据的时候有说法了,因为传参的 document[]interface{} 也就是说如果想直接用结构体切片是不能直接传进去的,下面提供两种方法:

// 创建一个新的[]interface{}的切片,并循环把结构体切片给放进去
userList := []User{{"miomiora1", 19}, {"miomiora2", 20}, {"miomiora3", 21}}

var userInterface []interface{}
for _, u := range userList {
	userInterface = append(userInterface, interface{}(u))
}

res, err := collection.InsertMany(ctx, userInterface)
id := res.InsertedIDs
fmt.Println(id)

过滤器

在接下来的 改、查、删 等操作中,都会使用到过滤器,这里的过滤器就推荐使用 bson 来操作了,在前面提到的 bson 有序以及无序的问题,如果是顺序不重要的语句,可以使用M来操作。

  • 不等于

bson.M{"name": bson.M{"$ne": "miomiora"}}

  • 大于

bson.M{"age": bson.M{"$gt": 10}}

  • 大于等于

bson.M{"age": bson.M{"$gte": 10}}

  • 小于

bson.M{"age": bson.M{"$lt": 10}}

  • 小于等于

bson.M{"age": bson.M{"$lte": 10}}

  • 包含

bson.M{"name": bson.M{"$in": []string{"hanamaru", "yui"}}

  • 不包含

bson.M{"name": bson.M{"$nin": []string{"hanamaru", "yui"}}

bson.M{"$or": []bson.M{{"name": "miomiora"}, {"age": bson.M{"$gt": 10}}}}

  • 正则
表达式说明
^匹配以指定模式开头的字符串
$匹配以指定模式结尾的字符串
.匹配除换行符以外的任何单个字符
*匹配前面的模式零次或多次
+匹配前面的模式一次或多次
?匹配前面的模式零次或一次
[]匹配括号中的任何字符
\d匹配任何数字字符
\w匹配任何字母数字字符
\s匹配任何空格字符
\D匹配任何非数字字符
\W匹配任何非字母数字字符
\S匹配任何非空格字符

示例:以 m 开头,中间可以出现任何字母数字字符,并且以 1 结尾

bson.M{"name": bson.M{"$regex": "^m\\w*1$"}}

  • 全部文档

bson.D{{}}

  • 查找单条文档
FindOne(ctx context.Context, filter interface{}, opts ...*options.FindOneOptions) *SingleResult
  • 查找多条文档
Find(ctx context.Context, filter interface{}, opts ...*options.FindOptions) (cur *Cursor, err error)
// 定义过滤器
filter := bson.M{"$or": []bson.M{{"name": "miomiora"}, {"age": bson.M{"$gt": 10}}}}

// 根据过滤器查找多条文档
cur, err := collection.Find(ctx, filter)
if err != nil {
	fmt.Println("collection.Find(ctx, filter) err ", err.Error())
	return
}
// 关闭游标
defer func(cur *mongo.Cursor, ctx context.Context) {
	err := cur.Close(ctx)
	if err != nil {
		panic(err)
	}
}(cur, ctx)

// 从游标中获取查找到的数据,并存入 userList中
var userList []User
err = cur.All(ctx, &userList)
if err != nil {
	fmt.Println("cur.All err ", err.Error())
	return
}

fmt.Println(userList)

  • 修改单条
UpdateOne(ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*UpdateResult, error)

修改的 update 参数也可以直接传入结构体,但没指定的字段会初始化为零值(不推荐)

  • 修改多条
UpdateMany(ctx context.Context, filter interface{}, update interface{}, opts ...*options.UpdateOptions) (*UpdateResult, error)
// 定义过滤器,这里的意思为 name 包含 miomiora 的文档
filter := bson.M{"name": bson.M{"$regex": "miomiora"}}

// 定义更新的数据,意为把 name 包含 miomiora 的文档中的 name 都改成 “批量修改”
update := bson.M{"$set": bson.M{"name": "批量修改"}}
many, err := collection.UpdateMany(ctx, filter, update)
fmt.Println(many)

  • 删除单条
DeleteOne(ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*DeleteResult, error)
  • 删除多条
DeleteMany(ctx context.Context, filter interface{}, opts ...*options.DeleteOptions) (*DeleteResult, error)
// 删除刚刚批量更新的文档,以及 name 为 yui 的文档
filter := bson.M{"$or": []bson.M{
	{"name": "批量修改"},
	{"name": "yui"},
}}

many, err := collection.DeleteMany(ctx, filter)
if err != nil {
	fmt.Println("collection.DeleteMany(ctx, filter) err ", err.Error())
	return
}

fmt.Println(many)
上次编辑于:
贡献者: miomiora