连接MongoDB数据库
在Go语言中连接MongoDB,你可以使用官方的MongoDB Go Driver,即mongo-go-driver
。这个库提供了丰富的API来与MongoDB数据库进行交互。以下是一个基本的步骤和示例代码,展示如何在Go程序中连接到MongoDB数据库。
步骤 1: 安装 MongoDB Go Driver
首先,你需要安装MongoDB Go Driver。在你的Go项目目录下,通过运行以下命令来安装:
1
2
go get go.mongodb.org/mongo-driver/mongo
go get go.mongodb.org/mongo-driver/mongo/options
步骤 2: 编写Go代码连接MongoDB
接下来,你可以编写Go代码来连接到MongoDB数据库。以下是一个简单的示例,展示了如何连接到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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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"
)
func main () {
// 设置MongoDB连接字符串
// 格式通常为:mongodb://username:password@host:port/dbname
uri := "mongodb://admin:admin@localhost:27017"
clientOptions := options . Client (). ApplyURI ( uri )
// 连接到MongoDB
client , err := mongo . Connect ( context . TODO (), clientOptions )
if err != nil {
log . Fatal ( err )
}
// 检查连接
err = client . Ping ( context . TODO (), nil )
if err != nil {
log . Fatal ( err )
}
fmt . Println ( "Connected to MongoDB!" )
// 选择数据库和集合
collection := client . Database ( "testdb" ). Collection ( "testcol" )
// 插入文档
insertResult , err := collection . InsertOne ( context . TODO (), bson . D {{ "name" , "MongoDB" }, { "type" , "database" }, { "count" , 1 }, { "info" , bson . D {{ "x" , 203 }, { "y" , 102 }}}}})
if err != nil {
log . Fatal ( err )
}
fmt . Println ( "Inserted a single document: " , insertResult . InsertedID )
// 查询文档
var result bson . M
err = collection . FindOne ( context . TODO (), bson . D {{ "name" , "MongoDB" }}). Decode ( & result )
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "Found a single document: %+v\n" , result )
// 关闭MongoDB连接
err = client . Disconnect ( context . TODO ())
if err != nil {
log . Fatal ( err )
}
fmt . Println ( "Connection to MongoDB closed." )
}
context.Context参数
在MongoDB Go Driver中,许多操作都接受一个context.Context
参数。
可以使用context.Context
来管理连接MongoDB的请求生命周期,主要是为了能够控制操作的执行时间,防止长时间运行的操作阻塞程序,同时也能够在需要时取消这些操作。
下面是一个具体的示例,展示如何在与MongoDB交互时使用context.Context
:
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
func main () {
// 创建一个新的MongoDB客户端,使用默认的Context
client , _ := mongo . Connect ( context . Background (), options . Client (). ApplyURI ( "mongodb://localhost:27017" ))
// 选择数据库和集合
collection := client . Database ( "mydatabase" ). Collection ( "users" )
// 创建一个带有时限的Context,用于查询操作
ctx , cancel := context . WithTimeout ( context . Background (), 5 * time . Second )
defer cancel ()
// 使用Context发起查询,查找年龄大于30的用户
filter := bson . M { "age" : bson . M { "$gt" : 30 }}
cursor , err := collection . Find ( ctx , filter )
if err != nil {
if ctx . Err () == context . DeadlineExceeded {
fmt . Println ( "Query timed out" )
} else {
log . Fatal ( err )
}
return
}
defer cursor . Close ( ctx )
// 遍历查询结果
for cursor . Next ( ctx ) {
var user map [ string ] interface {}
if err := cursor . Decode ( & user ); err != nil {
log . Fatal ( err )
}
fmt . Println ( user )
}
// 检查是否有错误发生
if err := cursor . Err (); err != nil {
log . Fatal ( err )
}
}
关键点解析
创建Context :使用context.WithTimeout
创建一个带有时限的Context,这个Context将在5秒后超时。
发起MongoDB操作 :将创建的限时Context传递给collection.Find
方法,这样查询操作将受到超时限制。
处理超时 :如果查询操作超时,ctx.Err()
将返回context.DeadlineExceeded
错误,可以通过检查这个错误来判断操作是否因超时而被取消。
取消Context :在查询操作完成后,调用cancel
函数来取消Context,释放资源。
bson.D和bson.M
在MongoDB的Go语言驱动(mongo-go-driver)中,bson.D
和bson.M
是两种用于表示BSON文档的Go类型。BSON(Binary JSON)是MongoDB中用于存储文档的一种二进制格式的JSON变种。这两种类型各有其用途和优势,下面详细说明它们之间的差异和用法。
bson.D
bson.D
是一个文档类型,用于表示有序的键值对序列。它是一个[]bson.E
的别名,其中bson.E
是一个结构体,包含Key
(字符串类型,键名)和Value
(interface{}
类型,键值)两个字段。bson.D
特别适用于那些需要明确控制BSON文档中字段顺序的场景,因为它保留了元素的插入顺序。
示例 :
1
2
3
4
5
6
7
8
func main () {
doc := bson . D {
{ "name" , "John Doe" },
{ "age" , 30 },
{ "isStudent" , false },
}
// ... 后续操作,如插入文档到MongoDB等
}
bson.M
bson.M
是一个映射类型,用于表示无序的键值对集合。它本质上是map[string]interface{}
的别名,因此使用起来非常类似于Go中的标准map。由于它是基于map的,所以它不保留元素的插入顺序。bson.M
在编写快速原型或当字段顺序不重要时非常有用。
示例 :
1
2
3
4
5
6
7
8
func main () {
doc := bson . M {
"name" : "Jane Doe" ,
"age" : 28 ,
"isStudent" : true ,
}
// ... 后续操作,如插入文档到MongoDB等
}
使用场景差异
当你需要明确控制BSON文档中字段的顺序时 ,应该使用bson.D
。这在某些情况下是必要的,比如MongoDB的某些操作可能会依赖于字段的顺序(尽管这种情况较少)。
当你不需要关心字段顺序,或者只是想快速编写代码时 ,bson.M
是一个更自然、更简洁的选择。
查询
数据库名称为test
,集合名称为stus
,文档的结构为:
1
2
3
4
5
6
7
8
9
10
11
12
{
"_id" : ObjectId ( "66869ef8abdfde5a12c58d50" ),
"name" : "Alice" ,
"age" : 26 ,
"gender" : "female" ,
"class" : "computer science 1" ,
"score" : 85 ,
"hobbies" : {
"cities" : [ "beijing" , "shanghai" , "shenzhen" ],
"sports" : [ "basketball" , "tennis" ]
}
}
先创建Go语言的映射结构体:
1
2
3
4
5
6
7
8
type Student struct {
Name string `bson:"name"`
Age int `bson:"age"`
Gender string `bson:"gender"`
Class string `bson:"class"`
Score int `bson:"score"`
// 其他字段...
}
然后在main
函数中连接数据库:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func main () {
client , err := connectMongodb ()
if err != nil {
panic ( err )
}
defer func ( client * mongo . Client , ctx context . Context ) {
err := client . Disconnect ( ctx )
if err != nil {
panic ( err )
}
fmt . Println ( "Connection to MongoDB closed." )
}( client , context . TODO ())
fmt . Println ( "Connected to MongoDB!" )
// 获取集合
collection := client . Database ( "test" ). Collection ( "stus" )
// 后面示例的代码写在后面
// ......
}
mongo.Collection.Find
方法是查询文档的主要方式之一。
方法签名
Go 语言中,mongo.Collection.Find
方法的基本签名如下:
1
2
func ( coll * Collection ) Find ( ctx context . Context , filter interface {},
opts ...* options . FindOptions ) ( cur * Cursor , err error )
其中:
ctx context.Context
:上下文对象,用于控制请求的生命周期,例如设置超时或取消请求。
filter interface{}
:查询过滤器,可以是任何实现了 bson.Raw
或 Document
接口的对象,通常是一个 map[string]interface{} 结构,用于指定查询条件。
*options.FindOptions
:一个可选的参数,用于指定查询的附加选项,如排序、限制结果数量、跳过某些结果等。
返回值
Find
方法返回一个 *mongo.Cursor
对象,这是一个游标,可以迭代地访问查询结果中的文档。
示例1:查询 name=“Tom” 且 age>30 的第一个文档
既可以使用bson.D
,也可以使用bson.M
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 构建查询条件
// 使用bson.D类型
query1 := bson . D {
{ "name" , "Tom" },
{ "age" , bson . D {{ "$gt" , 30 }}},
}
// 也可以使用bson.M类型
//query1 := bson.M{
// "name": "Tom",
// "age": bson.M{"$gt": 30},
//}
// 将查询的结果保存到stu中
var stu Student
err = collection . FindOne ( context . TODO (), query1 ). Decode ( & stu )
if err != nil {
log . Fatal ( err )
}
fmt . Println ( stu )
FindOne()
方法返回的是*mongo.SingleResult
类型,可以使用Decode()
方法,将其保存到Student
类型的变量中。
示例2:计算集合中所有文档的数量
查询条件为空,既可以使用bson.D
,也可以使用bson.M
。
1
count , _ := collection . CountDocuments ( context . TODO (), bson . M {}) // 也可以使用bson.D{}
示例3:计算年龄大于30的文档数量
1
2
filter := bson . M { "age" : bson . M { "$gt" : 30 }}
count , _ = collection . CountDocuments ( context . TODO (), filter )
示例4:查询集合中所有的文档
1
2
3
4
5
6
7
8
9
10
11
filter = bson . M {} // 创建空过滤器
// 获取MongoDB集合中所有的文档,并将结果存储在一个游标cursor中
cursor , _ := collection . Find ( context . TODO (), filter )
// 遍历游标,处理查询结果
for cursor . Next ( context . TODO ()) {
var stu Student
if err := cursor . Decode ( & stu ); err != nil {
log . Fatal ( err )
}
fmt . Println ( stu )
}
Find()
方法返回的是*mongo.Cursor
类型,可以cursor.Next()
方法来对游标cursor
进行遍历,在遍历到的游标位置,也可以调用Decode()
方法,将其保存到Student
类型的变量中。
示例5:查询分数在80到90的文档
1
2
filter = bson . M { "score" : bson . M { "$gte" : 80 , "$lte" : 90 }}
cursor , _ = collection . Find ( context . TODO (), filter )
示例6:或条件查询
查询name="Eric"
或age=36
的文档
1
2
3
4
5
6
7
filter = bson . M {
"$or" : [] bson . M {
{ "name" : "Eric" },
{ "age" : 36 },
},
}
cursor , _ = collection . Find ( context . TODO (), filter )
示例7:将所有文档按照score降序
如果是单一排序条件,即可以使用bson.M
,也可以使用bson.D
。
1
2
3
4
5
6
7
8
//sort := bson.M{
// "score": -1, // score降序
//}
sort := bson . D {
{ "score" , - 1 }, // score降序
}
opts := options . Find (). SetSort ( sort )
cursor , _ = collection . Find ( context . TODO (), bson . M {}, opts )
示例8:将所有文档先按照score降序,再age升序
多排序条件,只能使用bson.D
而不能使用bson.M
,因为这里的排序是有先后顺序的。
1
2
3
4
5
6
7
8
9
10
11
12
// 错误的写法:
//sort1 := bson.M{
// "score": -1, // score降序
// "age": 1, // age升序
//}
// 正确的写法:
sort1 := bson . D {
{ "score" , - 1 }, // score降序
{ "age" , 1 }, // age升序
}
opts = options . Find (). SetSort ( sort1 )
cursor , _ = collection . Find ( context . TODO (), bson . M {}, opts )
示例9:只查询前 3 个文档
1
2
limitOpts := options . Find (). SetLimit ( 3 )
cursor , _ = collection . Find ( context . TODO (), bson . M {}, limitOpts )
示例10:跳过前 3 个文档
1
2
skipOpts := options . Find (). SetSkip ( 3 )
cursor , _ = collection . Find ( context . TODO (), bson . M {}, skipOpts )
示例11:设置投影选项,只返回 name 和 score 字段,排除 _id 字段
1
2
3
projection := bson . M { "name" : 1 , "score" : 1 , "_id" : 0 }
projectionOpts := options . Find (). SetProjection ( projection )
cursor , _ = collection . Find ( context . TODO (), bson . M {}, projectionOpts )
示例12:in 条件查询
查询班级为computer science 1
和computer science 2
的文档:
1
2
3
4
5
6
filter = bson . M {
"class" : bson . M {
"$in" : [] string { "computer science 1" , "computer science 2" },
},
}
cursor , _ = collection . Find ( context . TODO (), filter )
示例13:查询存在 hobbies 字段的文档
1
2
3
4
5
6
filter = bson . M {
"hobbies" : bson . M {
"$exists" : true ,
},
}
cursor , _ = collection . Find ( context . TODO (), filter )
插入
InsertOne
方法是 MongoDB Go 驱动程序中用于向集合中插入单个文档的函数。它是 mongo.Collection
类型的一个方法,允许你向指定的 MongoDB 集合中添加一个新文档。如果插入成功,它将返回一个包含新插入文档 ID 的结果,以及可能发生的任何错误。
InsertMany
方法的格式和InsertOne
方法相同。
方法签名
在 MongoDB Go 驱动程序中,InsertOne
方法的大致签名如下:
1
2
func ( c * Collection ) InsertOne ( ctx context . Context , document interface {},
opts ...* options . InsertOneOptions ) ( * InsertOneResult , error )
ctx context.Context
:一个上下文对象,用于控制请求的生命周期,比如取消操作或设置超时时间。
document interface{}
:要插入的文档,它应该是一个可以被编码为 BSON 的值,如 bson.M
、bson.D
、结构体等。
opts ...*options.InsertOneOptions
:一个可选的参数列表,允许你指定额外的插入选项,比如绕过文档验证等。如果不需要这些选项,可以省略此参数。
返回值
*InsertOneResult
:一个包含插入操作结果的对象。通常,你会关心这个对象中的 InsertedID
字段,它包含了新插入文档的 _id
字段的值(如果文档本身没有指定 _id
,MongoDB 会自动生成一个)。
error
:如果在插入过程中发生错误,将返回一个错误对象。你应该检查这个返回值以确定操作是否成功。
示例1:插入单个文档
既可以使用bson.D
,也可以使用bson.M
。
使用bson.D
1
2
3
4
5
6
7
collection := client . Database ( "test" ). Collection ( "stus" )
collection . InsertOne ( context . TODO (), bson . D {
{ "name" , "张三" },
{ "age" , 20 },
{ "gender" , "男" },
{ "class" , "计算机科学与技术1班" },
})
使用bson.M
1
2
3
4
5
6
7
collection . InsertOne ( context . TODO (), bson . M {
"name" : "李四" ,
"age" : 23 ,
"gender" : "男" ,
"class" : "计算机科学与技术3班" ,
"score" : 69 ,
})
示例2:插入多个文档
和插入单个文档相同,都可以使用bson.D
或bson.M
。
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
// 使用bson.D
//docs := []interface{}{
// bson.D{
// {"name", "张三"},
// {"age", 20},
// {"gender", "男"},
// {"class", "计算机科学与技术1班"},
// },
// bson.D{
// {"name", "李四"},
// {"age", 21},
// {"gender", "男"},
// {"class", "计算机科学与技术2班"},
// },
//}
// 使用bson.M
docs := [] interface {}{
bson . M {
"name" : "张三" ,
"age" : 20 ,
"gender" : "男" ,
"class" : "计算机科学与技术1班" ,
},
bson . M {
"name" : "李四" ,
"age" : 21 ,
"gender" : "男" ,
"class" : "计算机科学与技术2班" ,
},
}
collection . InsertMany ( context . TODO (), docs )
更新
collection.UpdateOne()
方法是 MongoDB Go 驱动程序中用于更新集合中符合特定查询条件的第一个文档的函数。它是 mongo.Collection
类型的一个方法,提供了灵活的方式来修改集合中的文档。以下是该方法的详细说明:
方法签名
在 MongoDB Go 驱动程序中,UpdateOne
方法的大致签名如下(注意:具体签名可能会根据驱动程序的版本而有所不同):
1
2
func ( c * Collection ) UpdateOne ( ctx context . Context , filter interface {},
update interface {}, opts ...* options . UpdateOptions ) ( * UpdateResult , error )
ctx context.Context
:一个上下文对象,用于控制请求的生命周期,比如取消操作或设置超时时间。
filter interface{}
:一个查询条件,用于指定要更新的文档。它应该是一个可以被编码为 BSON 的值,MongoDB 将使用这个条件来查找集合中的文档。
update interface{}
:一个更新操作,指定了如何修改找到的文档。它应该是一个 BSON 文档,可以包含更新操作符(如 $set
、$inc
等)来指定更新操作。
opts ...*options.UpdateOptions
:一个可选的参数列表,允许你指定额外的更新选项,比如是否进行乐观锁检查(通过版本字段)等。如果不需要这些选项,可以省略此参数。
返回值
示例1:将name=“Alice"的文档的score改为85
既可以使用bson.D
,也可以使用bson.M
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 获取集合
collection := client . Database ( "test" ). Collection ( "stus" )
// 使用bson.D
// 构建查询条件
// filter := bson.D{{"name", "Alice"}}
// 构建更新操作
// update := bson.D{{"$set", bson.D{{"score", 85}}}}
// 使用bson.M
filter := bson . M { "name" : "Alice" }
update := bson . M { "$set" : bson . M { "score" : 84 }}
// 执行 updateOne 操作
result , _ := collection . UpdateOne ( context . TODO (), filter , update )
// 打印更新结果
fmt . Printf ( "Matched %v documents and updated %v documents.\n" , result . MatchedCount , result . ModifiedCount )
示例2:更新多个文档
1
2
3
filter = bson . M { "class" : "computer science 1" }
update = bson . M { "$inc" : bson . M { "score" : - 5 }}
collection . UpdateMany ( context . TODO (), filter , update )
示例3:替换整个文档
1
2
3
4
5
6
7
8
9
10
filter = bson . M { "name" : "Denny" }
replacement := bson . M {
"name" : "Dennis" ,
"age" : 29 ,
"gender" : "male" ,
"class" : "computer science 1" ,
"score" : 92 ,
}
// 执行 replaceOne 操作
collection . ReplaceOne ( context . TODO (), filter , replacement )
示例4:使用 upsert 选项
1
2
3
4
5
6
7
8
9
10
11
12
filter = bson . M { "name" : "Charlie" , "age" : 22 }
update = bson . M { "$set" : bson . M {
"name" : "Charlie" ,
"age" : 22 ,
"gender" : "male" ,
"class" : "computer science 3" ,
"score" : 99 ,
}}
// 构建选项以启用upsert
opts := options . Update (). SetUpsert ( true )
// 执行updateOne操作
collection . UpdateOne ( context . TODO (), filter , update , opts )
示例 5:从文档中移除指定的字段
1
2
3
4
5
6
7
8
filter = bson . M { "name" : "Eric" }
// 构建更新操作,使用$unset来移除score字段
update = bson . M { "$unset" : bson . M { "score" : 1 }}
// 注意:在$unset操作中,字段的值实际上并不重要,因为$unset是根据字段名来移除字段的。
// 但为了与MongoDB shell中的语法保持一致,这里仍然给出了值1。
// 在实际使用中,你也可以省略这个值,直接写bson.M{"score": ""}或完全忽略值(虽然这可能会影响代码的可读性)。
// 执行updateOne操作
collection . UpdateOne ( context . TODO (), filter , update )
删除
collection.DeleteOne()
方法是 MongoDB Go 驱动程序中的一个函数,用于从 MongoDB 集合中删除一个与给定过滤器匹配的文档。这个方法是 *mongo.Collection
类型的一个方法,表示对 MongoDB 集合的操作。
函数签名
在 MongoDB Go 驱动程序中,DeleteOne
方法的函数签名大致如下(注意:具体签名可能会根据 MongoDB Go 驱动程序的版本而略有不同):
1
2
func ( c * Collection ) DeleteOne ( ctx context . Context , filter interface {},
opts ...* options . DeleteOptions ) ( * DeleteResult , error )
ctx context.Context
:一个上下文对象,用于控制请求的取消、超时和截止日期。虽然 context.TODO()
可以用于简单的示例或测试,但在生产代码中,你应该传递一个具有适当超时和取消逻辑的上下文。
filter interface{}
:一个用于指定要删除的文档的选择器的接口。在 MongoDB Go 驱动程序中,这通常是一个 bson.M
或 bson.D
类型的值,用于构建查询条件。
opts ...*options.DeleteOptions
:一个可选的 *options.DeleteOptions
类型的切片,用于指定额外的删除选项,如写关注(write concern)或投影(虽然对于删除操作来说,投影并不适用)。
返回值
*DeleteResult
:一个指向 DeleteResult
结构的指针,该结构包含关于删除操作的信息,如被删除的文档数(对于 DeleteOne
来说,这将是 0 或 1)。
error
:如果在执行删除操作时发生错误,则返回该错误。
示例1:
示例 1:删除单个文档
要删除名为 “张三” 的学生的文档
1
2
3
4
5
6
7
// 获取集合
collection := client . Database ( "test" ). Collection ( "stus" )
// 构建过滤器
filter := bson . M { "name" : "张三" }
// 执行deleteOne操作
result , _ := collection . DeleteOne ( context . TODO (), filter )
fmt . Println ( "删除文档的数量:" , result . DeletedCount )
示例 2:删除多个文档
要删除所有名为 “张三” 的学生的文档
1
2
3
4
filter := bson . M { "name" : "张三" }
// 执行deleteMany操作
deleteResult , _ := collection . DeleteMany ( context . TODO (), filter )
fmt . Println ( "删除文档的数量:" , deleteResult . DeletedCount )
示例 3:删除所有文档(慎用)
1
2
3
4
5
6
7
filter := bson . M {} // 构建一个空的查询过滤器
// 执行deleteMany操作以删除所有文档
deleteResult , _ = collection . DeleteMany ( context . TODO (), filter )
fmt . Println ( "删除文档的数量:" , deleteResult . DeletedCount )
// 或者使用drop()来删除集合
collection . Drop ( context . TODO ())
内嵌文档
示例1:给name=“Alice"的文档添加hobbies属性,hobbies也有两个属性:cities和sports
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 获取集合
collection := client . Database ( "test" ). Collection ( "stus" )
// 构建查询过滤器
filter := bson . M { "name" : "Tom" }
// 构建更新文档
update := bson . M {
"$set" : bson . M {
"hobbies" : bson . M {
"cities" : [] string { "shenzhen" , "New York" },
"sports" : [] string { "skiing" , "mountaineering" },
},
},
}
// 执行updateOne操作
result , _ := collection . UpdateOne ( context . TODO (), filter , update )
fmt . Printf ( "Matched %v documents and updated %v documents.\n" , result . MatchedCount , result . ModifiedCount )
示例2:查询所有 hobbies.cities 数组中包含 “shenzhen” 的文档
1
2
3
4
5
6
7
8
filter := bson . M { "hobbies.cities" : "shenzhen" }
cursor , err := collection . Find ( context . TODO (), filter )
defer cursor . Close ( context . TODO ())
for cursor . Next ( context . TODO ()) {
var stu Student
cursor . Decode ( & stu )
fmt . Println ( stu )
}
示例3:将 Alice 喜欢的城市添加一个 “chengdu”
1
2
3
4
5
6
7
8
filter := bson . M { "name" : "Alice" }
update := bson . M {
"$push" : bson . M {
"hobbies.cities" : "chengdu" ,
},
}
// 执行updateOne操作
collection . UpdateOne ( context . TODO (), filter , update )
执行多次会多次添加。
示例4:如果 Alice 喜欢的城市没有 “chengdu”,则添加该城市,否则什么也不做
1
2
3
4
5
6
7
8
filter := bson . M { "name" : "Alice" }
update := bson . M {
"$addToSet" : bson . M {
"hobbies.cities" : "chengdu" ,
},
}
// 执行updateOne操作
collection . UpdateOne ( context . TODO (), filter , update )
执行多次也只会添加一次。
示例5:从 Alice 的 hobbies.cities 数组中删除刚才添加的 “chengdu”
1
2
3
4
5
6
7
filter := bson . M { "name" : "Alice" }
update := bson . M {
"$pull" : bson . M {
"hobbies.cities" : "chengdu" ,
},
}
collection . UpdateOne ( context . TODO (), filter , update )
这个 updateOne
操作会找到 name
为 “Alice” 的第一个文档,并从其 hobbies.cities
数组中移除所有 值为 “chengdu” 的元素。