Docs 菜单

Docs 主页开发应用程序MongoDB Manual

cursor.skip()

在此页面上

  • 定义
  • 行为
  • 分页示例
cursor.skip(<offset>)

重要

mongosh 方法

本页介绍了 mongosh方法。这不是特定于语言的驱动程序(例如 Node.js)的文档。

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

在游标上调用skip()方法来控制 MongoDB 开始返回结果的位置。此方法可能有助于实现分页结果。

注意

从数据库检索任何文档之前,必须对游标应用skip()

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

范围
类型
说明
offset
数字
结果集中要跳过的文档数。

如果将skip()sort()一起使用,请务必在将结果传递给skip()之前,在排序中至少包含一个包含唯一值的字段。

对包含重复值的字段进行排序时,可能会在多次执行中对这些重复字段返回不一致的排序顺序,尤其是当集合正在接收写入时。

为确保排序一致,最简单方法是在排序查询中纳入 _id 字段。

有关更多信息,请参阅使用 sort() 方法进行一致排序

当您链接skip()limit()时,方法链接顺序不会影响结果。服务器始终会根据排序顺序应用跳过操作,然后再应用对返回文档数量的限制。

以下代码示例显示了skip()limit()的不同链接顺序,它们总是为同一数据集生成相同的查询结果:

db.myColl.find().sort({_id: 1}).skip(3).limit(6);
db.myColl.find().sort({_id: 1}).limit(6).skip(3);

以下 JavaScript 函数使用skip()_id字段对集合进行分页:

function printStudents(pageNumber, nPerPage) {
print( "Page: " + pageNumber );
db.students.find()
.sort( { _id: 1 } )
.skip( pageNumber > 0 ? ( ( pageNumber - 1 ) * nPerPage ) : 0 )
.limit( nPerPage )
.forEach( student => {
print( student.name );
} );
}

skip()方法要求服务器在开始返回结果之前从输入结果集的开头开始扫描。随着偏移量的增加, skip()会变慢。

范围查询可以使用索引来避免扫描不需要的文档,随着偏移量的增长,与使用skip()进行分页相比,范围查询通常会产生更好的性能。

使用此过程以通过范围查询实现分页:

  • 选择 _id 等字段,该字段通常会随着时间的推移而朝着一致的方向变化,并且具有唯一索引以防止重复值,

  • 使用 $ltsort() 操作符查询字段小于起始值的文档,以及

  • 存储最近看到的字段值以供下一次查询。

例如,以下函数使用上述过程来输出集合中的学生姓名页面,而这些页面大致会按先使用 _id 字段的最新文档的顺序来排序(即,按降序排列):

function printStudents(startValue, nPerPage) {
let endValue = null;
db.students.find( { _id: { $lt: startValue } } )
.sort( { _id: -1 } )
.limit( nPerPage )
.forEach( student => {
print( student.name );
endValue = student._id;
} );
return endValue;
}

然后,可以使用以下代码利用此分页函数打印所有学生姓名,使用 MaxKey 从最大可能的键开始:

let currentKey = MaxKey;
while (currentKey !== null) {
currentKey = printStudents(currentKey, 10);
}

注意

虽然 ObjectId 值应该随着时间的推移而增加,但它们不一定是单调的。这是因为他们:

  • 仅包含一秒钟的时间分辨率,因此,不能保证在同一秒内创建的 ObjectID 值的顺序,并且

  • 由可能具有不同系统时钟的客户端生成。

按升序返回分页结果的方法与之前相类,但使用 $gt 并结合升序排序:

function printStudents(startValue, nPerPage) {
let endValue = null;
db.students.find( { _id: { $gt: startValue } } )
.sort( { _id: 1 } )
.limit( nPerPage )
.forEach( student => {
print( student.name );
endValue = student._id;
} );
return endValue;
}

使用该函数的方法与此类似,但起始键为 MinKey

let currentKey = MinKey;
while (currentKey !== null) {
currentKey = printStudents(currentKey, 10);
}
← cursor.size()