排序规则(Collations)
Overview
版本 3.4 中的新增功能。
排序规则是指如何比较通常采用特定自然语言的字符串的规则集。
例如,在加拿大法语中,给定单词中的最后一个重音决定了排序顺序。
考虑以下法语单词:
cote < coté < côte < côté
使用加拿大法语排序规则的排序顺序将导致以下结果:
cote < côte < coté < côté
如果未指定排序规则,MongoDB 会对字符串使用简单的二进制比较。 因此,单词的排序顺序为:
cote < coté < côte < côté
使用
您可以在创建collection和索引时为其指定默认排序规则,也可以为 CRUD 操作和聚合指定排序规则。 对于支持排序规则的操作,MongoDB 使用集合的默认排序规则,除非该操作指定了不同的排序规则。
排序规则参数
'collation' => { 'locale' => <string>, 'caseLevel' => <bool>, 'caseFirst' => <string>, 'strength' => <int>, 'numericOrdering' => <bool>, 'alternate' => <string>, 'maxVariable' => <string>, 'normalization' => <bool>, 'backwards' => <bool> }
唯一必需的参数是locale
,服务器会将其解析为 ICU 格式的区域设置 ID 。例如,将locale
设置为en_US
以代表美国英语,或将 fr_CA
设置为以代表加拿大法语。
有关可用参数的完整说明,请参阅MongoDB 手册条目。
为collection指定默认排序规则
以下示例在test
数据库上创建了一个名为contacts
的新集合,并指定了fr_CA
区域设置的默认排序规则。 在创建集合时指定排序规则可确保针对contacts
集合运行的所有涉及查询的操作都使用fr_CA
排序规则,除非查询指定了其他排序规则。 除非创建命令指定了其他排序规则,否则新集合上的所有索引也会继承默认排序规则。
client = Mongo::Client.new([ "127.0.0.1:27017" ], :database => "test") client[:contacts, { "collation" => { "locale" => "fr_CA" } } ].create
为索引指定排序规则
要为索引指定排序规则,请在创建索引时使用collation
选项。
以下示例在启用unique
参数并将默认排序规则将locale
设置为en_US
的情况下,在address_book
集合的name
字段上创建索引。
client = Mongo::Client.new([ "127.0.0.1:27017" ], :database => "test") client[:address_book].indexes.create_one( { "first_name" => 1 }, "unique" => true, "collation" => { "locale" => "en_US" } )
要使用此索引,请确保您的查询也指定相同的排序规则。 以下查询使用上述索引:
client[:address_book].find({"first_name" : "Adam" }, "collation" => { "locale" => "en_US" })
以下查询不使用索引。 第一个查询不使用排序规则,第二个查询使用的排序规则的strength
值与索引排序规则不同。
client[:address_book].find({"first_name" : "Adam" }) client[:address_book].find({"first_name" : "Adam" }, "collation" => { "locale" => "en_US", "strength" => 2 })
支持排序规则的操作
所有读取、更新和删除方法都支持排序规则。 下面列出了一些示例。
find()
和 sort()
单个查询可以指定对结果进行匹配和排序时使用的排序规则。 以下查询和排序操作使用德语排序规则,并将locale
参数设置为de
。
client = Mongo::Client.new([ "127.0.0.1:27017" ], :database => "test") docs = client[:contacts].find({ "city" => "New York" }, { "collation" => { "locale" => "de" } }).sort( "name" => 1 )
find_one_and_update()
名为 names
的集合包含以下文档:
{ "_id" : 1, "first_name" : "Hans" } { "_id" : 2, "first_name" : "Gunter" } { "_id" : 3, "first_name" : "Günter" } { "_id" : 4, "first_name" : "Jürgen" }
对collection执行的以下find_one_and_update
操作未指定排序规则。
client = Mongo::Client.new([ "127.0.0.1:27017" ], :database => "test") doc = client[:names].find_one_and_update( {"first_name" => { "$lt" => "Gunter" }}, { "$set" => { "verified" => true } })
由于Gunter
在collection中处于词法第一位,因此上述操作不会返回结果,也不会更新任何文档。
考虑相同的find_one_and_update
操作,但指定了排序规则。 区域设置为de@collation=phonebook
。
注意
某些区域设置提供collation=phonebook
选项,适用于以不同方式对专有名词和其他单词进行排序的语言。 根据de@collation=phonebook
排序规则,带变音符号的字符位于不带变音符号的相同字符之前。
client = Mongo::Client.new([ "127.0.0.1:27017" ], :database => "test") doc = client[:names].find_one_and_update( { "first_name" => { "$lt" => "Gunter" } }, { "$set" => { "verified" => true } }, { "collation" => { "locale" => "de@collation=phonebook" }, :return_document => :after } )
该操作返回以下更新后的文档:
{ "_id" => 3, "first_name" => "Günter", "verified" => true }
find_one_and_delete()
将numericOrdering
排序规则参数设置为true
,以将数字字符串按其数值进行比较。
collection numbers
包含以下文档:
{ "_id" : 1, "a" : "16" } { "_id" : 2, "a" : "84" } { "_id" : 3, "a" : "179" }
以下示例匹配字段a
的数值大于 100 的第一个文档并将其删除。
docs = numbers.find_one_and_delete({ "a" => { "$gt" => "100" } }, { "collation" => { "locale" => "en", "numericOrdering" => true } })
完成上述操作后,集合中保留以下文档:
{ "_id" : 1, "a" : "16" } { "_id" : 2, "a" : "84" }
如果在没有排序规则的情况下执行相同的操作,服务器会删除它找到的第一个a
词法值大于"100"
的文档。
numbers = client[:numbers] docs = numbers.find_one_and_delete({ "a" => { "$gt" => "100" } })
完成上述操作后, a
等于"16"
的文档已被删除,以下文档仍保留在collection中:
{ "_id" : 2, "a" : "84" } { "_id" : 3, "a" : "179" }
delete_many()
您可以将排序规则用于 Ruby 驱动程序中存在的所有各种批量操作。
collection recipes
包含以下文档:
{ "_id" : 1, "dish" : "veggie empanadas", "cuisine" : "Spanish" } { "_id" : 2, "dish" : "beef bourgignon", "cuisine" : "French" } { "_id" : 3, "dish" : "chicken molé", "cuisine" : "Mexican" } { "_id" : 4, "dish" : "chicken paillard", "cuisine" : "french" } { "_id" : 5, "dish" : "pozole verde", "cuisine" : "Mexican" }
将排序规则文档的strength
参数设置为1
或2
会导致服务器在查询筛选器中忽略大小写。 以下示例使用不区分大小写的查询筛选器删除cuisine
字段与French
匹配的所有记录。
client = Mongo::Client.new([ "127.0.0.1:27017" ], :database => "test") recipes = client[:recipes] docs = recipes.delete_many({ "cuisine" => "French" }, "collation" => { "locale" => "en_US", "strength" => 1 })
运行上述操作后,将从collection中删除_id
值为2
和4
的文档。
聚合(Aggregation)
要将排序规则与聚合操作一起使用,请在聚合选项中指定排序规则。
以下聚合示例使用名为names
的集合,并将first_name
字段分组在一起,计算每组中的结果总数,并按德语电话簿顺序对结果进行排序。
aggregation = names.aggregate( [ { "$group" => { "_id" => "$first_name", "name_count" => { "$sum" => 1 } } }, { "$sort" => { "_id" => 1 } }, ], { "collation" => { "locale" => "de@collation=phonebook" } } ) aggregation.each do |doc| #=> Yields a BSON::Document. end