meilisearch / documentation

Meilisearch documentation

Home Page:https://docs.meilisearch.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Guide on pagination

bidoubiwa opened this issue · comments

Pagination best practice

MeiliSearch was not made for pagination. The idea is that you never have to "go to page 2".
In case you still want pagination, let us consider two pagination styles.

1. Infinity scroll, or arrow pagination: recommended

This pagination is recognizable by its absence of a numbered paginated page. It will either have no visual clues and will be done in the background while you scroll down infinitely (i.e.: dev.to) or using arrows that let you navigate to the next page of results.

Pagination

To achieve this pagination you should make searches based on two pieces of information.

  1. How much result do you want to have on a single page (or add on one scroll)
  2. Are there anymore hits after this batch?

Showing a certain amount of hits per batch can be done using the limit. But since you don't want to give the possibility to your user to click on the right arrow if there are no more hits, you need to know where to stop. We suggest to always add + 1 on your limit count, if the number of results MeiliSearch returns is lower than this number, you should inform the user that he arrived at the end the results (by graying out the arrow for example).

For this example, let's say that we want 100 hits per page. Pagination will work like this. We will be using two search parameter to achieve pagination: limit and offset

  • Make a first search on batman with limit: 101 and offset: 0.
    • As we receive 101 results we know that there are more results.
    • We show 100 hits
    • We add a right arrow at the bottom
  • The user scrolls to the end of the page or clicks on the right arrow
  • Trigger another search on batman with limit: 101 and offset: 100
    • As we receive 101 results we know that there are more results.
    • We show 100 hits
    • We add a right arrow at the bottom
  • The user scrolls to the end of the page or clicks on the right arrow
  • Trigger another search on batman with limit: 100 and offset: 200
    • As we receive only 10 results we know that there are NO more possible results.
    • We show 100 hits
    • We grey out a right arrow at the bottom
  • The users can not click on the right arrow

As you may observe, the only parameter changing between each pagination is the offset.

⚠️ ❗️As it is possible to go infinite. We strongly suggest stopping around 1000 hits. Because the bigger the offset the longer it takes MeiliSearch to return the next results. This can be done by putting a limit on the offset value. This performance issue is due to the fact that MeiliSearch needs to sort limit + offset documents before returning the results. Thus instead of stoping the sort at 20 documents, it would have to stop the sort at 220 documents. Which takes more time.

2. Numbered Pagination or Finished Pagination: NOT recommended

this is NOT recommended

Finished pagination is the most known pagination system:
Screenshot 2020-10-20 at 13 50 59

While it has its uses, it is not a style that fits well with MeiliSearch.

No exact knowledge of the nb of hits

Meilisearch search response info nbHits is most of the time an upper bound approximation of the numbers of hits. It is not a reliable information unless the other search response info exhaustiveNbHits is true.

Perfomances issues

Another problem comes from performance issues when paginating to lets say page 200. Since we are using a bucket sort, having the first 20 results is way faster than having the 2000th result.
So giving the possibility to a user to directly jump to page 200 is not a good experience.

Because of this behavior we do not recommend a finished pagination.

How to make a numbered pagination with limited damage

If you want to create finished pagination you need to set a limit of results during your search. MeiliSearch is designed to fastly retrieve the best matching documents (the 20 firsts in a basic search request) but not to return the exact and exhaustive number of documents matching your request, for performance reasons.

What you concretely have to do is to set the limit search parameter to 1000.

MeiliSearch will return a hits array (less or equals to 1000) and the length of thishits array is the number of results -> you can now know the number of pages.
Depending on which page you want to display, you just have to take the piece of hits you need to display the expected results.

Example:
I have a front end application with finished pagination and I want to display 10 results per page.
I search for prince with limit set to 1000.
I get 32 results in hits.

  • I know that I have 22 / 10 = 2,2 => 3 pages to display
  • I will display the hits from 0 to 9 for page 1, 10 to 19 for page 2, and 20 to 22 for the last page.

💡As this technique lowers the performance of the search **we recommend setting the limit of results to a maximum of 1000 **. If you want to improve your performance, you can choose a lower limit. Algolia also sets the limit to 1000 for their pagination by default (see this page of docs).

Todo

Creation of a guide

A (small) guide should be made explaining how to create a pagination system with MeiliSearch.

This guide will be added in the search main concept guide as an example of what can be done using the search route.

The guide should only use curl and MeiliSearch routes. No other external library. Once it is written with cURL our other clients (ruby, js, php,..) will be able to add code-samples to match the cURL examples and thus the guide will be available in all languages.

Like this:
Screenshot 2020-10-19 at 20 57 09

To showcase the pagination, use both limit and offset but without using nbHits as it is not a reliable source of information. It should explain to the user how to paginate with arrows :

example:
Pagination

For example, if every page should have 20 results, using the search routes it should look like this:

  • Search on q = "batman", limit = 20, offset = 0
  • Hit the arrow
  • Search on q = "batman", limit = 20, offset = 20
  • Hit the right arrow
  • Search on q = "batman", limit = 20, offset = 40
    ...

The guide should mention the numbered pagination and explain that it is not recommended.

How to make a numbered pagination with limited damage

If you still want to create a numbered pagination system, we suggest you hard set the limit to 1000 results.
@curquiza could you confirm how to do this pagination system?

If you want to create a finished pagination you indeed need to set a limit of results during your search. MeiliSearch is designed to fastly retrieve the best matching documents (the 20 firsts in a basic search request) but not to return the exact and exhaustif number of documents matching your request, for performance reasons.

What you concretely have to do is to set the limitsearch parameter to 1000.

MeiliSearch will return a hits array (less or equals to 1000) and the length of thishits array is the number of results -> you can now know the number of pages.
Depending on which page you want to display, you just have to take the piece of hits you need to display the expected results.

Example:
I have a front end application with a finished pagination and I want to display 10 results per page.
I search for prince with limit set to 1000.
I get 32 results in hits.

  • I know that I have 22 / 10 = 2,2 => 3 pages to display
  • I will display the hits from 0 to 9 for page 1, 10 to 19 for page 2, and 20 to 22 for the last page.

💡 Algolia sets the limit to 1000 for their pagination by default (see this page of docs), that's why we also recommend using 1000 as a limitation, but if you want to improve your performance, you can choose a lower limit.

commented

@bidoubiwa and @gmourier created a rough draft(private link) of the pagination guide that @guimachiavelli will edit for release alongside v0.28 docs.

Hello!
For those interested, we are working on improving pagination in Meilisearch and we just released a first prototype that makes creating numbered pagination way easier! 🔥
It would be super helpful if you could let us know if this helps with your issue.
To know more about the prototype and how to use it, take a look at the dedicated discussion.