排序规则(Collations)
在此页面上
Overview
在本指南中,您可以了解如何使用排序规则按string值对查询或聚合操作结果进行排序。 排序规则是一组适用于特定语言和区域设置的字符排序约定。
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
字段的默认值,请访问支持的语言和区域设置。
对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)) }
如果不指定默认的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)
为操作设置排序规则
从集合中读取、更新和删除文档的操作可以使用排序规则。 将排序规则应用于操作会覆盖之前为集合定义的任何默认排序规则。
如果对操作应用的新排序规则不同于索引的排序规则,则无法使用该索引。 因此,该操作的性能可能不如索引所涵盖的操作。 有关索引未涵盖的排序操作缺点的更多信息,请参阅使用索引对查询结果进行排序。 有关支持排序规则的操作列表,请参阅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)) }
在不指定排序规则且将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 文档: