cursor.skip()
Definition
cursor.skip(<offset>)
Important
mongosh Method
This page documents a
mongosh
method. This is not the documentation for a language-specific driver, such as Node.js.For MongoDB API drivers, refer to the language-specific MongoDB driver documentation.
Call the
skip()
method on a cursor to control where MongoDB begins returning results. This approach may be useful in implementing paginated results.Note
You must apply
skip()
to the cursor before retrieving any documents from the database.The
skip()
method has the following parameter:ParameterTypeDescriptionoffset
numberThe number of documents to skip in the results set.
Compatibility
This method is available in deployments hosted in the following environments:
MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
Note
This command is supported in all MongoDB Atlas clusters. For information on Atlas support for all commands, see Unsupported Commands.
MongoDB Enterprise: The subscription-based, self-managed version of MongoDB
MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB
Behavior
Using skip()
with sort()
If using skip()
with sort()
, be
sure to include at least one field in your sort that contains
unique values, before passing results to skip()
.
Sorting on fields that contain duplicate values may return an inconsistent sort order for those duplicate fields over multiple executions, especially when the collection is actively receiving writes.
The easiest way to guarantee sort consistency is to include the
_id
field in your sort query.
See Consistent sorting with the sort() method for more information.
Using skip()
with limit()
When you chain skip()
and limit()
, the
method chaining order does not affect the results. The server always
applies the skip operation based on the sort order before it applies the
limit on how many documents to return.
The following code example shows different chaining orders for
skip()
and limit()
that always produce
the same query results for the same data set:
db.myColl.find().sort({_id: 1}).skip(3).limit(6); db.myColl.find().sort({_id: 1}).limit(6).skip(3);
Pagination Example
Using skip()
The following JavaScript function uses skip()
to
paginate a collection by its _id
field:
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 ); } ); }
The skip()
method requires the server to scan from the
beginning of the input results set before beginning to return results.
As the offset increases, skip()
will become slower.
Using Range Queries
Range queries can use indexes to avoid scanning
unwanted documents, typically yielding better performance as the offset
grows compared to using skip()
for pagination.
Descending Order
Use this procedure to implement pagination with range queries:
Choose a field such as
_id
which generally changes in a consistent direction over time and has a unique index to prevent duplicate values,Query for documents whose field is less than the start value using the
$lt
andsort()
operators, andStore the last-seen field value for the next query.
For example, the following function uses the above procedure to print
pages of student names from a collection, sorted approximately in order
of newest documents first using the _id
field (that is, in
descending order):
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; }
You may then use the following code to print all student names using this
pagination function, using MaxKey
to start
from the largest possible key:
let currentKey = MaxKey; while (currentKey !== null) { currentKey = printStudents(currentKey, 10); }
Note
While ObjectId values should increase over time, they are not necessarily monotonic. This is because they:
Only contain one second of temporal resolution, so ObjectId values created within the same second do not have a guaranteed ordering, and
Are generated by clients, which may have differing system clocks.
Ascending Order
Returning paginated results in ascending order is similar to the
previous, but uses $gt
with an ascending sort order:
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; }
Using this function is likewise similar, but with
MinKey
as the starting key:
let currentKey = MinKey; while (currentKey !== null) { currentKey = printStudents(currentKey, 10); }