mongodb 安装(docker)
先装个 mongo,为了省事就用 docker 了。
docker 的 daemon.json 加一个国内的源地址:
"registry-mirrors": [ "http://hub-mirror.c.163.com" ]
然后拉取 mongo 镜像:
docker pull mongodb
启动 mongo:
docker run -p 27017:27017 mongo
安装 mongodb go 驱动
go get go.mongodb.org/mongo-driver
基础代码
创建 main.go 文件,并且导入 bson
,mongo
和 mongo/options
包。
package main import( "context" "fmt" "log" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // 在后面的代码中将会使用这个 trainer 结构体 type trainer struct { name string age int city string } func main() { // }
使用 go driver 连接到 mongodb
一旦 mongodb 的 go 驱动被导入之后,我们就可以使用 mongo.connect
函数来连接到 mongodb。你必须传递一个 context
和 options.clientoptions
对象给 mongo.connect
函数。 被用来设置连接配置。
// 设置连接参数 clientoptions := options.client().applyuri("mongodb://localhost:27017") // 连接到 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!")
一旦你连接上了 mongodb,你现在可以获取 test 数据库的 trainers 集合。
collection := client.dataabse("test").collection("trainers")
下面的代码将会使用 collection
来查询 trainers
集合。
如果你不在需要查询 mongodb,就可以使用 client.disconnect()
来关闭 mongodb 连接。
err = client.disconnect(context.todo()) if err != nil { log.fatal(err) } fmt.println("connection to mongodb closed.")
在 go 里面使用 bson 对象
在发送查询请求到 mongodb 之前,了解如何使用 bson 对象是非常有必要的。在 mongodb 中存储的 json 文档叫 bson,是以二进制形式存储的。不像其他数据库以字符串形式存储 json 数据,bson 还包含了字段类型,这使得应用程序更容易可靠地处理、排序和比较。go 的 mongodb 驱动有两个表示 bson 数据的类型:d 类型和 raw 类型。
d 类型用于使用 go 中的原始类型来构建 bson 对象。这对于传递给 mongodb 的命令特别有用。d 类型包括四种类型:
d:一个 bson 文档。
m:无序的 map。
a:一个 bson 数组。
e:d 里面的单个元素。
这里是一个使用 d 类型筛选文档的例子,这里会筛选出名字为 alice 或者 bob 的数据:
bson.d({ "name", bson.d{ {"$in": bson.a{"alice", "bob"}} } })
crud 操作
一旦你连接到了数据库,我们就可以开始添加或者操作数据库中的数据了。collection
类型有一些方法允许你发送查询到数据库中。
插入文档
首先,创建一些新的 trainer
结构体来插入到数据库中:
ash := trainer{"ash", 10, "pallet town"} misty := trainer{"misty", 10, "cerulean city"} brock := trainer{"brock", 15, "pewter" city}
可以使用 collection.insertone()
方法来插入单个文档:
insertresult, err := collection.insertone(context.todo(), ash) if err != nil { log.fatal(err) } fmt.println("inserted a single document: ", insertresult.insertedid)
如果我们想一次性插入多个文档,可以传递一个切片给 collection.insertmany
方法:
trainers := []interface{}{misty, brock} insertmanyresult, err := collection.insertmany(context.todo(), trainers) if err != nil { log.fatal(err) } fmt.println("inserted multiple documents: ", insertmanyresult.insertedids)
更新文档
collection.updateone()
方法允许你更新单个文档。它需要一个 bson.d
类型的参数来筛选数据库中特定的文档,然后更新它。
// 筛选 name 字段的值为 ash 的记录 filter := bson.d{{"name", "ash"}} // 更新 age 字段,值加 1 update := bson.d{ {"$inc", bson.d{ {"age", 1} }} }
这几行代码会将数据库中名字为 ash 的文档的 age 字段的值加 1。
updateresult, err := collection.updateone(context.todo(), filter, update) if err != nil { log.fatal(err) } fmt.printf("matched %v documents and updated %v documents.\n", updateresult.matchedcount, updateresult.modifiedcount)
查询文档
如果想要查询一个文档,同样需要提供一个 filter 文档来筛选,同时需要一个接收结果的指针。为了查询单个文档,可以使用 collection.findone()
方法。这个方法会返回一条匹配上的记录并解析到我们指针指向的地方。你可以使用和上面相同的 filter 来查询 name 为 ash 的记录。
// 创建一个变量用来接收解析后的结果 var result trainer err = collection.findone(context.todo(), filter).decode(&result) if err != nil { log.fatal(err) } fmt.printf("found a single document: % v\n", result)
如果想要查询多个文档,可以使用 collection.find()
方法。这个方法返回一个 cursor
(游标)。一个 cursor
(游标)可以让我们一次获取到其中一条记录。一旦一个游标遍历完毕,你应该关闭这个游标。
下面的例子中,我们在 find 的时候同时指定了额外的一些选项,这里我们设置最多获取的记录数为 2。
// 这个选项会被传递给 find 方法 findoptions := options.find() findoptions.setlimit(2) // 这是用来保存查询结果的数组 var results []*trainer // 传递 bson.d{{}} 作为 filter 来匹配 collection 中的所有文档 cur, err := collection.find(context.todo(), bson.d{{}}, findoptions) if err != nil { log.fatal(err) } // 查询多个文档的时候返回一个 cursor // 迭代这个 cursor 允许我们一次解码一个文档 for cur.next(context.todo()) { // 创建一个用来接收单个文档的变量 var elem trainer err := cur.decode(&elem) if err != nil { log.fatal(err) } results = append(results, &elem) } if err := cur.err(); err != nil { log.fatal(err) } // 一旦结束了获取数据的操作,我们需要关闭 cursor cur.close(context.todo()) fmt.println("found multiple documents (array of pointers): % v\n", results)
删除文档
最后,你可以使用 collection.deleteone()
或者 collection.deletemany()
来删除文档。这里传递了 bson.d{ {} }
作为 filter 参数,将会匹配集合中的所有文档。你也可以使用 collection.drop
来删除整个集合。
deleteresult, err := collection.deletemany(context.todo(), bson.d{{}}) if err != nil { log.fatal(err) } fmt.printf("deleted %v documents in the trainers collection\n", deleteresult.deletedcount)
下一步
mongodb go 驱动的完整文档可以在 中查看。