文档菜单
文档首页
/ / /
Ruby MongoDB 驱动程序
/

排序规则

本页面

  • 概述
  • 使用方法
  • 支持排序规则的运算

新增在版本3.4.

排序规则是用于比较字符串的规则集合,通常用于特定的自然语言。

例如,在加拿大法语中,给定单词的最后一个重音符号决定了排序顺序。

考虑以下法语单词

cote < coté < côte < côté

使用加拿大法语排序规则进行的排序顺序将得到以下结果

cote < côte < coté < côté

如果未指定排序规则,MongoDB 使用字符串的简单二进制比较。因此,单词的排序顺序将是

cote < coté < côte < côté

您可以在创建集合和索引时指定默认的排序规则,或者指定 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 手册条目。

以下示例在 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 选项。

以下示例在address_book集合的name字段上创建了一个索引,启用了unique参数,并使用默认排序规则,将locale设置为en_US

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 })

所有读取、更新和删除方法都支持排序规则。以下是一些示例。

单个查询可以指定用于匹配和排序结果的排序规则。以下查询和排序操作使用德语排序规则,将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 )

名为 names 的集合包含以下文档

{ "_id" : 1, "first_name" : "Hans" }
{ "_id" : 2, "first_name" : "Gunter" }
{ "_id" : 3, "first_name" : "Günter" }
{ "_id" : 4, "first_name" : "Jürgen" }

在集合上执行的以下 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 在集合中按字典序排在最前面,上述操作没有返回结果,也没有更新任何文档。

考虑相同的 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 }

numericOrdering 排序参数设置为 true 以按数值比较数值字符串。

名为 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" 的文档已被删除,集合中剩下以下文档

{ "_id" : 2, "a" : "84" }
{ "_id" : 3, "a" : "179" }

您可以使用与 Ruby 驱动程序中所有各种批量操作一起使用的排序。

集合 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 参数设置为 12 将导致服务器在查询过滤器中忽略大小写。以下示例使用不区分大小写的查询过滤器删除所有字段 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 })

上述操作执行后,具有 _id 值为 24 的文档将从集合中删除。

要在聚合操作中使用排序,请在聚合选项中指定排序。

以下聚合示例使用名为 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

返回

Atlas 搜索索引