Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

cursor.sort()

在此页面上

  • 定义
  • 兼容性
  • 语法
  • 行为
  • 示例
  • 按自然顺序返回
cursor.sort(sort)

重要

mongosh 方法

本页面提供 mongosh 方法的相关信息。这不是特定于语言的驱动程序(例如 Node.js)的文档。

如需了解 MongoDB API 驱动程序,请参阅特定语言的 MongoDB 驱动程序文档。

指定查询返回匹配文档的顺序。在从数据库检索任何文档之前,必须对游标应用 sort()

可以使用 cursor.sort(sort) 查找托管在以下环境中的部署:

  • MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务

  • MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本

  • MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本

sort() 方法具有以下参数:

Parameter
类型
说明
sort
文档
定义结果集排序顺序的文档。

sort 参数包含字段和值对,格式如下:

{ field: value }

排序文件可以指定对现有字段进行升序或降序排序,或对文本分数元数据进行排序

  • 您最多可以对 32 个键进行排序。

  • 为排序模式提供重复字段会导致错误。

MongoDB 不按特定顺序将文档存储在集合中。对包含重复值的字段进行排序时,可能会以任何顺序返回包含这些值的文档。

如果需要一致的排序顺序,请在排序中至少纳入一个包含唯一值的字段。最简单方法是在排序查询中纳入 _id 字段。

考虑以下restaurant集合:

db.restaurants.insertMany( [
{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan"},
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens"},
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"},
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan"},
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn"},
] );

以下命令使用 sort() 方法对 borough 字段进行排序:

db.restaurants.find().sort( { "borough": 1 } )

在此示例中,排序顺序可能不一致,因为 borough 字段包含 ManhattanBrooklyn 的重复值。文档按 borough 的字母顺序返回,但具有 borough 的重复值的文档的顺序在多次执行同一排序中可能不相同。例如,以下是上述命令两次不同执行的结果:

{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn" }
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn" }
{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan" }
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan" }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens" }
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn" }
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn" }
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan" }
{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan" }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens" }

虽然 borough 的值仍按字母顺序排序,但包含 borough 重复值的文档(即 ManhattanBrooklyn)的顺序不同。

要实现一致的排序,请在排序中添加一个仅包含唯一值的字段。以下命令使用 sort() 方法对 borough 字段和 _id 字段进行排序:

db.restaurants.find().sort( { "borough": 1, "_id": 1 } )

由于 _id 字段始终保证包含唯一值,因此在同一排序的多次执行中返回的排序顺序将始终相同。

在排序参数中指定要排序的一个或多个字段,并指定值 1-1 以分别指定升序或降序排序。

以下操作首先按 age 字段以降序对文档进行排序,然后按 posts 字段以升序对文档进行排序:

db.users.find({ }).sort( { age : -1, posts: 1 } )

在排序操作中比较不同 BSON 类型的值时,MongoDB 使用以下从低到高的比较顺序:

  1. MinKey(内部类型)

  2. null

  3. 数值(int、long、double、decimal)

  4. 符号,字符串

  5. 对象

  6. 阵列

  7. BinData

  8. ObjectId

  9. 布尔

  10. Date

  11. 时间戳

  12. 正则表达式

  13. MaxKey(内部类型)

有关特定类型的比较/排序顺序的详细信息,请参阅比较/排序顺序。

注意

$text 提供自管理(非 Atlas)部署的文本查询功能。对于托管在 MongoDB Atlas 上的数据,MongoDB 提供了一种改进的全文查询解决方案 Atlas Search

如果您使用 $text,您可以使用 { $meta: "textScore" } 表达式按相关性分数降序进行排序。

以下示例文档将指定按 "textScore" 元数据排列的降序排序:

db.users.find(
{ $text: { $search: "operating" } },
{ score: { $meta: "textScore" }}
).sort({ score: { $meta: "textScore" } })

"textScore" 元数据按降序排序。

有关详细信息,请参阅 $meta

当 MongoDB 按数组值字段对文档进行排序时,排序键取决于排序是升序还是降序:

  • 在升序排序中,排序键是数组中的最低值。

  • 在降序排序中,排序键是数组中的最高值。

查询过滤器不影响排序键的选择。

例如,使用以下文档创建 shoes 集合:

db.shoes.insertMany( [
{ _id: 'A', sizes: [ 7, 11 ] },
{ _id: 'B', sizes: [ 8, 9, 10 ] }
] )

以下查询按 sizes 字段以升序和降序对文档进行排序:

// Ascending sort
db.shoes.find().sort( { sizes: 1 } )
// Descending sort
db.shoes.find().sort( { sizes: -1 } )

前两个查询均首先返回包含 _id: 'A' 的文档,因为 711 分别是 sizes 数组中条目中的最小值和最大值。

以下查询查找尺码大于 10 的鞋子,并按鞋子尺码的升序对结果进行排序:

db.shoes.find( { sizes: { $gte: 7 } } ).sort( { sizes: 1 } )

尽管过滤器包含大于 7sizes 条件,但由于查询过滤器不影响排序键的选择,该查询仍会返回带有 _id: 'A' 的文档。

MongoDB 可从包含排序字段的索引中获取排序操作的结果。如果此排序使用与查询谓词相同的索引,MongoDB 则可能会使用多个索引支持排序操作。

如果 MongoDB 无法使用一个或多个索引来获取排序顺序,则 MongoDB 必须对数据执行阻塞排序操作。阻塞排序表示 MongoDB 必须在返回结果之前消耗并处理排序的所有输入文档。阻塞排序不会阻塞对集合或数据库的并发操作。

使用索引的排序操作通常比阻塞排序性能更好。有关创建索引以支持排序操作的更多信息,请参阅使用索引对查询结果进行排序

如果 MongoDB 需要使用超过 100 MB 的系统内存进行阻塞排序操作,则 MongoDB 将返回错误,除非查询指定了 cursor.allowDiskUse()allowDiskUse() 允许 MongoDB 在处理阻塞排序操作时使用磁盘上的临时文件来存储超过 100 MB 系统内存限制的数据。

要检查 MongoDB 是否必须执行阻塞排序,请在查询中添加 cursor.explain() 并检查解释结果。如果查询计划包含 SORT 阶段,则 MongoDB 必须在 100 MB 内存限制下执行阻塞排序操作。

要防止阻塞排序消耗过多内存:

提示

另请参阅:

您可以将 sort()limit() 结合使用,以返回第一批(按排序顺序)k 文档,其中 k 是指定限制。

如果 MongoDB 无法通过索引扫描获得排序顺序,则 MongoDB 使用 top-k 排序算法。此算法会缓冲基础索引或集合访问迄今为止看到的前 k 项结果(或最后一项,取决于排序顺序)。如果在任何点这些 k 结果的内存占用超过 100 MB,查询就会失败,除非查询指定 cursor.allowDiskUse()

提示

另请参阅:

当一组结果同时进行排序投影时,MongoDB 查询引擎始终会应用排序操作。

集合 orders 包含以下文档:

{ _id: 1, item: { category: "cake", type: "chiffon" }, amount: 10 }
{ _id: 2, item: { category: "cookies", type: "chocolate chip" }, amount: 50 }
{ _id: 3, item: { category: "cookies", type: "chocolate chip" }, amount: 15 }
{ _id: 4, item: { category: "cake", type: "lemon" }, amount: 30 }
{ _id: 5, item: { category: "cake", type: "carrot" }, amount: 20 }
{ _id: 6, item: { category: "brownies", type: "blondie" }, amount: 10 }

以下查询返回 orders 集合中的所有文档,但不会指定排序顺序:

db.orders.find()

此查询将以不确定的顺序返回文档:

{ "_id" : 1, "item" : { "category" : "cake", "type" : "chiffon" }, "amount" : 10 }
{ "_id" : 2, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 50 }
{ "_id" : 3, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 15 }
{ "_id" : 4, "item" : { "category" : "cake", "type" : "lemon" }, "amount" : 30 }
{ "_id" : 5, "item" : { "category" : "cake", "type" : "carrot" }, "amount" : 20 }
{ "_id" : 6, "item" : { "category" : "brownies", "type" : "blondie" }, "amount" : 10 }

以下查询指定对 amount 字段进行降序排序。

db.orders.find().sort( { amount: -1 } )

此查询返回以下文档,按 amount 的降序排列:

{ "_id" : 2, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 50 }
{ "_id" : 4, "item" : { "category" : "cake", "type" : "lemon" }, "amount" : 30 }
{ "_id" : 5, "item" : { "category" : "cake", "type" : "carrot" }, "amount" : 20 }
{ "_id" : 3, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 15 }
{ "_id" : 1, "item" : { "category" : "cake", "type" : "chiffon" }, "amount" : 10 }
{ "_id" : 6, "item" : { "category" : "brownies", "type" : "blondie" }, "amount" : 10 }

以下查询使用嵌入式文档 item 中的字段指定排序顺序。查询首先按 category 字段升序排序,然后在每个 category 中按 type 字段升序排序。

db.orders.find().sort( { "item.category": 1, "item.type": 1 } )

此查询将返回以下文档,并先按 category 字段进行排序,然后在每个类别中按 type 字段进行排序:

{ "_id" : 6, "item" : { "category" : "brownies", "type" : "blondie" }, "amount" : 10 }
{ "_id" : 5, "item" : { "category" : "cake", "type" : "carrot" }, "amount" : 20 }
{ "_id" : 1, "item" : { "category" : "cake", "type" : "chiffon" }, "amount" : 10 }
{ "_id" : 4, "item" : { "category" : "cake", "type" : "lemon" }, "amount" : 30 }
{ "_id" : 2, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 50 }
{ "_id" : 3, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 15 }

$natural 参数会根据项目在数据库中的自然顺序来返回项目。此排序是一项内部实现功能,您不应依赖于文档的任何特定排序。

包含按 $natural 排序的查询使用索引来满足查询谓词,但以下情况除外:如果查询谓词是 _id 字段 { _id: <value> } 上的相等条件,则按 $natural 排序的查询可以使用 _id 索引。

提示

另请参阅:

后退

cursor.skip