使用MongoDB官方go库操作MongoDB
官方库更新很及时,兼容性最好,官方提供的文档也比较全,社区比较活跃,因此比较建议使用这个库来进行交互。
网上的文章:
# 初始化连接
初始化连接方法如下:
package public
import (
"context"
"log"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func InitDb() *mongo.Client {
uri := "mongodb://root:123456@localhost:27017"
if uri == "" {
log.Fatal("You must set your 'MONGODB_URI' environmental variable. See\n\t https://docs.mongodb.com/drivers/go/current/usage-examples/#environment-variable")
}
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
panic(err)
}
defer func() {
if err := client.Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
return client
}
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
此处返回一个客户端对象, 然后通过里边的方法指定库和表。
指定库
:
var DB *mongo.Database
DB = public.InitDb().Database("class") // 指定库名为 class
2
3
指定表
:
table := DB.Collection("user") // 指定表名为user
# 插入
# 插入单条
首次示例提供完整示例,后续仅提供方法。
package main
import (
"context"
"learn-mongo/public"
"go.mongodb.org/mongo-driver/mongo"
)
var DB *mongo.Database
var ctx = context.Background()
func init() {
// 初始化数据库
DB = public.InitDb().Database("class")
}
// AddOne 插入单条
func AddOne() {
coll := DB.Collection("testdata")
doc := make(map[string]interface{})
doc["title"] = "test"
doc["content"] = "this is a test"
_, err := coll.InsertOne(ctx, doc)
if err != nil {
panic(err)
}
}
func main() {
AddOne()
defer func() {
if err := public.InitDb().Disconnect(context.TODO()); err != nil {
panic(err)
}
}()
}
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
其中一些已经说明过了,暂不多赘述,运行之后,可以在表中看到此条数据:
db.getCollection('testdata').find({"title":"test"})
/* 1 */
{
"_id" : ObjectId("61f2389ca0cd2ab482132e57"),
"title" : "test",
"content" : "this is a test"
}
2
3
4
5
6
7
8
# 插入多条
// AddMore 插入多条
func AddMore() {
coll := DB.Collection("testdata")
docs := []interface{}{
bson.D{{"title", "Record of a Shriveled Datum"}, {"text", "No bytes, no problem. Just insert a document, in MongoDB"}},
bson.D{{"title", "Showcasing a Blossoming Binary"}, {"text", "Binary data, safely stored with GridFS. Bucket the data"}},
}
_, err := coll.InsertMany(context.TODO(), docs)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
12
# 更新
# 更新单条
// UpdateOne 更新单条
func UpdateOne() {
coll := DB.Collection("testdata")
filter := bson.D{{"title", "test"}}
update := bson.D{{"$set", bson.D{{"avg_rating", 4.5}}}}
_, err := coll.UpdateOne(context.TODO(), filter, update)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
UpdateOne
有三个参数,传递一个 context,一个过滤规则拿到匹配的数据,一个 update 表示将要更新的内容。
此处表示在testdata
表中查询出title
为 test 的这条数据,在匹配的这条记录中添加一个avg_rating
的字段,其值为 4.5。
# 更新多条
进行操作之前,我们先准备一些测试数据:
db.testdata.insert([
{ "name" : "小A", "identify": "aaa","age": 1, "group_identify": "ops"},
{ "name" : "小B", "identify": "bbb","age": 2, "group_identify": "ops"},
{ "name" : "小C", "identify": "ccc","age": 3, "group_identify": "ops"},
{ "name" : "小D", "identify": "ddd","age": 4, "group_identify": "test"},
{ "name" : "小E", "identify": "eee","age": 5, "group_identify": "test"},
{ "name" : "小F", "identify": "fff","age": 6, "group_identify": "test"}
])
2
3
4
5
6
7
8
我的需求是更新 test 小组同学的年龄为当前的 3 倍:
// UpdateMany 更新多条
func UpdateMany() {
coll := DB.Collection("testdata")
filter := bson.D{{"group_identify", "test"}}
update := bson.D{{"$mul", bson.D{{"age", 3}}}}
_, err := coll.UpdateMany(context.TODO(), filter, update)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
MongoDB 在更新的时候,提供了一些很好用的方法供我们查询,详情参考:[[MongoDB交互时表达式与方法整理汇总#MongoDB中更新时的一些表达式]]
运行这个方法之后,可以看到这三个人的年龄更新了:
$ db.getCollection('testdata').find({"group_identify":"test"})
/* 1 */
{
"_id" : ObjectId("61f24699c8d32bc297dbecf2"),
"name" : "小D",
"identify" : "ddd",
"age" : 12.0,
"group_identify" : "test"
}
/* 2 */
{
"_id" : ObjectId("61f24699c8d32bc297dbecf3"),
"name" : "小E",
"identify" : "eee",
"age" : 15.0,
"group_identify" : "test"
}
/* 3 */
{
"_id" : ObjectId("61f24699c8d32bc297dbecf4"),
"name" : "小F",
"identify" : "fff",
"age" : 18.0,
"group_identify" : "test"
}
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
# 查询
# 查询单条
// FindOne 查询单条
func FindOnd() {
var result bson.M
table := DB.Collection("testdata")
err := table.FindOne(context.TODO(), bson.M{"title": "test"}).Decode(&result) //
if err != nil {
fmt.Printf("Error: %v\n", err)
}
fmt.Printf("%v\n", result)
v, err := encoder.Encode(result, encoder.SortMapKeys)
if err != nil {
fmt.Printf("%v\n", err)
}
fmt.Println(string(v))
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 利用 ID 查询
// FindOndAsId 基于ID查询单条
func FindOndAsId() {
var result bson.M
table := DB.Collection("user")
objid, err := primitive.ObjectIDFromHex("61f0f6d6c8d32bc297dbecd6")
if err != nil {
fmt.Printf("obj id failed: %v\n", err)
}
err = table.FindOne(context.TODO(), bson.M{"_id": objid}).Decode(&result)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
fmt.Printf("%v\n", result)
v, err := encoder.Encode(result, encoder.SortMapKeys)
if err != nil {
fmt.Printf("%v\n", err)
}
fmt.Println(string(v))
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 模糊查询
type Article struct {
Title string
Text string
}
// FindAsLike 模糊查询
func FindAsLike() {
table := DB.Collection("testdata")
findOptions := options.Find()
filter := bson.D{}
filter = append(filter, bson.E{
Key: "title",
Value: bson.M{"$regex": primitive.Regex{Pattern: ".*" + "a" + ".*", Options: "i"}}}) //i 表示不区分大小写
cus, err := table.Find(ctx, filter, findOptions)
if err != nil {
fmt.Printf("find failed: %v\n", err)
}
defer func(cus *mongo.Cursor, ctx context.Context) {
err := cus.Close(ctx)
if err != nil {
return
}
}(cus, ctx)
list := make([]*Article, 0)
for cus.Next(ctx) {
article := new(Article)
err := cus.Decode(&article)
if err != nil {
fmt.Printf("decode failed: %v\n", err)
// return nil, tools.NewMongoError(err)
}
list = append(list, article)
}
fmt.Println("results: ", list)
for _, v := range list {
fmt.Println(v)
}
}
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
# 查询多条
// FindMany 查询多条
func FindMany() {
/*
插入测试数据
db.testdata.insert([
{ "name" : "小A", "identify": "aaa","age":1},
{ "name" : "小B", "identify": "bbb","age":2},
{ "name" : "小C", "identify": "ccc","age":3},
{ "name" : "小D", "identify": "ddd","age":4},
{ "name" : "小E", "identify": "eee","age":5},
{ "name" : "小F", "identify": "fff","age":6},
])
*/
table := DB.Collection("testdata")
filter := bson.D{{"age", bson.D{{"$lte", 3}}}} // 查询年龄小于等于3的,这里特别有意思,能够使用$lte这种方法,类似这样的,MongoDB还提供了很多其他的查询方法,比如$gt等等
cursor, err := table.Find(ctx, filter)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
var results []bson.M
if err = cursor.All(context.TODO(), &results); err != nil {
panic(err)
}
for _, result := range results {
v, err := encoder.Encode(result, encoder.SortMapKeys)
if err != nil {
fmt.Printf("%v\n", err)
}
fmt.Println(string(v))
}
}
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
就像更新的时候一样,查询的时候也有一些表达式可供使用。更多参考:[[MongoDB交互时表达式与方法整理汇总#mongodb中查询的表达式介绍]]
# 替换
# 替换单条
ReplaceOne()
您可以使用该方法替换集合中的文档。这个方法针对于 cmdb 场景更加合适。
首先添加一条测试数据:
db.testdata.insert([
{ "name" : "小A", "identify": "aaa","content":"this is aaa"},
])
2
3
然后基于 identify 完全 replace 这条记录:
// ReplaceOne 替换单条
func ReplaceOne() {
coll := DB.Collection("testdata")
filter := bson.D{{"identify", "aaa"}}
replacement := bson.D{{"name", "小A-r"}, {"identify", "aaa"}, {"content", "this is aaa replace"}}
_, err := coll.ReplaceOne(context.TODO(), filter, replacement)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
# 删除
# 删除单条
// DeleteOne 删除单条
func DeleteOne() {
coll := DB.Collection("testdata")
filter := bson.D{{"identify", "aaa"}}
_, err := coll.DeleteOne(context.TODO(), filter)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
# 删除多条
同样,在删除的时候,我们调用 Delete 方法,传递过滤条件,这个时候也可以删除指定过滤的条件。
添加测试数据:
db.testdata.insert([
{ "name" : "小A", "identify": "aaa","age": 1, "group_identify": "ops"},
{ "name" : "小B", "identify": "bbb","age": 2, "group_identify": "ops"},
{ "name" : "小C", "identify": "ccc","age": 3, "group_identify": "ops"},
{ "name" : "小D", "identify": "ddd","age": 4, "group_identify": "test"},
{ "name" : "小E", "identify": "eee","age": 5, "group_identify": "test"},
{ "name" : "小F", "identify": "fff","age": 6, "group_identify": "test"}
])
2
3
4
5
6
7
8
我们删除年龄大于 3 岁的记录:
// DeleteMany 删除多条
func DeleteMany() {
coll := DB.Collection("testdata")
filter := bson.D{{"age", bson.D{{"$gt", 3}}}}
_, err := coll.DeleteMany(context.TODO(), filter)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
然后可以看到只剩下前三条了:
$ db.getCollection('testdata').find({})
/* 1 */
{
"_id" : ObjectId("61f24a4dc8d32bc297dbed02"),
"name" : "小A",
"identify" : "aaa",
"age" : 1.0,
"group_identify" : "ops"
}
/* 2 */
{
"_id" : ObjectId("61f24a4dc8d32bc297dbed03"),
"name" : "小B",
"identify" : "bbb",
"age" : 2.0,
"group_identify" : "ops"
}
/* 3 */
{
"_id" : ObjectId("61f24a4dc8d32bc297dbed04"),
"name" : "小C",
"identify" : "ccc",
"age" : 3.0,
"group_identify" : "ops"
}
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
# 批量
BulkWrite()
您可以使用该方法对集合执行批量写入操作 。
官方给的示例如下:
coll := DB.Collection("testdata")
models := []mongo.WriteModel{
mongo.NewReplaceOneModel().SetFilter(bson.D{{"title", "Record of a Shriveled Datum"}}).
SetReplacement(bson.D{{"title", "Dodging Greys"}, {"text", "When there're no matches, no longer need to panic. You can use upsert"}}),
mongo.NewUpdateOneModel().SetFilter(bson.D{{"title", "Dodging Greys"}}).
SetUpdate(bson.D{{"$set", bson.D{{"title", "Dodge The Greys"}}}}),
}
opts := options.BulkWrite().SetOrdered(true)
results, err := coll.BulkWrite(context.TODO(), models, opts)
2
3
4
5
6
7
8
9
10
- 匹配一个文档,其中
title
是“收缩基准的记录”并将其替换为新文档 - 匹配其中
title
为“Dodging Greys”的文档并将该值更新为'Dodge The Greys'
通常不太会用到这种批量的方式。
# 汇总
# 两种方式
EstimatedDocumentCount()
:获得集合中文档数量的近似值CountDocuments()
:获得集合中文档的确切数量
// Count 查询数量
func Count() {
coll := DB.Collection("testdata")
filter := bson.D{{"group_identify", "test"}}
estCount, estCountErr := coll.EstimatedDocumentCount(context.TODO())
if estCountErr != nil {
panic(estCountErr)
}
count, err := coll.CountDocuments(context.TODO(), filter)
if err != nil {
panic(err)
}
fmt.Println(estCount, count)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 关联
# 关联查询
基于 MongoDB 原始语句的查询操作流程参考:[[MongoDB关联查询的学习以及实践]]
现在 golang 中使用如下方式实现关联查询:
func Aggregate() {
query := []bson.M{{
"$lookup": bson.M{
"from": "user",
"localField": "identify",
"foreignField": "groupIdentify",
"as": "output",
}}}
coll := DB.Collection("group")
cur, err := coll.Aggregate(context.TODO(), query)
if err != nil {
fmt.Printf("aggregate failed:%v\n", err)
}
defer cur.Close(context.TODO())
for cur.Next(context.TODO()) {
// 当数据没有映射到结构体时,可以通过map查询
one := make(map[string]interface{})
err := cur.Decode(&one)
if err != nil {
fmt.Printf("%v\n", err)
}
v, err := encoder.Encode(one, encoder.SortMapKeys)
if err != nil {
fmt.Printf("%v\n", err)
}
fmt.Println(string(v))
}
}
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
运行结果如下:
$ go run main.go | jq
{
"_id": "61f0f6c2c8d32bc297dbecd2",
"identify": "yunweizu",
"name": "运维组",
"output": [
{
"_id": "61f0f6d6c8d32bc297dbecd4",
"groupIdentify": "yunweizu",
"identify": "aaa",
"name": "小A"
},
{
"_id": "61f0f6d6c8d32bc297dbecd5",
"groupIdentify": "yunweizu",
"identify": "bbb",
"name": "小B"
},
{
"_id": "61f0f6d6c8d32bc297dbecd6",
"groupIdentify": "yunweizu",
"identify": "ccc",
"name": "小C"
}
]
}
{
"_id": "61f0f6c2c8d32bc297dbecd3",
"identify": "kefuzu",
"name": "客服组",
"output": [
{
"_id": "61f0f6d6c8d32bc297dbecd7",
"groupIdentify": "kefuzu",
"identify": "ddd",
"name": "小D"
},
{
"_id": "61f0f6d6c8d32bc297dbecd8",
"groupIdentify": "kefuzu",
"identify": "eee",
"name": "小E"
},
{
"_id": "61f0f6d6c8d32bc297dbecd9",
"groupIdentify": "kefuzu",
"identify": "fff",
"name": "小F"
}
]
}
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
如果想要过滤指定分组,则用如下方式:
func Aggregate() {
query := []bson.M{{
"$lookup": bson.M{
"from": "user",
"localField": "identify",
"foreignField": "groupIdentify",
"as": "output",
}},
{"$match": bson.M{"identify": "yunweizu"}},
}
coll := DB.Collection("group")
cur, err := coll.Aggregate(context.TODO(), query)
if err != nil {
fmt.Printf("aggregate failed:%v\n", err)
}
defer cur.Close(context.TODO())
for cur.Next(context.TODO()) {
// 当数据没有映射到结构体时,可以通过map查询
one := make(map[string]interface{})
err := cur.Decode(&one)
if err != nil {
fmt.Printf("%v\n", err)
}
v, err := encoder.Encode(one, encoder.SortMapKeys)
if err != nil {
fmt.Printf("%v\n", err)
}
fmt.Println(string(v))
}
}
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
运行结果如下:
$ go run main.go | jq
{
"_id": "61f0f6c2c8d32bc297dbecd2",
"identify": "yunweizu",
"name": "运维组",
"output": [
{
"_id": "61f0f6d6c8d32bc297dbecd4",
"groupIdentify": "yunweizu",
"identify": "aaa",
"name": "小A"
},
{
"_id": "61f0f6d6c8d32bc297dbecd5",
"groupIdentify": "yunweizu",
"identify": "bbb",
"name": "小B"
},
{
"_id": "61f0f6d6c8d32bc297dbecd6",
"groupIdentify": "yunweizu",
"identify": "ccc",
"name": "小C"
}
]
}
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
基本上和写原生语句差不多了。
# 字段
# 添加字段
# 添加单条
单个字段利用 $push
指令进行添加:
// UpdateOneField 添加单个字段
func UpdateOneField() {
coll := DB.Collection("testdata")
objid, err := primitive.ObjectIDFromHex("62159551120b25bd2c801b09")
if err != nil {
fmt.Printf("%v\n", err)
}
filter := bson.M{"_id": objid}
updata := bson.M{"$push": bson.M{"link_data": bson.M{"field_identify": "1", "model_data_id": "5"}}}
_, err = coll.UpdateOne(ctx, filter, updata)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
添加之后效果如下:
/* 1 */
{
"_id" : ObjectId("62159551120b25bd2c801b09"),
"title" : "Record of a Shriveled Datum",
"text" : "No bytes, no problem. Just insert a document, in MongoDB",
"link_data" : [
{
"field_identify" : "1",
"model_data_id" : "5"
},
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
注意这里使用$push
有一个问题就是,如果一个值重复往一个数组里添加,那么在 MongoDB 中会重复添加,效果如下:
$ db.getCollection('test').find({})
/* 1 */
{
"_id" : ObjectId("61ef6e9d78a349e08e8f50da"),
"test" : "test"
}
$ db.test.update({ "test" : "test" },{ $push: { label_list: "1" } })
再运行一次
$ db.test.update({ "test" : "test" },{ $push: { label_list: "1" } })
然后查询
$ db.getCollection('test').find({})
/* 1 */
{
"_id" : ObjectId("61ef6e9d78a349e08e8f50da"),
"test" : "test",
"label_list" : [
"1",
"1"
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
此时可以改用$addToSet
,功效与$push
一致,只不过$addToSet
会自动检测,如果要添加的值已在列表,就不会重复添加:
$ db.getCollection('test').find({})
/* 1 */
{
"_id" : ObjectId("61ef6e9d78a349e08e8f50da"),
"test" : "test"
}
$ db.test.update({ "test" : "test" },{ $addToSet: { label_list: "1" } })
再运行一次
$ db.test.update({ "test" : "test" },{ $addToSet: { label_list: "1" } })
然后查询
$ db.getCollection('test').find({})
/* 1 */
{
"_id" : ObjectId("61ef6e9d78a349e08e8f50da"),
"test" : "test",
"label_list" : [
"1"
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
可以看到这里虽然同样执行了两次,但是数据只会插入一次,适合那种进关联一次的场景。
# 添加多条
多个字段利用 $push
和$each
结合的方式进行添加,each 允许我们添加一个数组的内容:
// UpdateOneField 添加单个字段数据
func UpdateOneField() {
coll := DB.Collection("testdata")
objid, err := primitive.ObjectIDFromHex("62159551120b25bd2c801b09")
if err != nil {
fmt.Printf("%v\n", err)
}
filter := bson.M{"_id": objid}
linkData := []map[string]string{
{
"field_identify": "eryajf_guanliandd",
"model_data_id": "6215aaf220ea934fb727096c",
},
{
"field_identify": "eryajf_guanliandd",
"model_data_id": "6215aaf220ea934fbaaaaaaa",
},
}
updata := bson.M{"$push": bson.M{"link_data": bson.M{"$each": linkData, "$position": 0}}}
_, err = coll.UpdateOne(ctx, filter, updata)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
添加之后效果如下:
/* 1 */
{
"_id" : ObjectId("62159551120b25bd2c801b09"),
"title" : "Record of a Shriveled Datum",
"text" : "No bytes, no problem. Just insert a document, in MongoDB",
"link_data" : [
{
"field_identify" : "eryajf_guanliandd",
"model_data_id" : "6215aaf220ea934fb727096c"
},
{
"field_identify" : "eryajf_guanliandd",
"model_data_id" : "6215aaf220ea934fbaaaaaaa"
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
同样,这里使用$push
存在一个问题,就是相同的数据,多次添加的时候,会多次存储,因此这里可以借助$addToSet
的能力,实现自动去重的效果。
关于$push
与$addToSet
的异同,详情可参考这篇:golang 使用$push和$addToSet 往数组添加字段的异同 (opens new window)
# 删除字段
# 删除单条
单个字段利用 $pull
指令进行删除:
// DeleteOneField 删除单个字段数据
func DeleteOneField() {
coll := DB.Collection("testdata")
objid, err := primitive.ObjectIDFromHex("62159551120b25bd2c801b09")
if err != nil {
fmt.Printf("%v\n", err)
}
filter := bson.M{"_id": objid}
updata := bson.M{"$pull": bson.M{"link_data": bson.M{"field_identify": "1", "model_data_id": "5"}}}
_, err = coll.UpdateOne(ctx, filter, updata)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 删除多条
删除多条记录利用$pullAll
指令进行删除:
// DeleteManyField 删除多条记录
func DeleteManyField() {
coll := DB.Collection("testdata")
objid, err := primitive.ObjectIDFromHex("62159551120b25bd2c801b09")
if err != nil {
fmt.Printf("%v\n", err)
}
filter := bson.M{"_id": objid}
linkData := []map[string]string{
{
"field_identify": "eryajf_guanliandd",
"model_data_id": "6215aaf220ea934fb727096c",
},
{
"field_identify": "eryajf_guanliandd",
"model_data_id": "6215aaf220ea934fbaaaaaaa",
},
}
updata := bson.M{"$pullAll": bson.M{"link_data_testa": linkData}}
_, err = coll.UpdateOne(ctx, filter, updata)
if err != nil {
panic(err)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25