排序规则
概述
在本指南中,您可以了解如何使用 排序规则 来根据字符串值对查询或聚合操作结果进行排序。排序规则是一组适用于特定语言和区域的字符排序约定。
MongoDB 中的排序规则
MongoDB 默认使用 二进制排序规则 对字符串进行排序。此排序规则方法使用ASCII标准字符值进行比较和排序字符串。某些语言和区域设置具有特定的字符排序约定,与ASCII标准不同。
例如,在加拿大法语中,当其他字符相同的情况下,最右侧的重音字符决定了字符串的排序顺序。考虑以下加拿大法语单词
cote
coté
côte
côté
使用默认的二元排序规则时,MongoDB按照以下顺序对这些单词进行排序
cote coté côte côté
使用加拿大法语排序规则时,MongoDB按照以下顺序对这些单词进行排序
cote côte coté côté
指定排序规则
要指定排序规则,创建一个Collation
对象。您必须定义Collation
对象的Locale
字段;所有其他字段都是可选的。例如,以下代码示例指定了一个具有"en_US"
区域设置排序规则的Collation
对象
myCollation := &options.Collation{Locale: "en_US"}
要查看完整的 Collation
对象字段列表,请访问 Collation API 文档。要查看所有受支持的地区和 Locale
字段的默认值,请访问 受支持的语言和地区。
在集合或视图中设置 Collation
您可以在创建新的集合或视图时应用 collation。这将为该集合或视图上调用任何操作定义默认 collation。通过 CreateCollectionOptions
或 CreateViewOptions
对象设置 collation。然后,使用选项对象作为参数调用 CreateCollection()
或 CreateView()
方法。
创建集合示例
以下示例创建了一个名为 books
的新集合,并指定了默认 collation,使用 "fr"
地区。Strength
collation 字段具有 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()
方法返回所有具有按字母顺序排在"Infinite Jest"
之前的name
值的文档
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
值。这些规则将单词以"C"开头的内容排在以"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文档