本篇我们学习 MongoDB 中的 limit() 方法,它可以限制查询返回的文档数量。

limit() 方法

find() 方法可能会查找出大量的文档,但是应用程序不一定需要所有的返回结果。为了限制返回文档的数量,可以使用 limit() 方法:

db.collection.find(<query>).limit(<documentCount>)

其中, 的取值范围为 -2 31 到 231。如果指定了超出该范围的参数, limit() 返回的结果不确定。

如果 指定了负数值,limit() 返回结果和对应正数参数的结果相同。另外,系统在返回一个批次的文档之后将会关闭游标。如果查询结果的数量不止一个批次,实际返回的结果数量将会小于指定的数量。

如果将 设置为 0,相当于没有限制返回结果的数量。

limit() 方法和 SQL 语句中的 LIMIT 子句作用类似。

如果想要使用 limit() 方法获取确定内容的结果,需要先对结果进行排序:

cursor
   .sort({...})
   .limit(<documentCount>)

在实际应用中,我们通常结合 limit() 和 skip() 方法实现分页功能。skip() 方法用于指定从哪一个文档开始返回结果:

cursor.skip(<offset>)

以下语法用于返回第 pageNo 页中的文档,每页包含 documentCount 个文档:

db.collection.find({...}
).sort({...}
).skip(pageNo > 0 ? ( ( pageNo - 1 ) * documentCount) : 0
).limit(documentCount);

skip() 意味着 MongoDB 服务器需要从结果集中扫描并忽略指定数量的文档,然后开始返回结果。因此,随着 的增加,skip() 方法会越来越慢。

limit() 和 skip() 方法和 SQL 中的 LIMIT OFFSET 子句作用类似。

limit() 示例

接下来的示例将会使用以下产品集合:

db.products.insertMany([
    { "_id" : 1, "name" : "xPhone", "price" : 799, "releaseDate" : ISODate("2011-05-14T00:00:00Z"), "spec" : { "ram" : 4, "screen" : 6.5, "cpu" : 2.66 }, "color" : [ "white", "black" ], "storage" : [ 64, 128, 256 ] },
    { "_id" : 2, "name" : "xTablet", "price" : 899, "releaseDate" : ISODate("2011-09-01T00:00:00Z"), "spec" : { "ram" : 16, "screen" : 9.5, "cpu" : 3.66 }, "color" : [ "white", "black", "purple" ], "storage" : [ 128, 256, 512 ] },
    { "_id" : 3, "name" : "SmartTablet", "price" : 899, "releaseDate" : ISODate("2015-01-14T00:00:00Z"), "spec" : { "ram" : 12, "screen" : 9.7, "cpu" : 3.66 }, "color" : [ "blue" ], "storage" : [ 16, 64, 128 ] },
    { "_id" : 4, "name" : "SmartPad", "price" : 699, "releaseDate" : ISODate("2020-05-14T00:00:00Z"), "spec" : { "ram" : 8, "screen" : 9.7, "cpu" : 1.66 }, "color" : [ "white", "orange", "gold", "gray" ], "storage" : [ 128, 256, 1024 ] },
    { "_id" : 5, "name" : "SmartPhone", "price" : 599, "releaseDate" : ISODate("2022-09-14T00:00:00Z"), "spec" : { "ram" : 4, "screen" : 9.7, "cpu" : 1.66 }, "color" : [ "white", "orange", "gold", "gray" ], "storage" : [ 128, 256 ] },
    { "_id" : 6, "name" : "xWidget", "spec" : { "ram" : 64, "screen" : 9.7, "cpu" : 3.66 }, "color" : [ "black" ], "storage" : [ 1024 ] },
    { "_id" : 7, "name" : "xReader", "price" : null, "spec" : { "ram" : 64, "screen" : 6.7, "cpu" : 3.66 }, "color" : [ "black", "white" ], "storage" : [ 128 ] }
])

示例一:查找最昂贵的产品

以下示例使用 limit() 方法获取产品集合中最贵的产品,返回结果中包含了 _id、name 以及 price 字段:

db.products.find({}, {
    name: 1,
    price: 1
}).sort({
    price: -1
}).limit(1);

查询返回的结果如下:

[ { _id: 2, name: 'xTablet', price: 899 } ]

在示例中,我们按照价格从高到低对产品进行排序,然后使用 limit() 返回了排名第一的产品。产品集合中包含了 2 个价格为 899 的产品,因此返回的文档取决于它们在磁盘中的存储顺序。

为了返回确定性的结果,排序结果必须具有唯一性。例如:

db.products.find({}, {
    name: 1,
    price: 1
}).sort({
    price: -1,
    name: 1
}).limit(1);

查询返回的结果如下:

[ { _id: 3, name: 'SmartTablet', price: 899 } ]

示例同时使用了价格和名称进行排序,当价格相同时按照名称升序进行排列,此时查询返回了确定的结果。

示例二:实现分页查询功能

假如我们想要将产品进行分页展示,每页显示 2 个产品。以下查询使用 skip() 和 limit() 方法获取了第 2 页中的文档:

db.products.find({}, {
    name: 1,
    price: 1
}).sort({
    price: -1,
    name: 1
}).skip(2).limit(2);

查询结果如下:

[
  { _id: 1, name: 'xPhone', price: 799 },
  { _id: 4, name: 'SmartPad', price: 699 }
]