Overview
在本指南中,您可以学习;了解如何使用Go驾驶员来配置读取和写入操作。
读取和写入设置
您可以通过设置读取偏好(read preference)控制驾驶员路由读取操作的方式。您还可以通过设置读关注(read concern)或写关注(write concern)来控制驾驶员处理数据一致性和持久性的方式。读关注指定执行读操作时数据所需的持久性级别,写入关注指定驾驶员如何等待副本集的写入操作确认。
您可以在以下级别设置写关注、读关注和读取偏好选项:
客户端级别,除非被覆盖,否则将为所有操作执行设置默认值
会话级别
事务级别
数据库级别
集合级别
前面的列表还指示了选项设置的优先级递增顺序。示例,如果为ACID 事务设立读关注(read concern),它将覆盖为客户端设立的读关注(read concern)。
写关注
写关注(write concern)描述了副本集集中承载数据的节点的数量,这些节点必须在操作返回为成功之前确认写入操作,例如插入或更新。默认下,如果只有主节点 (primary node in the replica set)副本集成员确认,则写入操作成功。
选项
MongoDB Go驱动程序提供了 writeconcern
包,它允许您为副本集指定写关注(write concern)。通过将 WriteConcern
类型的实例传递给 SetWriteConcern()
方法来设置写关注(write concern)。WriteConcern
类型提供以下方法来选择常见的写关注(write concern)规范:
方法 | 说明 |
---|---|
| The client requests acknowledgement that write operations propagate to
tagged members of a mongod instance. For more
information, see the Write Concern specification.Parameter: tag (string) |
| The client requests acknowledgement that the replica set has
written the changes to the on-disk journal. For more information, see the
Write Concern specification. Parameter: none |
| The client requests acknowledgement that write operations propagate to the
majority of data-bearing voting members. For more information, see the
Write Concern specification. Parameter: none |
| The client requests requests no acknowledgment of write
operations. For more information, see the
Write Concern specification for w: 0. Parameter: none |
| The client requests acknowledgement that the replica set has
written the changes to memory on one node, such as the standalone mongod or
the primary in a replica set. For more
information, see the Write Concern specification for w: 1. Parameter: none |
提示
写关注超时
您无法在 WriteConcern
实例上设立超时。相反,请在创建上下文时使用 WithTimeout()
方法在操作级别设立超时。要学习;了解更多信息,请参阅《连接选项》指南中的 限制服务器执行时间。
如果需要更专门的写关注,则您可以自行定义 WriteConcern
结构文本。您可以在 WriteConcern
结构中设置以下字段:
字段 | 说明 |
---|---|
| Specifies the number of mongod instances or tagged members
that write operations must propagate to for acknowledgement. Common values include
1 , 0 , and "majority" .Type: string or int |
| Specifies whether the replica set must write the changes to the on-disk
journal for acknowledgement. Type: bool |
例子
以下代码展示了如何在客户端和集合级别指定不同的写入关注。客户端级写关注(write concern)请求两个副本集成员的确认,并将日志设置为 false
。集合级别的写关注(write concern)请求大多数副本集成员的确认。
uri := "mongodb://<hostname>:<port>" journal := false cliWC := &writeconcern.WriteConcern{ W: 2, Journal: &journal, } clOpts := options.Client().ApplyURI(uri).SetWriteConcern(cliWC) client, err := mongo.Connect(clOpts) ... collWC := writeconcern.Majority() collOpts := options.Collection().SetWriteConcern(collWC) coll := client.Database("db").Collection("myColl", collOpts)
读关注 (read concern)
读关注选项可以让您确定客户端从查询中返回哪些数据。默认的读关注级别为“本地”,这意味着客户端会返回实例的最新数据,但不保证该数据已写入大多数副本集成员。
选项
MongoDB Go驱动程序提供了 readconcern
包,可让您指定副本集的读关注(read concern)。通过将 ReadConcern
类型的实例传递给 SetReadConcern()
方法来设置读关注(read concern)。ReadConcern
类型具有以下方法来指定读关注(read concern):
方法 | 说明 |
---|---|
| 查询从实例返回数据,但不保证数据已写入大多数副本集成员。 有关更多信息,请参阅读关注规范。 |
| 该查询返回的数据反映了以写关注(write concern) |
| 查询会返回实例的最新数据。 有关更多信息,请参阅读关注规范。 |
| 该查询返回确认已写入副本集中大多数成员的实例的最新数据。 有关更多信息,请参阅读关注规范。 |
| 该查询返回特定时间点 |
例子
以下代码显示了如何指定“majority”的读关注(read concern)。然后,代码会选择带有此选项的Collection
。
rc := readconcern.Majority() opts := options.Collection().SetReadConcern(rc) database := client.Database("db") coll := database.Collection("myCollection", opts)
读取偏好
读取偏好选项指定 MongoDB 客户端如何将读取操作路由到副本集成员。默认情况下,应用程序将其读取操作定向到副本集中的主节点。
读取偏好由读取偏好模式和可选的标签集列表、 maxStalenessSeconds选项和对冲读选项组成。
选项
MongoDB Go驱动程序提供了 readpref
包,它允许您指定副本集的读取偏好(read preference)。通过将 ReadPref
类型的实例传递给 SetReadPreference()
方法来设置读取偏好(read preference)。ReadPref
类型具有以下方法来指定读取偏好(read preference):
方法 | 说明 |
---|---|
| 客户端根据指定的延迟阈值从符合条件的随机副本集成员中读取。有关更多信息,请参阅读取偏好服务器手册条目。 |
| 客户端从当前副本集主节点读取。 有关更多信息,请参阅MongoDB Server手册中的读取偏好条目。 |
| 客户端会从可用的主节点 (primary node in the replica set)节点中读取数据。如果主节点 (primary node in the replica set)不可用,则操作将从从节点(secondary node from replica set)成员读取。有关更多信息,请参阅读取偏好服务器手册条目。 |
| 客户端从副本集的从节点读取。 有关更多信息,请参阅MongoDB Server手册中的读取偏好条目。 |
| 如果有一个或多个可用的从节点,客户端会从从节点(secondary node from replica set)读取。如果从节点不可用,则操作将从主节点 (primary node in the replica set)成员读取。有关更多信息,请参阅读取偏好服务器手册条目。 |
提示
或者,您可以在连接字符串中指定读取偏好(read preference)。 有关详细信息,请参阅有关“读取偏好选项”的服务器手册条目。
例子
以下代码显示如何将读取偏好指定到从节点的读取。然后代码使用此选项选择 Database
。
rp := readpref.Secondary() opts := options.Database().SetReadPreference(rp) database := client.Database("db", opts)
可重试读取和写入
如果某些写入操作由于网络或服务器错误而失败,Go驾驶员会自动重试一次。
在使用 options.Client
结构体创建新客户端时,您可以通过将 RetryReads
或 RetryWrites
选项设置为 False
来显式禁用可重试读取或可重试写入。
以下示例使用 ClientOptions
setter 函数为客户端禁用可重试读取和写入:
// Defines the client options clientOps := options.Client(). ApplyURI(uri). SetRetryWrites(false). SetRetryReads(false) // Creates a new client using the specified options client, err := mongo.Connect(clientOps) if err != nil { panic(err) }
要学习;了解有关支持的可重试读取操作的更多信息,请参阅MongoDB Server手册中的可重试读取。要学习;了解有关支持的可重试写入操作的更多信息,请参阅MongoDB Server手册中的可重试写入。
排序规则
您可以指定排序规则来修改读取和写入操作的行为。排序规则是一设立特定于语言的字符串比较规则,例如字母大小写和重音符号规则。
默认下, MongoDB使用二进制排序规则对字符串进行排序。此默认规则使用 ASCII 标准 字符值对字符串进行比较和排序。语言和区域设置具有与 ASCII 标准不同的特定字符排序约定,您可以选择在操作中应用一设立不同的排序规则。
您可以在以下级别指定排序规则:
集合:为集合上的操作设置默认规则。您无法为现有集合定义排序规则。
索引:为使用索引的操作设置排序规则。
操作:设置操作的排序规则并覆盖任何继承的排序规则。
指定排序规则
要指定排序规则,请创建一个 Collation
对象。您必须定义 Collation
对象的 Locale
字段,但所有其他字段都是可选的。示例,以下代码示例指定具有 "en_US"
区域设置设置排序规则的 Collation
对象:
myCollation := &options.Collation{Locale: "en_US"}
有关Collation
对象字段的完整列表,请访问 Collation API 文档 。要查看所有支持的区域设置以及Locale
字段的默认值,请访问支持的语言和区域设置。
对collection或视图设置排序规则
创建新的集合或视图时,可以应用排序规则。 这定义了对该集合或视图调用的任何操作的默认排序规则。 通过CreateCollectionOptions
或CreateViewOptions
对象设置排序规则。 然后,将选项对象作为参数调用CreateCollection()
或CreateView()
方法。
创建集合示例
以下示例创建了一个名为books
的新集合,并指定了具有"fr"
区域设置的默认排序规则。 Strength
排序规则字段的值为1
,用于忽略字母重音的差异。
myCollation := &options.Collation{Locale: "fr", Strength: 1} opts := options.CreateCollection().SetCollation(myCollation) err := db.CreateCollection(context.TODO(), "books", opts) if err != nil { panic(err) }
使用默认排序规则示例
如果您在books
集合上调用使用排序规则的操作,则该操作将使用创建集合示例中指定的默认排序规则。
假设books
集合包含以下文档:
{"name" : "Emma", "length" : "474"} {"name" : "Les Misérables", "length": "1462"} {"name" : "Infinite Jest", "length" : "1104"} {"name" : "Cryptonomicon", "length" : "918"} {"name" : "Ça", "length" : "1138"}
注意
要学习;了解如何插入文档,请参阅插入文档。
以下示例使用Find()
方法返回name
值按字母顺序位于"Infinite Jest"
之前的所有文档:
filter := bson.D{{"name", bson.D{{"$lt", "Infinite Jest"}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []bson.D if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Emma","length":"474"} {"name":"Cryptonomicon","length":"918"} {"name":"Ça","length":"1138"}
如果代码未指定默认的books
排序规则,则 Find()
方法将遵循默认的二进制排序规则规则来确定 "Infinite Jest"
之前的 name
值。这些规则将以“Ç”开头的单词放在以“I”开头的单词之后。输出如下所示:
{"name":"Emma","length":"474"} {"name":"Cryptonomicon","length":"918"}
要学习;了解有关 Find()
方法的更多信息,请参阅查找文档。
对索引设置排序规则
在集合上创建新索引时,可以应用排序规则。 该索引会将文档的有序表示形式存储在集合中,因此 MongoDB 实例不会在内存中执行排序操作。
要在操作中使用索引,操作必须使用与索引中指定的排序规则相同的排序规则。 此外,请确保包含排序规则的索引涵盖该操作。 通过IndexOptions
对象设置排序规则,并将该对象作为参数传递给CreateOne()
方法。
例子
创建books
集合并应用默认排序规则后(如创建集合示例部分所示),您无法更改集合的默认排序规则。 但是,您可以使用不同的排序规则为集合创建索引。
以下示例使用CreateOne()
方法在name
字段上创建升序索引,并指定具有"en_US"
区域设置的新排序规则:
myCollation := &options.Collation{Locale: "en_US"} opts := options.Index().SetCollation(myCollation) indexModel := mongo.IndexModel{ Keys: bson.D{{"name", 1}}, Options: opts, } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: name_1
为操作设置排序规则
从集合中读取、更新和删除文档的操作可以使用排序规则。 将排序规则应用于操作会覆盖之前为集合定义的任何默认排序规则。
如果对操作应用的新排序规则不同于索引的排序规则,则无法使用该索引。 因此,该操作的性能可能不如索引所涵盖的操作。 有关索引未涵盖的排序操作缺点的更多信息,请参阅使用索引对查询结果进行排序。 有关支持排序规则的操作列表,请参阅MongoDB 手册。
例子
您可以使用支持排序规则的操作来更新和查询books
集合中的文档。
以下示例使用Find()
方法返回length
值大于"1000"
的文档。 NumericOrdering
排序规则字段的值为true
,以确保值按数字顺序而不是字母顺序排序:
filter := bson.D{{"length", bson.D{{"$gt", "1000"}}}} myCollation := &options.Collation{Locale: "en_US", NumericOrdering: true} opts := options.Find().SetCollation(myCollation) cursor, err := coll.Find(context.TODO(), filter, opts) if err != nil { panic(err) } var results []bson.D if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := bson.MarshalExtJSON(result, false, false) fmt.Println(string(res)) }
{"name":"Les Misérables","length":"1462"} {"name":"Infinite Jest","length":"1104"} {"name":"Ça","length":"1138"}
如果代码未指定将 NumericOrdering
字段设立为 true
的排序规则,则同一 Find()
操作会将 length
值作为字符串进行比较。在这种情况下,输出如下所示:
{"name":"Emma","length":"474"} {"name":"Les Misérables","length":"1462"} {""name":"Infinite Jest","length":"1104"} {"name":"Cryptonomicon","length":"918"} {"name":"Ça","length":"1138"}
更多信息
要学习;了解有关Find()
方法的更多信息,请参阅《查找文档》指南。
要学习;了解有关本指南中讨论的概念的更多信息,请访问以下手册页面:
API 文档
要进一步了解本指南中讨论的方法,请参阅以下 API 文档: