Pagination
Pagination is commonly used by applications to consume large amount of data by dividing it into small pages. Modern applications leverage one of the following commonly used UX patterns:
- Traditional pagination using page numbers - Users can visit next or previous page of results or jump an arbitraty page by choosing page numbers. The main benefit to a user is a visibility into number of pages and ability to jump to an arbitrary page number.
- Infinite scrolling - When a website returns only a part of the results. But as the users scroll down to the end of the page, additional results are loaded and rendered for the users. This allows users to browse as many results they want without having to click anything, which is friendlier to mobile device users.
Paginating through search results
In this section we'll see the constructs provided by our SDK that assist developers in building out pagination into their apps. Considering the search example let's work through the search index:
const client = new Tigris();
const search = client.getSearch();
const catalog = await search.getIndex<Catalog>("catalog");
Using page numbers
To retrieve a page of results, you can simply use search(query, page)
method with page number and
page size. Following query fetches the first page of results with page size set as 10
const query: SearchQuery<Catalog> = {
q: "running",
hitsPerPage: 10, // Optional. Defaults to 20
};
const result: SearchResult<Catalog> = await catalog.search(query, 1);
console.log(result);
Output
{
"hits": [
{
"document": {
"brand": "adidas",
"price": 35,
"review": {
"author": "olivia",
"rating": 7.5
},
"popularity": 7,
"id": "6",
"labels": "clothing",
"name": "running shorts"
},
"meta": {
"createdAt": "2023-03-13T21:42:35.000Z",
"textMatch": {
"fields": [
"name"
],
"score": "578730123365187697"
}
}
},
{
"document": {
"id": "5",
"brand": "nike",
"name": "running shoes",
"price": 89,
"labels": "shoes",
"popularity": 10,
"review": {
"rating": 8.5,
"author": "olivia"
}
},
"meta": {
"createdAt": "2023-03-13T21:42:35.000Z",
"textMatch": {
"fields": [
"name"
],
"score": "578730123365187697"
}
}
}
],
"facets": {},
"meta": {
"found": 23,
"totalPages": 3,
"page": {
"current": 1,
"size": 10
},
"matchedFields": [
"name"
]
}
}
The hitsPerPage
parameter controls the number of documents to include in a result page. The returned
array of documents is accessible under hits
key along with some search metadata.
console.log(result.hits);
Output
[
{
"document": {
"labels": "clothing",
"popularity": 7,
"id": "6",
"name": "running shorts",
"review": {
"rating": 7.5,
"author": "olivia"
},
"price": 35,
"brand": "adidas"
},
"meta": {
"createdAt": "2023-03-13T21:42:07.000Z",
"textMatch": {
"fields": [
"name"
],
"score": "578730123365187697"
}
}
},
{
"document": {
"name": "running shoes",
"id": "5",
"price": 89,
"popularity": 10,
"review": {
"author": "olivia",
"rating": 8.5
},
"brand": "nike",
"labels": "shoes"
},
"meta": {
"createdAt": "2023-03-13T21:42:07.000Z",
"textMatch": {
"fields": [
"name"
],
"score": "578730123365187697"
}
}
}
]
Additionally, search result contains meta
object having current page and total pages along with
other information.
console.log(result.meta);
Output
{
"found": 23,
"totalPages": 3,
"page": {
"current": 1,
"size": 10
},
"matchedFields": [
"name"
]
}
Infinite scrolling
Infinite scrolling also loads data in pages, it is just that the UX is more fluid.
Instead of using page number, an Iterator object can be obtained from search()
method call and processed iteratively.
const query: SearchQuery<Catalog> = {
q: "running",
hitsPerPage: 10, // Optional. Defaults to 20
};
const resultIterable: SearchIterator<Catalog> = await catalog.search(query);
for await (const result of resultIterable) {
console.log(result);
}
Output
{
"hits": [
{
"document": {
"brand": "adidas",
"price": 35,
"review": {
"author": "olivia",
"rating": 7.5
},
"popularity": 7,
"id": "6",
"labels": "clothing",
"name": "running shorts"
},
"meta": {
"createdAt": "2023-03-13T21:42:35.000Z",
"textMatch": {
"fields": [
"name"
],
"score": "578730123365187697"
}
}
},
{
"document": {
"id": "5",
"brand": "nike",
"name": "running shoes",
"price": 89,
"labels": "shoes",
"popularity": 10,
"review": {
"rating": 8.5,
"author": "olivia"
}
},
"meta": {
"createdAt": "2023-03-13T21:42:35.000Z",
"textMatch": {
"fields": [
"name"
],
"score": "578730123365187697"
}
}
}
],
"facets": {},
"meta": {
"found": 23,
"totalPages": 3,
"page": {
"current": 1,
"size": 10
},
"matchedFields": [
"name"
]
}
}
As you can see, the iterator returns the same SearchResult
object as in previous section
with pagination metadata.