Skip to content
On this page

一般来说,对 mongodb 中某个字符串字段 进行排序 是按 二进制 排序的

那么如果 类似 "123" 这种数据,能否按 数值的规则排序 > "20" 吗?

答案是有的,这里用到的是 Mongodb 索引中的 collation

我们创建一个表,里面写入 3 条数据,value 字段都是字符串类型的数值

db.createCollection('test');
db.test.insert({ value: '12345' });
db.person.insert({ value: '2345' });
db.person.insert({ value: '3456' });

对 value 字段进行排序

db.test.find({}).sort({ value: -1 })
{"_id" : ObjectId("5e7606e476d53a453c7135e8"),"value" : "3456"},
{"_id" : ObjectId("5e7606dd76d53a453c7135e7"),"value" : "2345"},
{"_id" : ObjectId("5e7606d276d53a453c7135e6"),"value" : "12345"},

不出意外的 是按照 value 的第一位 的 3 > 2 > 1 排的序

我们这里在 sort 前加上 collation 方法

db.test.find({}).collation({ locale: 'en', numericOrdering: true }).sort({ value: -1 })
{"_id" : ObjectId("5e7606d276d53a453c7135e6"),"value" : "12345"},
{"_id" : ObjectId("5e7606e476d53a453c7135e8"),"value" : "3456"},
{"_id" : ObjectId("5e7606dd76d53a453c7135e7"),"value" : "2345"},

这样就对 字符串 value 以数值的规则 进行了排序

Mongodb collation 详解

Collation allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks.

简而言之,Collation 允许 MongoDB 用户根据 不同的语言 定制 排序规则,举个例子,一个存储中国用户信息的集合。

db.createCollection('person');
db.person.insert({ name: '张三' });
db.person.insert({ name: '李四' });
db.person.insert({ name: '王五' });
db.person.insert({ name: '马六' });
db.person.insert({ name: '张七' });

默认情况下,名字字段会被当做一个普通的二机制字符串来对比,按照 name 字段排序的结果如下

db.person.find().sort({name: 1})
{ "_id" : ObjectId("586b98980cec8d86881cffac"), "name" : "张七" }
{ "_id" : ObjectId("586b98980cec8d86881cffa8"), "name" : "张三" }
{ "_id" : ObjectId("586b98980cec8d86881cffa9"), "name" : "李四" }
{ "_id" : ObjectId("586b98980cec8d86881cffaa"), "name" : "王五" }
{ "_id" : ObjectId("586b98980cec8d86881cffab"), "name" : "马六" }

而对于中文名字,通常有按拼音顺序排序的需求,这时就可以通过 collation 来搞定

db.createCollection('person', { collation: { locale: 'zh' } });
db.person.insert({ name: '张三' });
db.person.insert({ name: '李四' });
db.person.insert({ name: '王五' });
db.person.insert({ name: '马六' });
db.person.insert({ name: '张七' });

我们这里 插入几个 中文人名

db.createCollection('person', { collation: { locale: 'zh' } });
db.person.insert({ name: '张三' });
db.person.insert({ name: '李四' });
db.person.insert({ name: '王五' });
db.person.insert({ name: '马六' });
db.person.insert({ name: '张七' });

此时再按 name 字段排序,则会按照 locale 指定的中文规则来排序

db.person.find().sort({name: 1})
{ "_id" : ObjectId("586b995d0cec8d86881cffae"), "name" : "李四" }
{ "_id" : ObjectId("586b995d0cec8d86881cffb0"), "name" : "马六" }
{ "_id" : ObjectId("586b995d0cec8d86881cffaf"), "name" : "王五" }
{ "_id" : ObjectId("586b995d0cec8d86881cffb1"), "name" : "张七" }
{ "_id" : ObjectId("586b995d0cec8d86881cffad"), "name" : "张三" }

MongoDB 3.4 里,基本所有涉及字符串字段排序的命令,都支持指定 collation,比如「创建集合、创建索引、find」等;上述例子里在 createCollection 的时候指定了 collation,则该集合里所有字符串默认都会按指定的 collation 来排序,如果只想针对某一个字段来指定 collation,可以该字段创建指定 collation 的索引,例如

db.person.createIndex({ name: 1 }, { collation: { locale: 'zh' } });