Blogger Information
Blog 85
fans 0
comment 0
visits 72823
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
MongoDB Go Driver使用帮助文档
Smile
Original
885 people have browsed it

正式的MongoDB Go Driver近来变成1.0的GA版本。它现在被认为是一个完整的特性, 并且准备好在正式产品中使用。这篇使用说明书将帮助你开始使用 MongoDB Go Driver。你将会创建一个简单的程序并且学到如何:

安装MongoDB Go Driver使用Go Driver来连接MongoDB在Go内使用BSON对象给MongoDB发送CRUD操作

你可以在github代码仓库看到这篇帮助文档的完整代码。为了可以按步骤进行, 你需要一个MongoDB数据库来连接, 你可以使用一个运行在本地的MongoDB数据库, 或者很容易地使用MongoDB Atlas来创建一个500M的数据库。

安装MongoDB Go Driver

MongoDB Go Driver有几个代码包组成, 如果你正在使用go get工具, 你可使用如下命令安装:

go get go.mongodb.org/mongo-driver

这个命令的输出可能看起来像一个告警信息:package http://go.mongodb.org/mongo-driver: no Go files in (…)。这是go get的预期输出。

如果你正在使用dep package manager, 你可以用如下的命令安装mongo主程序包, 以及bson包和mongo/options包:

dep ensure --add go.mongodb.org/mongo-driver/mongo \
go.mongodb.org/mongo-driver/bson \
go.mongodb.org/mongo-driver/mongo/options

如果你正在使用go mod, 正确的代码包会在构建的时候获取到。

创建框架

创建main.go文件并且import bson, mongo, and 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"
)

// You will be using this Trainer type later in the program
type Trainer struct {
   Name string
   Age  int
   City string
}

func main() {
   // Rest of the code will go here
}

这段代码也import几个标准库, 并且定义了一个Trainer类型, 在后面的帮助文档中你会用到它们。

使用Go Driver连接到MongoDB

一旦MongoDB Go Driver被import, 你可以使用mongo.Connect()来连接到一个MongoDB部署,你必须要传递一个context和一个options.ClientOptions对象给mongo.Connect()。这些client options被用来设置连接字符串, 它也被用来配置driver的设定, 比如write concern, socket timeout等等。options包文档有更多可用的client options信息。

添加下面的代码到main函数里面:

// Set client options
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

// Connect to MongoDB
client, err := mongo.Connect(context.TODO(), clientOptions)

if err != nil {
   log.Fatal(err)
}

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

if err != nil {
   log.Fatal(err)
}

fmt.Println("Connected to MongoDB!")

一旦连接成功, 你可以通过将如下这行代码添加到main函数最后面来获得在test库里面Trainer集合的handle:

collection := client.Database("test").Collection("trainers")

下面的代码会使用该集合的handle来查询trainers集合。

最好的实践是保存一个连接到MongoDB的client一段时间,以便应用程序可以利用连接池—-你不会希望每次查询打开和关闭一个链接。然而, 如果你的应用程序不再需要一个连接, 该连接可以使用client.Disconnect()被关闭,像这样:

err = client.Disconnect(context.TODO())

if err != nil {
   log.Fatal(err)
}
fmt.Println("Connection to MongoDB closed.")

运行代码来测试一下你的程序能成功的连接到MongoDB服务器。Go 会对没有使用的bson和mongo/options包, 以及没有使用的集合变量报警,因为我们还没有使用它们做任何事情。 你必须要注释掉它们直到它们被你的程序使用到, 然后来测试连接。

在Go中使用BSON对象

在我们发送查询给数据库之前, 很重要的一点是,理解Go Driver是如何和BSON对象协同工作的。JSON文档在MongoDB里面以二进制形式存储, 被称作BSON(二进制编码的JSON)。不像其他的数据库保存JSON数据为简单的字符串和数字, BSON扩展了JSON的保存形式, 包括额外的类型, 比如int, long, date, floating point以及decimal128。这使得它让应用程序更容易来可靠地处理、排序和比较数据。Go Driver有两个系列的类型表示BSON数据:D系列类型和Raw系列类型。

D系列的类型使用原生的Go类型简单地构建BSON对象。这可以非常有用的来创建传递给MongoDB的命令。 D系列包含4种类型:
- D:一个BSON文档。这个类型应该被用在顺序很重要的场景, 比如MongoDB命令。
- M: 一个无需map。 它和D是一样的, 除了它不保留顺序。
- A: 一个BSON数组。
- E: 在D里面的一个单一的子项。

这里有一个使用D类型构建的过滤文档的例子, 它可能被用在查询name字段匹配“Alice”或者“Bob”的文档:

bson.D{{
   "name",
   bson.D{{
       "$in",
       bson.A{"Alice", "Bob"}
   }}
}}

Raw系列类型被用来验证bytes类型的slice, 你也可以从Raw类型使用Lookup()获得单个的子项, 这在你不想要unmarshall某个BSON到另一个类型的时候很有用。这篇帮助文档会只使用D系列类型。

CRUD操作

一旦你已经连接到一个数据库, 是时候添加和操作一些数据了。集合类型有一些函数允许你给数据库发送查询。

插入文档

首先, 创建一些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() 函数会采用一个slice对象:

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()函数允许你更新单一的文档, 它需要一个filter文档来匹配数据库里面的文档, 并且需要一个update文档来描述更新的操作。你可以用bson.D类型来构建这些文档:

filter := bson.D{{"name", "Ash"}}

update := bson.D{
   {"$inc", bson.D{
       {"age", 1},
   }},
}

这段代码会匹配name是“Ash”的文档, 并且将Ash的age增加1 —生日快乐, Ash!

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)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()函数。这个函数返回单个的结果,被解码成为一个值。你可以使用和上面使用过的update查询一样的filter变量来匹配一个name是Ash的文档。

// create a value into which the result can be decoded
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(),这个函数返回一个游标。一个游标提供一个文档流, 通过它你可以遍历和解码每一个文档。一旦一个游标被消耗掉, 你应该关闭游标。这里你也可以使用options包来设定一些操作选项, 特别的, 你可以设定一个返回文档数量的限制, 比如2个。

// Pass these options to the Find method
findOptions := options.Find()
findOptions.SetLimit(2)

// Here's an array in which you can store the decoded documents
var results []*Trainer

// Passing bson.D{{}} as the filter matches all documents in the collection
cur, err := collection.Find(context.TODO(), bson.D{{}}, findOptions)
if err != nil {
   log.Fatal(err)
}

// Finding multiple documents returns a cursor
// Iterating through the cursor allows us to decode documents one at a time
for cur.Next(context.TODO()) {

   // create a value into which the single document can be decoded
   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)
}

// Close the cursor once finished
cur.Close(context.TODO())

fmt.Printf("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)

接下来步骤

你可以在Github 代码仓库看到这篇帮助文档的最终的代码。MongoDB Go Driver 的文档能从GoDoc获得。
你可能会对使用aggregations或者transaction特别感兴趣。

如果你有任何问题, 请联系mongo-go-driver Google group。关于Go 项目任何的bug,请编辑一个MongoDB JIRA, 我们很喜欢你能够有Go Driver的反馈, 因此请联系我们并且让我们知道你的想法。


Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post