How to Paginate the Query Results
On this page
- Create the Atlas Search Index With Static Mappings
- Required Roles
- Procedure
- Run a Query and Paginate the Results
- Procedure
- Retrieve Page 1 and Generate Pagination Tokens
- Retrieve Page 2 Using
searchAfter
- Return to Page 1 Using
searchBefore
- Jump from Page 2 to Page 5 Using
searchAfter
and$skip
- Use Facet with the Paginated Results
This tutorial demonstrates how to paginate the results of your Atlas Search
queries to build functions like "Next Page" and "Previous Page" in your
application. It also demonstrates how to jump across pages by using
$skip
and $limit
. This tutorial takes you
through the following steps:
Set up an Atlas Search index with static mappings for the
sample_mflix.movies
collection.Run Atlas Search queries against the indexed fields to return sequential results that allow you to do the following:
Traverse pages in-order to build functions like "Next Page" and "Previous Page".
Jump from the second to the fifth page and skip pages in the results.
Retrieve a count of the total number of movies in each genre in the results.
Before you begin, ensure that your Atlas cluster meets the requirements described in the Prerequisites.
Note
To use the Atlas Search $search
searchSequenceToken
to
retrieve sequential results, your Atlas cluster must run
MongoDB v6.0.13+ or v7.0.5+.
Create the Atlas Search Index With Static Mappings
In this section, you create an Atlas Search index that uses static
mappings to index the fields in the
sample_mflix.movies
collection.
Required Roles
To create an Atlas Search index, you must have Project Data Access Admin
or higher access to the project.
Procedure
In Atlas, go to the Clusters page for your project.
If it's not already displayed, select the organization that contains your desired project from the Organizations menu in the navigation bar.
If it's not already displayed, select your desired project from the Projects menu in the navigation bar.
If it's not already displayed, click Clusters in the sidebar.
The Clusters page displays.
Go to the Atlas Search page for your cluster.
You can go the Atlas Search page from the sidebar, the Data Explorer, or your cluster details page.
In the sidebar, click Atlas Search under the Services heading.
From the Select data source dropdown, select your cluster and click Go to Atlas Search.
The Atlas Search page displays.
Click the Browse Collections button for your cluster.
Expand the database and select the collection.
Click the Search Indexes tab for the collection.
The Atlas Search page displays.
Click the cluster's name.
Click the Atlas Search tab.
The Atlas Search page displays.
Define the Atlas Search index.
The following index definition configures index for the following fields:
title
field as the string type for full-text search against the fieldgenres
field as the stringFacet type for faceted search against the fieldreleased
field as the date type for sorting the results using the field
You can use the Atlas Search Visual Editor or the Atlas Search JSON Editor in the Atlas user interface to create the index.
Click Next.
Click Refine Your Index.
In the Index Configurations section, toggle to disable Dynamic Mapping.
Click Add Field in the Field Mappings section and click Add after configuring the settings for the following fields, one by one, in the Add Field Mapping window Customized Configuration tab.
Field NameData Type Configurationtitle
String
genres
stringFacet
released
Date
Click Save Changes.
Replace the default index definition with the following definition.
1 { 2 "mappings": { 3 "dynamic": false, 4 "fields": { 5 "title": { 6 "type": "string" 7 }, 8 "genres": { 9 "type": "stringFacet" 10 }, 11 "released": { 12 "type": "date" 13 } 14 } 15 } 16 } Click Next.
Run a Query and Paginate the Results
In this section, you run queries to retrieve results for movies with the
term summer
in the title. In the queries, you retrieve a point of
reference, which you then use in the subsequent queries to retrieve
additional results for the same term before and after the specified
point of reference.
Note
By default, Atlas Search sorts the documents in the results by the relevance
score of the documents. If multiple documents in the results have
identical scores, Atlas Search returns arbitrarily ordered results. To
return documents in a determined order, the queries specify a unique
field, released
, to sort the results.
This section demonstrates how to do the following:
Procedure
To run these queries, you must first do the following:
Connect to your cluster in mongosh
.
Open mongosh
in a terminal window and connect to your
cluster. For detailed instructions on connecting, see
Connect via mongosh.
Retrieve Page 1 and Generate Pagination Tokens
The sample query uses the following pipeline stages to retrieve results for the first page and retrieve tokens or a point of reference for subsequent queries:
Limits the results to | |
Includes only the
|
db.movies.aggregate([ { "$search": { "index": "pagination-tutorial", "text": { "path": "title", "query": "summer" }, "sort": { "released": 1 } } }, { "$limit": 10 }, { "$project": { "_id": 0, "title": 1, "released": 1, "genres": 1, "paginationToken" : { "$meta" : "searchSequenceToken" }, "score": { "$meta": "searchScore" } } } ])
[ { genres: [ 'Drama' ], title: "A Summer at Grandpa's", paginationToken: 'CKUdGgJgAA==', score: 2.262615203857422 }, { genres: [ 'Musical', 'Romance' ], title: 'Summer Stock', released: ISODate('1951-01-22T00:00:00.000Z'), paginationToken: 'CJsFGgkpAHw/0HT///8=', score: 3.000213623046875 }, { genres: [ 'Comedy', 'Romance' ], title: 'Smiles of a Summer Night', released: ISODate('1957-12-23T00:00:00.000Z'), paginationToken: 'CKIHGgkpAKDlpaf///8=', score: 2.0149309635162354 }, { genres: [ 'Drama' ], title: 'Violent Summer', released: ISODate('1959-11-13T00:00:00.000Z'), paginationToken: 'CI8JGgkpAJhJh7X///8=', score: 3.000213623046875 }, { genres: [ 'Drama', 'Romance' ], title: 'A Summer Place', released: ISODate('1959-11-18T00:00:00.000Z'), paginationToken: 'CLoJGgkpAGQJobX///8=', score: 2.579726457595825 }, { genres: [ 'Drama' ], title: 'The End of Summer', released: ISODate('1962-02-01T00:00:00.000Z'), paginationToken: 'CK0KGgkpAAzP18X///8=', score: 2.262615203857422 }, { genres: [ 'Drama', 'Romance' ], title: 'Summer and Smoke', released: ISODate('1962-04-01T00:00:00.000Z'), paginationToken: 'CMQKGgkpAECmB8f///8=', score: 2.579726457595825 }, { genres: [ 'Documentary', 'Sport' ], title: 'The Endless Summer', released: ISODate('1968-08-17T00:00:00.000Z'), paginationToken: 'CO4MGgkpAJjH5vX///8=', score: 2.579726457595825 }, { genres: [ 'Comedy', 'Drama', 'Romance' ], title: "Summer of '42", released: ISODate('1971-04-09T00:00:00.000Z'), paginationToken: 'CPQQGgkpAGRgUAkAAAA=', score: 2.579726457595825 }, { genres: [ 'Drama' ], title: 'That Certain Summer', released: ISODate('1972-11-01T00:00:00.000Z'), paginationToken: 'COwRGgkpAPQV0hQAAAA=', score: 2.579726457595825 } ]
Retrieve Page 2 Using searchAfter
To retrieve additional results, you specify the point of reference after which you want to retrieve the results. This query demonstrates how to retrieve results to build a function like "Next Page" in your application.
The sample query uses the following pipeline stages to retrieve
results for the second page using the token generated by
searchSequenceToken
from the prior query for the same term:
| |
Limits the results to | |
Includes only the
|
db.movies.aggregate([ { "$search": { "index": "pagination-tutorial", "text": { "path": "title", "query": "summer" }, "searchAfter": "COwRGgkpAPQV0hQAAAA=", "sort": { "released": 1 } } }, { "$limit": 10 }, { "$project": { "_id": 0, "title": 1, "released": 1, "genres": 1, "paginationToken" : { "$meta" : "searchSequenceToken" }, "score": { "$meta": "searchScore" } } } ])
[ { genres: [ 'Drama' ], title: 'Summer Wishes, Winter Dreams', released: ISODate('1974-09-09T00:00:00.000Z'), paginationToken: 'CMwSGgkpAECHcCIAAAA=', score: 2.262615203857422 }, { genres: [ 'Drama', 'Thriller' ], title: 'Shadows of a Hot Summer', released: ISODate('1978-09-01T00:00:00.000Z'), paginationToken: 'CPEVGgkpAGw/qz8AAAA=', score: 2.0149309635162354 }, { genres: [ 'Drama' ], title: 'Indian Summer', released: ISODate('1978-11-01T00:00:00.000Z'), paginationToken: 'CNYRGgkpAFhj5UAAAAA=', score: 3.000213623046875 }, { genres: [ 'Drama' ], title: 'Indian Summer', released: ISODate('1978-11-01T00:00:00.000Z'), paginationToken: 'CNsRGgkpAFhj5UAAAAA=', score: 3.000213623046875 }, { genres: [ 'Drama', 'Mystery' ], title: 'One Deadly Summer', released: ISODate('1983-05-11T00:00:00.000Z'), paginationToken: 'COwcGgkpAAjtIGIAAAA=', score: 2.579726457595825 }, { genres: [ 'Comedy' ], title: 'Summer Rental', released: ISODate('1985-08-09T00:00:00.000Z'), paginationToken: 'CL8fGgkpABTypHIAAAA=', score: 3.000213623046875 }, { genres: [ 'Drama', 'Romance' ], title: 'Summer', released: ISODate('1986-08-29T00:00:00.000Z'), paginationToken: 'CO0gGgkpAHCiY3oAAAA=', score: 3.5844719409942627 }, { genres: [ 'Drama', 'Thriller' ], title: 'Summer Camp Nightmare', released: ISODate('1987-04-17T00:00:00.000Z'), paginationToken: 'CNkiGgkpAHQ/CX8AAAA=', score: 2.579726457595825 }, { genres: [ 'Action', 'Crime', 'Drama' ], title: 'Cold Summer of 1953', released: ISODate('1988-06-01T00:00:00.000Z'), paginationToken: 'CNsjGgkpACjVTYcAAAA=', score: 2.262615203857422 }, { genres: [ 'Drama', 'War' ], title: 'That Summer of White Roses', released: ISODate('1989-07-11T00:00:00.000Z'), paginationToken: 'CI0mGgkpALSEc48AAAA=', score: 2.0149309635162354 } ]
Return to Page 1 Using searchBefore
To retrieve previous results, you specify the point of reference before which you want to retrieve the results. This query demonstrates how to retrieve results to build a function like "Previous Page" in your application.
The sample query uses the following pipeline stages to return to
results on the first page using the token generated by
searchSequenceToken
from the prior query for the same term:
| |
Limits the results to | |
Includes only the
|
Note
By default, Atlas Search returns the results in reverse order for queries
that specify tokens to retrieve results before a point of
reference. To return documents in-order, the query uses the
toArray() and the
JavaScript reverse()
methods.
db.movies.aggregate([ { "$search": { "index": "pagination-tutorial", "text": { "path": "title", "query": "summer" }, "searchBefore": "CMwSGgkpAECHcCIAAAA=", "sort": { "released": 1 } } }, { "$limit": 10 }, { "$project": { "_id": 0, "title": 1, "released": 1, "genres": 1, "paginationToken" : { "$meta" : "searchSequenceToken" }, "score": { "$meta": "searchScore" } } } ]).toArray().reverse()
[ { genres: [ 'Drama' ], title: "A Summer at Grandpa's", paginationToken: 'CKUdGgJgAA==', score: 2.262615203857422 }, { genres: [ 'Musical', 'Romance' ], title: 'Summer Stock', released: ISODate('1951-01-22T00:00:00.000Z'), paginationToken: 'CJsFGgkpAHw/0HT///8=', score: 3.000213623046875 }, { genres: [ 'Comedy', 'Romance' ], title: 'Smiles of a Summer Night', released: ISODate('1957-12-23T00:00:00.000Z'), paginationToken: 'CKIHGgkpAKDlpaf///8=', score: 2.0149309635162354 }, { genres: [ 'Drama' ], title: 'Violent Summer', released: ISODate('1959-11-13T00:00:00.000Z'), paginationToken: 'CI8JGgkpAJhJh7X///8=', score: 3.000213623046875 }, { genres: [ 'Drama', 'Romance' ], title: 'A Summer Place', released: ISODate('1959-11-18T00:00:00.000Z'), paginationToken: 'CLoJGgkpAGQJobX///8=', score: 2.579726457595825 }, { genres: [ 'Drama' ], title: 'The End of Summer', released: ISODate('1962-02-01T00:00:00.000Z'), paginationToken: 'CK0KGgkpAAzP18X///8=', score: 2.262615203857422 }, { genres: [ 'Drama', 'Romance' ], title: 'Summer and Smoke', released: ISODate('1962-04-01T00:00:00.000Z'), paginationToken: 'CMQKGgkpAECmB8f///8=', score: 2.579726457595825 }, { genres: [ 'Documentary', 'Sport' ], title: 'The Endless Summer', released: ISODate('1968-08-17T00:00:00.000Z'), paginationToken: 'CO4MGgkpAJjH5vX///8=', score: 2.579726457595825 }, { genres: [ 'Comedy', 'Drama', 'Romance' ], title: "Summer of '42", released: ISODate('1971-04-09T00:00:00.000Z'), paginationToken: 'CPQQGgkpAGRgUAkAAAA=', score: 2.579726457595825 }, { genres: [ 'Drama' ], title: 'That Certain Summer', released: ISODate('1972-11-01T00:00:00.000Z'), paginationToken: 'COwRGgkpAPQV0hQAAAA=', score: 2.579726457595825 } ]
Jump from Page 2 to Page 5 Using searchAfter
and $skip
To skip results and jump from page 2 to 5, you use the token generated by
searchSequenceToken
to specify the point of reference after which you
want to retrieve the results and then skip twenty documents in the
results. This query demonstrates how to retrieve results to build a
function in your application that allows skipping pages.
The sample query uses the following pipeline stages to jump to
results on page 5 by using the token generated by searchSequenceToken
from the prior query for the same term and by
using the $skip
and $limit
stages:
| |
Skips 20 documents in the results after the specified point of
reference, which is the token associated with the twentieth
document in the results for the query you ran to
Retrieve Page 2 Using | |
Limits the results to | |
Includes only the
|
db.movies.aggregate([ { "$search": { "index": "pagination-tutorial", "text": { "path": "title", "query": "summer" }, "searchAfter": "COwRGgkpAPQV0hQAAAA=", "sort": { "released": 1 } } }, { "$skip": 20 }, { "$limit": 10 }, { "$project": { "_id": 0, "title": 1, "released": 1, "genres": 1, "paginationToken" : { "$meta" : "searchSequenceToken" }, "score": { "$meta": "searchScore" } } } ])
[ { genres: [ 'Drama' ], title: 'A Storm in Summer', released: ISODate('2000-02-27T00:00:00.000Z'), paginationToken: 'CO5FGgkpAChakN0AAAA=', score: 2.262615203857422 }, { genres: [ 'Comedy', 'Romance' ], title: 'Wet Hot American Summer', released: ISODate('2002-04-11T00:00:00.000Z'), paginationToken: 'CKtIGgkpAFBUIu0AAAA=', score: 2.262615203857422 }, { genres: [ 'Comedy', 'Drama', 'Romance' ], title: 'Summer Things', released: ISODate('2002-10-09T00:00:00.000Z'), paginationToken: 'CIpPGgkpAFxzxvAAAAA=', score: 3.000213623046875 }, { genres: [ 'Adventure', 'Drama', 'Family' ], title: 'Wolf Summer', released: ISODate('2003-02-28T00:00:00.000Z'), paginationToken: 'COZWGgkpAGS6ofMAAAA=', score: 3.000213623046875 }, { genres: [ 'Animation', 'Adventure' ], title: 'Nasu: Summer in Andalusia', released: ISODate('2003-06-26T00:00:00.000Z'), paginationToken: 'CNlaGgkpAMxoAfYAAAA=', score: 2.262615203857422 }, { genres: [ 'Drama' ], title: 'Spring, Summer, Fall, Winter... and Spring', released: ISODate('2004-05-28T00:00:00.000Z'), paginationToken: 'CJ5ZGgkpAOjnyPwAAAA=', score: 1.8161234855651855 }, { genres: [ 'Comedy', 'Drama', 'Romance' ], title: 'Summer Storm', released: ISODate('2004-09-02T00:00:00.000Z'), paginationToken: 'CMVfGgkpAMRwvP4AAAA=', score: 3.000213623046875 }, { genres: [ 'Drama' ], title: 'Summer in the Golden Valley', released: ISODate('2004-10-08T00:00:00.000Z'), paginationToken: 'CNNWGgkpALTVdf8AAAA=', score: 2.0149309635162354 }, { genres: [ 'Drama', 'Romance' ], title: 'My Summer of Love', released: ISODate('2005-07-01T00:00:00.000Z'), paginationToken: 'CL5aGgkpAEyxzwQBAAA=', score: 2.262615203857422 }, { genres: [ 'Drama' ], title: 'Summer in Berlin', released: ISODate('2006-01-05T00:00:00.000Z'), paginationToken: 'CPZmGgkpANzclwgBAAA=', score: 2.579726457595825 } ]
Use Facet with the Paginated Results
This section demonstrates how searchSequenceToken
can be used with Atlas Search facets.
The sample query uses the following pipeline stages:
| |
Adds the | |
Limits the results to | |
Returns the following fields:
|
db.movies.aggregate([ { "$search": { "index": "pagination-tutorial", "facet": { "operator": { "text": { "path": "title", "query": "summer" } }, "facets": { "genresFacet": { "type": "string", "path": "genres" } } } } }, { "$addFields": { "paginationToken" : { "$meta" : "searchSequenceToken" } } }, { "$limit": 10 }, { "$facet": { "docs": [ { "$project": { "_id": 0, "title": 1, "released": 1, "genres": 1, "paginationToken" : 1 } } ], "meta": [ { "$replaceWith": "$$SEARCH_META" }, { "$limit": 1 } ] } }, { "$set": { "meta": { "$arrayElemAt": ["$meta", 0] } } } ])
[ { docs: [ { genres: [ 'Drama', 'Romance' ], title: 'Summer', released: ISODate('1986-08-29T00:00:00.000Z'), paginationToken: 'CO0gFf1nZUA=' }, { genres: [ 'Musical', 'Romance' ], title: 'Summer Stock', released: ISODate('1951-01-22T00:00:00.000Z'), paginationToken: 'CJsFFYADQEA=' }, { genres: [ 'Drama' ], title: 'Violent Summer', released: ISODate('1959-11-13T00:00:00.000Z'), paginationToken: 'CI8JFYADQEA=' }, { genres: [ 'Drama' ], title: 'Indian Summer', released: ISODate('1978-11-01T00:00:00.000Z'), paginationToken: 'CNYRFYADQEA=' }, { genres: [ 'Drama' ], title: 'Indian Summer', released: ISODate('1978-11-01T00:00:00.000Z'), paginationToken: 'CNsRFYADQEA=' }, { genres: [ 'Comedy' ], title: 'Summer Rental', released: ISODate('1985-08-09T00:00:00.000Z'), paginationToken: 'CL8fFYADQEA=' }, { genres: [ 'Comedy', 'Drama', 'Romance' ], title: 'Summer Things', released: ISODate('2002-10-09T00:00:00.000Z'), paginationToken: 'CIpPFYADQEA=' }, { genres: [ 'Adventure', 'Drama', 'Family' ], title: 'Wolf Summer', released: ISODate('2003-02-28T00:00:00.000Z'), paginationToken: 'COZWFYADQEA=' }, { genres: [ 'Comedy', 'Drama', 'Romance' ], title: 'Summer Storm', released: ISODate('2004-09-02T00:00:00.000Z'), paginationToken: 'CMVfFYADQEA=' }, { genres: [ 'Drama', 'Romance' ], title: 'Summer Palace', released: ISODate('2007-04-18T00:00:00.000Z'), paginationToken: 'CIRrFYADQEA=' } ], meta: { count: { lowerBound: Long('65') }, facet: { genresFacet: { buckets: [ { _id: 'Drama', count: Long('48') }, { _id: 'Romance', count: Long('20') }, { _id: 'Comedy', count: Long('19') }, { _id: 'Family', count: Long('7') }, { _id: 'Adventure', count: Long('5') }, { _id: 'Crime', count: Long('5') }, { _id: 'Mystery', count: Long('5') }, { _id: 'Thriller', count: Long('5') }, { _id: 'Horror', count: Long('4') }, { _id: 'Action', count: Long('3') } ] } } } } ]