Docs 菜单

Docs 主页开发应用程序MongoDB Manual

cursor.sort()

在此页面上

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

重要

mongosh 方法

这是一个 mongosh方法。这不是Node.js或其他特定于编程语言的驱动程序方法的文档。

在大多数情况下, mongosh方法的工作方式与旧版mongo shell 方法相同。但是,某些旧方法在mongosh中不可用。

有关旧版mongo shell 文档,请参阅相应 MongoDB Server 版本的文档:

对于 MongoDB API 驱动程序,请参阅特定语言的MongoDB 驱动程序文档。

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

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

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

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

范围
类型
说明
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 搜索,您可以使用 { $meta: "textScore" } 表达式按相关性分数降序进行排序。

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

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

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

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

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。此算法会缓冲底层索引或collection访问到目前为止看到的前k个结果(或最后一个,取决于排序顺序)。如果在任何时候这些k结果的内存占用超过100兆字节,则查询将失败,除非查询指定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()