From f3f36ec5c67d42bcb7a7e8377023cdc29f024c3c Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 21 Jun 2022 18:54:42 +0200 Subject: [PATCH 01/39] pagination guide: zeroth draft --- learn/advanced/pagination.md | 125 +++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 learn/advanced/pagination.md diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md new file mode 100644 index 0000000000..ac7cd8adf1 --- /dev/null +++ b/learn/advanced/pagination.md @@ -0,0 +1,125 @@ +# Pagination of search results + +In a perfect world, users would not need to look beyond the first search result to find what they were looking for. In practice, this is difficult to achieve due to design constraints, performance trade-offs, and even inneffective query terms. Because of that, it is usually necessary to create a pagination interface so users can browse through long lists of results. + +In this guide, we will discuss some of Meilisearch's current limitations, how these limitations impact common pagination interface patterns, and the recommended way of handling pagination when using Meilisearch. + +## Choosing the right pagination interface + +For performance reasons, Meilisearch cannot provide you with the exact number of possible results for a query. Instead, you can only know the `estimatedTotalHits` when using our search API. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. + +Additionally, Meilisearch is optimized to return the most relevant results as fast as possible. The negative side of this design decision is that queries might become slower the further away we get from the first results. + +Because you cannot know the number of total hits and slower queries the further we move from the first result, we do not recommend creating interfaces with page selectors that allow users to jump to any arbitrary result page. If this type of interface is crucial for your user's search experience, this document's last section lists a number of tips that might help you work around Meilisearch's current limitations. + +Instead of a full page selector, we recommend creating pagination interfaces centered around previous and next buttons. + +::: note +By default, Meilisearch only returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/settings.md) to know how to change this. +::: + +## Recommended: Previous and next buttons + +Pagination interfaces that rely solely on previous and next buttons are similar to page selectors, but do not allow users to jump to an arbitrary results page. + +![Placeholder image for prev/next interface]() + +Though this approach offers less precision than a full-blown page selector, it does not require knowing the number of total search results. + +### Implementation + +Previous and next buttons can be implemented using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters. + +Paginating requires providing an `offset` that is equal to your `limit` times the page number times: `offset = limit * page number`. + +For example, if you set `limit` to `20` and want the first page of search results, your `offset` must be 0: `offset = 0 * 20`. + +```sh +curl \ + -X POST 'http://localhost:7700/indexes/movies/search' \ + -H 'Content-Type: application/json' \ + --data-binary '{ + "q": "shifu", + "limit": 20, + "offset": 0 + }' +``` + +If you keep the same `limit` and want the third page of results, `offset` must be `40`: `offset = 2 * 20`. + +```sh +curl \ + -X POST 'http://localhost:7700/indexes/movies/search' \ + -H 'Content-Type: application/json' \ + --data-binary '{ + "q": "shifu", + "limit": 20, + "offset": 40 + }' +``` + +As you might have noticed, we start counting page numbers from 0. This means the first page of results is 0, the second page is 1, and so forth. + +It is often helpful to disable navigation buttons when the user cannot move to next or the "previous page. The "previous" button should be disabled whenever your `offset` is 0. + +To disable the "next" button, we recommend setting your `limit` to the number of displayed results plus 1. For example, if you want each page to display 20 search results, set `limit` to 21. If the number of returned items is less than 21, we can safely assume we are in the last page. + +```js +const results = await index.search("x", { limit: 21, offset: 0 }) + +// Previous button +if (offset === 0 ) { + // last page + document.querySelector("#previous_button").disabled +} + +// Next button +if (results.hits.length < limit ) { + // last page + document.querySelector("#next_button").disabled +} +``` + +## Not recommended: Page selection + +As its name states, this type of pagination is made of a numbered list of pages accompanied by next and previous buttons. + +[UI screenshot] + +![](https://vuejsexamples.com/content/images/2018/11/vue-pagination.gif) + +This is a very common type of interface and offers users a significant amount of precision when navigating results. Despite being similar to our recommended pagination solution, the page selector requires knowing the exact number of total matches. This makes it difficult to implement when using Meilisearch. + +### Implementation + +The general implementation of a page selection interface is similar to our recommended solution, using previous and next buttons: you must use the `limit` and `offset` search parameters to set your page size and navigate between search results. + +To create the page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. Meilisearch, however, can only give you an estimate of the total number of search results. + +We recommend two different workarounds to create this kind of pagination interface with Meilisearch. + +#### Set a hard limit of results during your search + +By default, a search request returns 20 search results. You can change this value to a much higher number and treat it as the effective maximum of search results you will show a user. Doing so means the size of your `hits` array is the exact number of search results you have to paginate. + +For example, if you set `limit` to 300, every search request made to Meilisearch returns at most 300 documents. If a query returns a `hits` array with 200 items and you want each page to display 20 results, you can create a page selector with 10 pages. + +This method provides control and reliability. It also prevents users from paginating too far, which avoids performance loss. However, this limits the number of results your users can see. + +::: note +We do not recommend setting high values for `limit` as it can negatively impact performance. +::: + +#### Accept the unreliable number + +You can still use `estimatedTotalHits` to calculate the number of search result pages. This means your page count is likely to change until Meilisearch retrives the last search result. + +For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page in Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 10 total pages. + +This method gives users access to all search results. However, it also results in an interface that might occasionally change in front of the user. + +## Unsatisfied? Let us know + +We are actively working on improving Meilisearch pagination. Is our recommended pagination method not suitable for the application you're developing? Is page selection critical for your website? Please let us know in this GitHub discussion. + +Is creating pagination interfaces in Meilisearch for you this is a huge issue, please provide feedback on [this discussion](https://github.com/meilisearch/product/discussions/483). \ No newline at end of file From 4f76ad2430308914f5f16946b321aea88df5f04d Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 22 Jun 2022 19:50:09 +0200 Subject: [PATCH 02/39] pagination guide: slightly improved draft --- learn/advanced/pagination.md | 90 ++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index ac7cd8adf1..8cef0a8b82 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -4,18 +4,16 @@ In a perfect world, users would not need to look beyond the first search result In this guide, we will discuss some of Meilisearch's current limitations, how these limitations impact common pagination interface patterns, and the recommended way of handling pagination when using Meilisearch. -## Choosing the right pagination interface +## Choosing the right pagination UI -For performance reasons, Meilisearch cannot provide you with the exact number of possible results for a query. Instead, you can only know the `estimatedTotalHits` when using our search API. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. +For performance reasons, Meilisearch cannot provide the exact number of possible results for a query. When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. -Additionally, Meilisearch is optimized to return the most relevant results as fast as possible. The negative side of this design decision is that queries might become slower the further away we get from the first results. +Because of this, we do not recommend creating interfaces with page selectors that allow users to jump to an arbitrary results page. If page selection is crucial to the software you are developing, this document's last section lists a number of tips that might help you work around Meilisearch's current limitations. -Because you cannot know the number of total hits and slower queries the further we move from the first result, we do not recommend creating interfaces with page selectors that allow users to jump to any arbitrary result page. If this type of interface is crucial for your user's search experience, this document's last section lists a number of tips that might help you work around Meilisearch's current limitations. - -Instead of a full page selector, we recommend creating pagination interfaces centered around previous and next buttons. +Instead of a full page selector, [we recommend creating pagination interfaces centered around previous and next buttons](#recommended-previous-and-next-buttons). ::: note -By default, Meilisearch only returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/settings.md) to know how to change this. +By default, Meilisearch returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/settings.md) if you need to change this. ::: ## Recommended: Previous and next buttons @@ -30,53 +28,47 @@ Though this approach offers less precision than a full-blown page selector, it d Previous and next buttons can be implemented using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters. -Paginating requires providing an `offset` that is equal to your `limit` times the page number times: `offset = limit * page number`. +Paginating requires providing an `offset` that is equal to your `limit` times the page number times: `offset = limit * page number`. We recommend starting page count from 0 instead of 1 when calculating offset values. For example, if you set `limit` to `20` and want the first page of search results, your `offset` must be 0: `offset = 0 * 20`. -```sh -curl \ - -X POST 'http://localhost:7700/indexes/movies/search' \ - -H 'Content-Type: application/json' \ - --data-binary '{ - "q": "shifu", - "limit": 20, - "offset": 0 - }' +```js +const results = await index.search("x", { limit: 20, offset: 0 }); ``` If you keep the same `limit` and want the third page of results, `offset` must be `40`: `offset = 2 * 20`. -```sh -curl \ - -X POST 'http://localhost:7700/indexes/movies/search' \ - -H 'Content-Type: application/json' \ - --data-binary '{ - "q": "shifu", - "limit": 20, - "offset": 40 - }' +```js +const results = await index.search("x", { limit: 20, offset: 40 }); ``` -As you might have noticed, we start counting page numbers from 0. This means the first page of results is 0, the second page is 1, and so forth. +Once a query returns less than your configured `limit`, you have reached the last results page. -It is often helpful to disable navigation buttons when the user cannot move to next or the "previous page. The "previous" button should be disabled whenever your `offset` is 0. +It is often helpful to disable navigation buttons when the user cannot move to the "next" or "previous" page. The "previous" button should be disabled whenever your `offset` is 0. -To disable the "next" button, we recommend setting your `limit` to the number of displayed results plus 1. For example, if you want each page to display 20 search results, set `limit` to 21. If the number of returned items is less than 21, we can safely assume we are in the last page. +To disable the "next" button, we recommend setting your query's `limit` to the number of displayed results plus one. The extra result indicates that you have at least one item beyond what you can display in a single results page: ```js const results = await index.search("x", { limit: 21, offset: 0 }) -// Previous button if (offset === 0 ) { - // last page - document.querySelector("#previous_button").disabled + // If offset equals 0, we're on the first results page + // and can disable the "previous" buttons + document.querySelector("#previous_button").disabled = true; +} else { + document.querySelector("#previous_button").disabled = false; } -// Next button -if (results.hits.length < limit ) { - // last page - document.querySelector("#next_button").disabled +if (results.hits.length < 21 ) { + // If Meilisearch returns 20 items or less, + // we don't have any more results to + // and can disable the "next" + document.querySelector("#next_button").disabled = true; +} else { + // If Meilisearch returns exactly 21 results + // and our page can only show 20 items at a time, + // we have at least one more page with 1 result in it + document.querySelector("#next_button").disabled = false; } ``` @@ -84,17 +76,17 @@ if (results.hits.length < limit ) { As its name states, this type of pagination is made of a numbered list of pages accompanied by next and previous buttons. -[UI screenshot] - -![](https://vuejsexamples.com/content/images/2018/11/vue-pagination.gif) +![placeholder page selection UI](https://vuejsexamples.com/content/images/2018/11/vue-pagination.gif) -This is a very common type of interface and offers users a significant amount of precision when navigating results. Despite being similar to our recommended pagination solution, the page selector requires knowing the exact number of total matches. This makes it difficult to implement when using Meilisearch. +This is is a common UI pattern that offers users a significant amount of precision when navigating results. ### Implementation -The general implementation of a page selection interface is similar to our recommended solution, using previous and next buttons: you must use the `limit` and `offset` search parameters to set your page size and navigate between search results. +The general implementation of a page selection interface is similar to our [recommended solution](#recommended-previous-and-next-buttons), but you must also display a page list. -To create the page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. Meilisearch, however, can only give you an estimate of the total number of search results. +To create the page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. + +Since Meilisearch can only give you an estimate of total search results, it can be difficult to implement page selectors when using Meilisearch. We recommend two different workarounds to create this kind of pagination interface with Meilisearch. @@ -104,22 +96,22 @@ By default, a search request returns 20 search results. You can change this valu For example, if you set `limit` to 300, every search request made to Meilisearch returns at most 300 documents. If a query returns a `hits` array with 200 items and you want each page to display 20 results, you can create a page selector with 10 pages. +// perhaps a code sample here? + This method provides control and reliability. It also prevents users from paginating too far, which avoids performance loss. However, this limits the number of results your users can see. ::: note -We do not recommend setting high values for `limit` as it can negatively impact performance. +We do not recommend caution when setting high values for `limit` as it can negatively impact performance. ::: #### Accept the unreliable number -You can still use `estimatedTotalHits` to calculate the number of search result pages. This means your page count is likely to change until Meilisearch retrives the last search result. +You use `estimatedTotalHits` to calculate the number of search result pages. This means your page count is likely to change until Meilisearch retrives the last search result. -For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page in Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 10 total pages. +For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page according to Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 10 total pages. -This method gives users access to all search results. However, it also results in an interface that might occasionally change in front of the user. +This method gives users access to all search results. However, it also results in an interface that might feel unreliable due to constant and unpredictable changes. ## Unsatisfied? Let us know -We are actively working on improving Meilisearch pagination. Is our recommended pagination method not suitable for the application you're developing? Is page selection critical for your website? Please let us know in this GitHub discussion. - -Is creating pagination interfaces in Meilisearch for you this is a huge issue, please provide feedback on [this discussion](https://github.com/meilisearch/product/discussions/483). \ No newline at end of file +Is the current state of pagination in Meilisearch negatively impacting you? Please share your thoughts with us in this [GitHub discussion](https://github.com/meilisearch/product/discussions/483). We are actively working on improving this aspect of Meilisearch and your input is greatly appreciated. From 693de12bb7704b9773e910430bd29b39ffd29fb5 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Thu, 23 Jun 2022 18:13:55 +0200 Subject: [PATCH 03/39] pagination settings: API reference scaffolding --- reference/api/pagination.md | 90 +++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 reference/api/pagination.md diff --git a/reference/api/pagination.md b/reference/api/pagination.md new file mode 100644 index 0000000000..89fc2b8695 --- /dev/null +++ b/reference/api/pagination.md @@ -0,0 +1,90 @@ +# Pagination + +_Child route of the [settings route](/reference/api/settings.md)._ + +This route allows you to configure the pagination settings for an index. + +Pagination settings can also be updated directly through the [global settings route](/reference/api/settings.md#update-settings) along with the other settings. + +To learn more about paginating search results with Meilisearch,, refer to our [dedicated guide](/learn/advanced/pagination.md). + +::: warning +Updating the settings means overwriting the default settings of Meilisearch. You can reset to default values using the `DELETE` routes. +::: + +## Get pagination settings + + + +Get the pagination settings of an index. The index [`uid`](/learn/core_concepts/indexes.md#index-uid) is required. + +### Example + + + +#### Response: `200 OK` + +```json +{ + +} +``` + +### Returned fields + +#### `field_name` + +[field explanation] + +## Update pagination settings + + + +Partially update the pagination settings for an index. The index [`uid`](/learn/core_concepts/indexes.md#index-uid) is required. + +### Body + +#### `field_name` + +[field explanation] + +#### Example + + + +#### Response: `200 OK` + +```json +{ + "uid": 1, + "indexUid": "books", + "status": "enqueued", + "type": "settingsUpdate", + "enqueuedAt": "2022-04-14T20:56:44.991039Z" +} +``` + +You can use the returned `uid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). + +## Reset pagination settings + +Reset an index's pagination settings to their default value. The index [`uid`](/learn/core_concepts/indexes.md#index-uid) is required. + +#### Example + + + +#### Response: `200 OK` + +```json +{ + "uid": 1, + "indexUid": "books", + "status": "enqueued", + "type": "settingsUpdate", + "enqueuedAt": "2022-04-14T20:53:32.863107Z" +} +``` + +You can use the returned `uid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). + From 6d624d5e7dddc510c0414019c2232580537b35a5 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 27 Jun 2022 16:30:05 +0200 Subject: [PATCH 04/39] pagination: new API reference page --- reference/api/pagination.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/reference/api/pagination.md b/reference/api/pagination.md index 89fc2b8695..c32f29d5cc 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -6,7 +6,8 @@ This route allows you to configure the pagination settings for an index. Pagination settings can also be updated directly through the [global settings route](/reference/api/settings.md#update-settings) along with the other settings. -To learn more about paginating search results with Meilisearch,, refer to our [dedicated guide](/learn/advanced/pagination.md). + +To learn more about paginating search results with Meilisearch, refer to our [dedicated guide](/learn/advanced/pagination.md). ::: warning Updating the settings means overwriting the default settings of Meilisearch. You can reset to default values using the `DELETE` routes. @@ -26,27 +27,29 @@ Get the pagination settings of an index. The index [`uid`](/learn/core_concepts/ ```json { - + "maxTotalHits": 1000 } ``` ### Returned fields -#### `field_name` +#### `maxTotalHits` -[field explanation] +The maximum number of results Meilisearch can return. ## Update pagination settings - + Partially update the pagination settings for an index. The index [`uid`](/learn/core_concepts/indexes.md#index-uid) is required. ### Body -#### `field_name` +#### `maxTotalHits` -[field explanation] +An integer indicating the maximum number of search results Meilisearch can return. + +`maxTotalHits` takes priority over search parameters such as `limit` and `offset`. For example, if you set `maxTotalHits` to 100, you will not be able to access search results beyond 100 no matter the value configured for `offset`. #### Example @@ -87,4 +90,3 @@ Reset an index's pagination settings to their default value. The index [`uid`](/ ``` You can use the returned `uid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). - From b2c4659e87f25a344cfeecc3632ca4d9986f0414 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 27 Jun 2022 16:30:31 +0200 Subject: [PATCH 05/39] pagination: new API code samples --- .code-samples.meilisearch.yaml | 13 +++++++++++++ .vuepress/public/sample-template.yaml | 3 +++ 2 files changed, 16 insertions(+) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 047cb60b9f..5bc68e942c 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -958,3 +958,16 @@ getting_started_typo_tolerance: |- --data-binary '{ "minWordSizeForTypos": { "oneTypo": 4 } }' +get_pagination_settings_1: |- + curl \ + -X GET 'http://localhost:7700/indexes/books/settings/pagination' +update_pagination_settings_1: |- + curl \ + -X POST 'http://localhost:7700/indexes/books/settings/pagination' \ + -H 'Content-Type: application/json' \ + --data-binary '{ + "maxTotalHits": 100 + }' +reset_typo_tolerance_1: |- + curl \ + -X DELETE 'http://localhost:7700/indexes/books/settings/pagination' \ No newline at end of file diff --git a/.vuepress/public/sample-template.yaml b/.vuepress/public/sample-template.yaml index 8b52eec657..544cf8048b 100644 --- a/.vuepress/public/sample-template.yaml +++ b/.vuepress/public/sample-template.yaml @@ -146,3 +146,6 @@ updating_guide_retrieve_documents_old: |- updating_guide_update_settings_old: |- updating_guide_add_documents_old: |- getting_started_typo_tolerance: |- +get_pagination_settings_1: |- +update_pagination_settings_1: |- +reset_typo_tolerance_1: |- \ No newline at end of file From dcd96bb37cd0f28dbee011ce2f1b24df04d589cf Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 27 Jun 2022 16:44:59 +0200 Subject: [PATCH 06/39] pagination: fix code sample key --- .code-samples.meilisearch.yaml | 2 +- .vuepress/public/sample-template.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 5bc68e942c..fd60dc3c2f 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -968,6 +968,6 @@ update_pagination_settings_1: |- --data-binary '{ "maxTotalHits": 100 }' -reset_typo_tolerance_1: |- +reset_pagination_settings_1: |- curl \ -X DELETE 'http://localhost:7700/indexes/books/settings/pagination' \ No newline at end of file diff --git a/.vuepress/public/sample-template.yaml b/.vuepress/public/sample-template.yaml index 544cf8048b..e9e857c693 100644 --- a/.vuepress/public/sample-template.yaml +++ b/.vuepress/public/sample-template.yaml @@ -148,4 +148,4 @@ updating_guide_add_documents_old: |- getting_started_typo_tolerance: |- get_pagination_settings_1: |- update_pagination_settings_1: |- -reset_typo_tolerance_1: |- \ No newline at end of file +reset_pagination_settings_1: |- From 6ce706895cd748c6ae67e50e2434c7165846c2c9 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 27 Jun 2022 16:50:50 +0200 Subject: [PATCH 07/39] pagination: add API reference to menu --- .vuepress/config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.vuepress/config.js b/.vuepress/config.js index 395bd548d8..c88b11d36c 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -324,6 +324,7 @@ module.exports = { '/reference/api/displayed_attributes', '/reference/api/distinct_attribute', '/reference/api/filterable_attributes', + '/reference/api/pagination', '/reference/api/ranking_rules', '/reference/api/searchable_attributes', '/reference/api/sortable_attributes', From 88e9fc5ea8b1a98093880053d7f97b6c1f41ff55 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 27 Jun 2022 17:29:25 +0200 Subject: [PATCH 08/39] pagination: update global settings reference --- .code-samples.meilisearch.yaml | 3 ++ reference/api/pagination.md | 8 ++-- reference/api/settings.md | 83 ++++++++++++++++++---------------- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index fd60dc3c2f..7f1a2450b1 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -183,6 +183,9 @@ update_settings_1: |- "twoTypos": 10 }, "disableOnAttributes": ["title"] + }, + "pagination": { + "maxTotalHits": 5000 } }' reset_settings_1: |- diff --git a/reference/api/pagination.md b/reference/api/pagination.md index c32f29d5cc..e4e066488a 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -6,7 +6,6 @@ This route allows you to configure the pagination settings for an index. Pagination settings can also be updated directly through the [global settings route](/reference/api/settings.md#update-settings) along with the other settings. - To learn more about paginating search results with Meilisearch, refer to our [dedicated guide](/learn/advanced/pagination.md). ::: warning @@ -47,9 +46,12 @@ Partially update the pagination settings for an index. The index [`uid`](/learn/ #### `maxTotalHits` -An integer indicating the maximum number of search results Meilisearch can return. +**Type:** integer +**Default value:** `1000` + +An integer indicating the maximum number of search results Meilisearch can return. `maxTotalHits` takes priority over search parameters such as `limit` and `offset`. -`maxTotalHits` takes priority over search parameters such as `limit` and `offset`. For example, if you set `maxTotalHits` to 100, you will not be able to access search results beyond 100 no matter the value configured for `offset`. +For example, if you set `maxTotalHits` to 100, you will not be able to access search results beyond 100 no matter the value configured for `offset`. #### Example diff --git a/reference/api/settings.md b/reference/api/settings.md index 2d22e9b45b..c474bf25d7 100644 --- a/reference/api/settings.md +++ b/reference/api/settings.md @@ -7,6 +7,7 @@ These are the reference pages for the child routes: - [Displayed attributes](/reference/api/displayed_attributes.md) - [Distinct attribute](/reference/api/distinct_attribute.md) - [Filterable attributes](/reference/api/filterable_attributes.md) +- [Pagination](/reference/api/pagination.md) - [Ranking rules](/reference/api/ranking_rules.md) - [Searchable attributes](/reference/api/searchable_attributes.md) - [Sortable attributes](/reference/api/sortable_attributes.md) @@ -30,17 +31,18 @@ Get the settings of an index. The index [`uid`](/learn/core_concepts/indexes.md# ### Response body -| Variable | Type | Description | Default value | -| ------------------------ | --------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -| **displayedAttributes** | [Strings] | Fields displayed in the returned documents | `["*"]` (all attributes) | -| **distinctAttribute** | String | Search returns documents with distinct (different) values of the given field | `null` | -| **filterableAttributes** | [Strings] | Attributes to use as [filters and facets](/learn/advanced/filtering_and_faceted_search.md) | `[]` | -| **rankingRules** | [Strings] | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | -| **searchableAttributes** | [Strings] | Fields in which to search for matching query words sorted by order of importance | `["*"]` (all attributes) | -| **sortableAttributes** | [Strings] | Attributes to use when [sorting](/learn/advanced/sorting.md) search results | `[]` | -| **stopWords** | [Strings] | List of words ignored by Meilisearch when present in search queries | `[]` | -| **synonyms** | Object | List of associated words treated similarly | `{}` | -| **typoTolerance** | Object | Typo tolerance settings | `{}` | +| Variable | Type | Description | Default value | +| ------------------------ | --------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | +| **displayedAttributes** | [Strings] | Fields displayed in the returned documents | `["*"]` (all attributes) | +| **distinctAttribute** | String | Search returns documents with distinct (different) values of the given field | `null` | +| **filterableAttributes** | [Strings] | Attributes to use as [filters and facets](/learn/advanced/filtering_and_faceted_search.md) | `[]` | +| **pagination** | Object | Pagination settings | `{}` | +| **rankingRules** | [Strings] | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | +| **searchableAttributes** | [Strings] | Fields in which to search for matching query words sorted by order of importance | `["*"]` (all attributes) | +| **sortableAttributes** | [Strings] | Attributes to use when [sorting](/learn/advanced/sorting.md) search results | `[]` | +| **stopWords** | [Strings] | List of words ignored by Meilisearch when present in search queries | `[]` | +| **synonyms** | Object | List of associated words treated similarly | `{}` | +| **typoTolerance** | Object | Typo tolerance settings | `{}` | [Learn more about the settings in this guide.](/learn/configuration/settings.md) @@ -92,12 +94,15 @@ List the settings. "typoTolerance": { "enabled": true, "minWordSizeForTypos": { - "oneTypo": 5, - "twoTypos": 10 + "oneTypo": 5, + "twoTypos": 10 }, - "disableOnWords": [], - "disableOnAttributes": [] - } + "disableOnWords": [], + "disableOnAttributes": [] + }, + "pagination": { + "maxTotalHits": 1000 + } } ``` @@ -117,17 +122,18 @@ If the provided index does not exist, it will be created. ### Body -| Variable | Type | Description | Default value | -| ------------------------ | --------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -| **displayedAttributes** | [Strings] | Fields displayed in the returned documents | `["*"]` (all attributes) | -| **distinctAttribute** | String | Search returns documents with distinct (different) values of the given field | `null` | -| **filterableAttributes** | [Strings] | Attributes to use as [filters and facets](/learn/advanced/filtering_and_faceted_search.md) | `[]` | -| **rankingRules** | [Strings] | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | -| **searchableAttributes** | [Strings] | Fields in which to search for matching query words sorted by order of importance | `["*"]` (all attributes) | -| **sortableAttributes** | [Strings] | Attributes to use when [sorting](/learn/advanced/sorting.md) search results | `[]` | -| **stopWords** | [Strings] | List of words ignored by Meilisearch when present in search queries | `[]` | -| **synonyms** | Object | List of associated words treated similarly | `{}` | -| **typoTolerance** | Object | Typo tolerance settings | `{}` | +| Variable | Type | Description | Default value | +| ------------------------ | --------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | +| **displayedAttributes** | [Strings] | Fields displayed in the returned documents | `["*"]` (all attributes) | +| **distinctAttribute** | String | Search returns documents with distinct (different) values of the given field | `null` | +| **filterableAttributes** | [Strings] | Attributes to use as [filters and facets](/learn/advanced/filtering_and_faceted_search.md) | `[]` | +| **pagination** | Object | Pagination settings | `{}` | +| **rankingRules** | [Strings] | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | +| **searchableAttributes** | [Strings] | Fields in which to search for matching query words sorted by order of importance | `["*"]` (all attributes) | +| **sortableAttributes** | [Strings] | Attributes to use when [sorting](/learn/advanced/sorting.md) search results | `[]` | +| **stopWords** | [Strings] | List of words ignored by Meilisearch when present in search queries | `[]` | +| **synonyms** | Object | List of associated words treated similarly | `{}` | +| **typoTolerance** | Object | Typo tolerance settings | `{}` | ### Example @@ -155,17 +161,18 @@ Reset the settings of an index. The index [`uid`](/learn/core_concepts/indexes.m All settings will be reset to their default value. -| Variable | Type | Description | Default value | -| ------------------------ | --------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -| **displayedAttributes** | [Strings] | Fields displayed in the returned documents | `["*"]` (all attributes) | -| **distinctAttribute** | String | Search returns documents with distinct (different) values of the given field | `null` | -| **filterableAttributes** | [Strings] | Attributes to use as [filters and facets](/learn/advanced/filtering_and_faceted_search.md) | `[]` | -| **rankingRules** | [Strings] | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | -| **searchableAttributes** | [Strings] | Fields in which to search for matching query words sorted by order of importance | `["*"]` (all attributes) | -| **sortableAttributes** | [Strings] | Attributes to use when [sorting](/learn/advanced/sorting.md) search results | `[]` | -| **stopWords** | [Strings] | List of words ignored by Meilisearch when present in search queries | `[]` | -| **synonyms** | Object | List of associated words treated similarly | `{}` | -| **typoTolerance** | Object | Typo tolerance settings | `{}` | +| Variable | Type | Description | Default value | +| ------------------------ | --------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | +| **displayedAttributes** | [Strings] | Fields displayed in the returned documents | `["*"]` (all attributes) | +| **distinctAttribute** | String | Search returns documents with distinct (different) values of the given field | `null` | +| **filterableAttributes** | [Strings] | Attributes to use as [filters and facets](/learn/advanced/filtering_and_faceted_search.md) | `[]` | +| **pagination** | Object | Pagination settings | `{}` | +| **rankingRules** | [Strings] | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | +| **searchableAttributes** | [Strings] | Fields in which to search for matching query words sorted by order of importance | `["*"]` (all attributes) | +| **sortableAttributes** | [Strings] | Attributes to use when [sorting](/learn/advanced/sorting.md) search results | `[]` | +| **stopWords** | [Strings] | List of words ignored by Meilisearch when present in search queries | `[]` | +| **synonyms** | Object | List of associated words treated similarly | `{}` | +| **typoTolerance** | Object | Typo tolerance settings | `{}` | [Learn more about the settings](/learn/configuration/settings.md). #### Example From 9cffdb11e6dfb9832de0445d47671b3a72d06231 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 28 Jun 2022 12:51:12 +0200 Subject: [PATCH 09/39] pagination: add guide placeholder --- learn/advanced/pagination.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 learn/advanced/pagination.md diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md new file mode 100644 index 0000000000..e69de29bb2 From aec2da0bd3ff472abc2772fa2f92871e5feb2ca8 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 28 Jun 2022 13:38:02 +0200 Subject: [PATCH 10/39] pagination: update known limitations --- learn/advanced/known_limitations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/learn/advanced/known_limitations.md b/learn/advanced/known_limitations.md index e3743423b2..f76033d033 100644 --- a/learn/advanced/known_limitations.md +++ b/learn/advanced/known_limitations.md @@ -97,6 +97,6 @@ user = 1 OR user = 2 […] OR user = 1500 OR user = 1501 […] OR user = 2000 OR ## Maximum number of results per search -**Limitation:** Meilisearch returns up to 1000 documents per search. +**Limitation:** By default, Meilisearch returns up to 1000 documents per search. -**Explanation:** This non-customizable limit ensures the database is protected from malicious scraping. This limit only applies to the [search route](/reference/api/search.md). If you want to get all documents in your database, you can use the [get documents endpoint](/reference/api/documents.md#get-documents) instead. +**Explanation:** Meilisearch limits the maximum amount of returned search results to protect your database from malicious scraping. You may change this by using the `maxTotalHits` property of the [pagination index settings](/reference/api/pagination.md#maxtotalhits-1). `maxTotalHits` only applies to the [search route](/reference/api/search.md) and has no effect on the [get documents endpoint](/reference/api/documents.md#get-documents). From b0572e00bf229dd3ca4d3c08896daec2bc0ef2f7 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 28 Jun 2022 13:57:16 +0200 Subject: [PATCH 11/39] pagination: update HTTP method --- .code-samples.meilisearch.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 7f1a2450b1..509a6303bb 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -966,11 +966,11 @@ get_pagination_settings_1: |- -X GET 'http://localhost:7700/indexes/books/settings/pagination' update_pagination_settings_1: |- curl \ - -X POST 'http://localhost:7700/indexes/books/settings/pagination' \ + -X PATCH 'http://localhost:7700/indexes/books/settings/pagination' \ -H 'Content-Type: application/json' \ --data-binary '{ "maxTotalHits": 100 }' reset_pagination_settings_1: |- curl \ - -X DELETE 'http://localhost:7700/indexes/books/settings/pagination' \ No newline at end of file + -X DELETE 'http://localhost:7700/indexes/books/settings/pagination' From 9250fc03452414d8a562b546c16ccb744cf81d26 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 28 Jun 2022 16:47:30 +0200 Subject: [PATCH 12/39] Apply suggestions from code review Co-authored-by: Tommy <68053732+dichotommy@users.noreply.github.com> --- learn/advanced/pagination.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index 8cef0a8b82..d2479e081b 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -1,16 +1,16 @@ # Pagination of search results -In a perfect world, users would not need to look beyond the first search result to find what they were looking for. In practice, this is difficult to achieve due to design constraints, performance trade-offs, and even inneffective query terms. Because of that, it is usually necessary to create a pagination interface so users can browse through long lists of results. +In a perfect world, users would not need to look beyond the first search result to find what they were looking for. In practice, however, it is usually necessary to create some kind of pagination interface so users can browse through long lists of results. In this guide, we will discuss some of Meilisearch's current limitations, how these limitations impact common pagination interface patterns, and the recommended way of handling pagination when using Meilisearch. ## Choosing the right pagination UI -For performance reasons, Meilisearch cannot provide the exact number of possible results for a query. When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. +For performance reasons, Meilisearch cannot provide the exact number of results for a query. When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. -Because of this, we do not recommend creating interfaces with page selectors that allow users to jump to an arbitrary results page. If page selection is crucial to the software you are developing, this document's last section lists a number of tips that might help you work around Meilisearch's current limitations. +Because of this, we do not recommend creating interfaces with page selectors that allow users to jump to a specific page. If page selection is crucial to the software you are developing, see the [last section of this page](#not-recommended-page-selection) for tips that might help you work around Meilisearch's current limitations. -Instead of a full page selector, [we recommend creating pagination interfaces centered around previous and next buttons](#recommended-previous-and-next-buttons). +We recommend creating pagination interfaces centered around previous and next buttons. ::: note By default, Meilisearch returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/settings.md) if you need to change this. @@ -18,11 +18,11 @@ By default, Meilisearch returns a maximum of 1000 search results. Consult our [i ## Recommended: Previous and next buttons -Pagination interfaces that rely solely on previous and next buttons are similar to page selectors, but do not allow users to jump to an arbitrary results page. +Using previous and next buttons for pagination means that users can easily page through results, but don't have the ability to jump to an arbitrary results page. ![Placeholder image for prev/next interface]() -Though this approach offers less precision than a full-blown page selector, it does not require knowing the number of total search results. +Though this approach offers less precision than a full-blown page selector, it does not require knowing the precise number of search results. This makes it a good fit for Meilisearch's current capabilities. ### Implementation @@ -36,17 +36,17 @@ For example, if you set `limit` to `20` and want the first page of search result const results = await index.search("x", { limit: 20, offset: 0 }); ``` -If you keep the same `limit` and want the third page of results, `offset` must be `40`: `offset = 2 * 20`. +If you want the third page of results, `offset` must be `40`: `offset = 2 * 20`. ```js const results = await index.search("x", { limit: 20, offset: 40 }); ``` -Once a query returns less than your configured `limit`, you have reached the last results page. +Once a query returns fewer `hits` than your configured `limit`, you have reached the last results page. It is often helpful to disable navigation buttons when the user cannot move to the "next" or "previous" page. The "previous" button should be disabled whenever your `offset` is 0. -To disable the "next" button, we recommend setting your query's `limit` to the number of displayed results plus one. The extra result indicates that you have at least one item beyond what you can display in a single results page: +To know when to disable the "next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user; its purpose is to indicate that there is at least one more document to display on the next page: ```js const results = await index.search("x", { limit: 21, offset: 0 }) @@ -61,8 +61,8 @@ if (offset === 0 ) { if (results.hits.length < 21 ) { // If Meilisearch returns 20 items or less, - // we don't have any more results to - // and can disable the "next" + // we don't have any more results to display + // and can disable the "next" button document.querySelector("#next_button").disabled = true; } else { // If Meilisearch returns exactly 21 results @@ -74,15 +74,15 @@ if (results.hits.length < 21 ) { ## Not recommended: Page selection -As its name states, this type of pagination is made of a numbered list of pages accompanied by next and previous buttons. +This type of pagination consists of a numbered list of pages accompanied by next and previous buttons. ![placeholder page selection UI](https://vuejsexamples.com/content/images/2018/11/vue-pagination.gif) -This is is a common UI pattern that offers users a significant amount of precision when navigating results. +This is a common UI pattern that offers users a significant amount of precision when navigating results. However, due to Meilisearch's [limitations](#choosing-the-right-pagination-ui), it is not a good fit for pagination with Meilisearch. ### Implementation -The general implementation of a page selection interface is similar to our [recommended solution](#recommended-previous-and-next-buttons), but you must also display a page list. +The general implementation of a page selection interface is similar to our [recommended solution](#recommended-previous-and-next-buttons), but also includes a numbered page list. To create the page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. @@ -90,7 +90,7 @@ Since Meilisearch can only give you an estimate of total search results, it can We recommend two different workarounds to create this kind of pagination interface with Meilisearch. -#### Set a hard limit of results during your search +#### Set a hard limit on search results By default, a search request returns 20 search results. You can change this value to a much higher number and treat it as the effective maximum of search results you will show a user. Doing so means the size of your `hits` array is the exact number of search results you have to paginate. @@ -101,7 +101,7 @@ For example, if you set `limit` to 300, every search request made to Meilisearch This method provides control and reliability. It also prevents users from paginating too far, which avoids performance loss. However, this limits the number of results your users can see. ::: note -We do not recommend caution when setting high values for `limit` as it can negatively impact performance. +We recommend caution when setting high values for `limit` as it can negatively impact performance. ::: #### Accept the unreliable number From a99a123bcb1128cb3fdb8bea2dea3b80fa86beab Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 28 Jun 2022 16:48:10 +0200 Subject: [PATCH 13/39] Apply suggestions from code review Co-authored-by: Tommy <68053732+dichotommy@users.noreply.github.com> --- learn/advanced/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index d2479e081b..fa35fab70a 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -106,7 +106,7 @@ We recommend caution when setting high values for `limit` as it can negatively i #### Accept the unreliable number -You use `estimatedTotalHits` to calculate the number of search result pages. This means your page count is likely to change until Meilisearch retrives the last search result. +In this pagination method, use `estimatedTotalHits` to calculate the number of search result pages. This means your number of results and page count are likely to change until Meilisearch retrieves the last search result. For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page according to Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 10 total pages. From d63d87d3d4e30a57bf5d50bd94be686ed97f0dcd Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 28 Jun 2022 17:11:44 +0200 Subject: [PATCH 14/39] Apply suggestions from code review Co-authored-by: Tommy <68053732+dichotommy@users.noreply.github.com> --- learn/advanced/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index fa35fab70a..0c6c78dbb8 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -28,7 +28,7 @@ Though this approach offers less precision than a full-blown page selector, it d Previous and next buttons can be implemented using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters. -Paginating requires providing an `offset` that is equal to your `limit` times the page number times: `offset = limit * page number`. We recommend starting page count from 0 instead of 1 when calculating offset values. +Paginating requires providing an `offset` that is equal to your `limit` times the page number: `offset = limit * page number`. We recommend starting page count from 0 instead of 1 when calculating offset values. For example, if you set `limit` to `20` and want the first page of search results, your `offset` must be 0: `offset = 0 * 20`. From 9d070d1ae09012b2e435c7505e722bd8c3b9de18 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 29 Jun 2022 12:45:36 +0200 Subject: [PATCH 15/39] pagination guide: first draft --- learn/advanced/pagination.md | 71 +++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index 0c6c78dbb8..f2bff6a617 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -1,20 +1,18 @@ # Pagination of search results -In a perfect world, users would not need to look beyond the first search result to find what they were looking for. In practice, however, it is usually necessary to create some kind of pagination interface so users can browse through long lists of results. +In a perfect world, users would not need to look beyond the first search result to find what they were looking for. In practice, however, it is usually necessary to create some kind of pagination interface to browse through long lists of results. In this guide, we will discuss some of Meilisearch's current limitations, how these limitations impact common pagination interface patterns, and the recommended way of handling pagination when using Meilisearch. ## Choosing the right pagination UI -For performance reasons, Meilisearch cannot provide the exact number of results for a query. When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. +There are quite a few pagination interfaces you might want to implement in your application. Many common UI patterns have a page selector allowing users to jump to any search results page. To create a page selector, you must know the exact number of total results so you can calculate the precise number of results pages. -Because of this, we do not recommend creating interfaces with page selectors that allow users to jump to a specific page. If page selection is crucial to the software you are developing, see the [last section of this page](#not-recommended-page-selection) for tips that might help you work around Meilisearch's current limitations. +For performance reasons, however, Meilisearch cannot provide the exact number of results for a query. Instead, When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. -We recommend creating pagination interfaces centered around previous and next buttons. +Because of this, we do not recommend creating interfaces with page selectors. If page selection is crucial to the software you are developing, see the [last section of this page](#not-recommended-page-selection) for tips that might help you work around Meilisearch's current limitations. -::: note -By default, Meilisearch returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/settings.md) if you need to change this. -::: +We recommend creating pagination interfaces centered around [previous and next buttons](#recommended-previous-and-next-buttons). ## Recommended: Previous and next buttons @@ -26,48 +24,63 @@ Though this approach offers less precision than a full-blown page selector, it d ### Implementation +#### `limit` and `offset` + Previous and next buttons can be implemented using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters. -Paginating requires providing an `offset` that is equal to your `limit` times the page number: `offset = limit * page number`. We recommend starting page count from 0 instead of 1 when calculating offset values. +`limit` sets the size of page. If you set `limit` to 20, Meilisearch's response will contain a maximum of 20 search results. `offset` skips a number of search results. If you set `offset` to 40, Meilisearch's response will skip the first 40 search results. + +You can use both parameters together to effectively create search pages. + +#### Search pages and calculating `offset` -For example, if you set `limit` to `20` and want the first page of search results, your `offset` must be 0: `offset = 0 * 20`. +If you set `limit` to 20 and `offset` to 0, you get the first twenty results. We can call this our first page. ```js const results = await index.search("x", { limit: 20, offset: 0 }); ``` -If you want the third page of results, `offset` must be `40`: `offset = 2 * 20`. +Likewise, if you set `limit` to 20 and `offset` to 40, you skip the first 40 search results and get documents ranked from 41 through 60. We can call this the third results page. ```js const results = await index.search("x", { limit: 20, offset: 40 }); ``` +Use this formula to quickly calculate a page's offset value: `offset = limit * (page number - 1)`. + Once a query returns fewer `hits` than your configured `limit`, you have reached the last results page. -It is often helpful to disable navigation buttons when the user cannot move to the "next" or "previous" page. The "previous" button should be disabled whenever your `offset` is 0. +#### Disabling navigation buttons for first and last pages + +It is often helpful to disable navigation buttons when the user cannot move to the "next" or "previous" page. + +The "previous" button should be disabled whenever your `offset` is 0, as this indicates your user is on the first results page. -To know when to disable the "next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user; its purpose is to indicate that there is at least one more document to display on the next page: +To know when to disable the "next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user. Its purpose is to indicate that there is at least one more document to display on the next page: ```js const results = await index.search("x", { limit: 21, offset: 0 }) +// If offset equals 0, we're on the first results page if (offset === 0 ) { - // If offset equals 0, we're on the first results page - // and can disable the "previous" buttons document.querySelector("#previous_button").disabled = true; -} else { +} + +// If offset is bigger than 0, we're not on the first results page +if (offset > 0 ) { document.querySelector("#previous_button").disabled = false; } +// If Meilisearch returns 20 items or less, +// we are on the last page if (results.hits.length < 21 ) { - // If Meilisearch returns 20 items or less, - // we don't have any more results to display - // and can disable the "next" button document.querySelector("#next_button").disabled = true; -} else { - // If Meilisearch returns exactly 21 results - // and our page can only show 20 items at a time, - // we have at least one more page with 1 result in it +} + +// If Meilisearch returns exactly 21 results +// and our page can only show 20 items at a time, +// we have at least one more page with one result in it +if (results.hits.length === 21 ) { document.querySelector("#next_button").disabled = false; } ``` @@ -84,13 +97,13 @@ This is a common UI pattern that offers users a significant amount of precision The general implementation of a page selection interface is similar to our [recommended solution](#recommended-previous-and-next-buttons), but also includes a numbered page list. -To create the page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. +To create a numbered page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. -Since Meilisearch can only give you an estimate of total search results, it can be difficult to implement page selectors when using Meilisearch. +Since Meilisearch can only give you an estimate of total search results, it is difficult to implement page selectors when using Meilisearch. We recommend two different workarounds to create this kind of pagination interface with Meilisearch. -#### Set a hard limit on search results +#### Use `limit` to set a maximum number of search results By default, a search request returns 20 search results. You can change this value to a much higher number and treat it as the effective maximum of search results you will show a user. Doing so means the size of your `hits` array is the exact number of search results you have to paginate. @@ -98,15 +111,15 @@ For example, if you set `limit` to 300, every search request made to Meilisearch // perhaps a code sample here? -This method provides control and reliability. It also prevents users from paginating too far, which avoids performance loss. However, this limits the number of results your users can see. +This method provides control and reliability. It also prevents users from paginating too far, which might result in performance gains. However, it limits the number of results your users can see. Additionally, we recommend caution when setting high values for `limit` as it can negatively impact performance. ::: note -We recommend caution when setting high values for `limit` as it can negatively impact performance. +By default, Meilisearch returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/pagination.md#maxtotalhits-1) if you need to change this. ::: -#### Accept the unreliable number +#### Use `estimatedTotalHits` -In this pagination method, use `estimatedTotalHits` to calculate the number of search result pages. This means your number of results and page count are likely to change until Meilisearch retrieves the last search result. +Though we advise against it, you can use `estimatedTotalHits` to calculate the number of search result pages. This means your number of results and page count are likely to change until Meilisearch retrieves the last search result. For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page according to Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 10 total pages. From 1e88a917941a93a399874f86bd1a4927301c0caf Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 29 Jun 2022 15:56:18 +0200 Subject: [PATCH 16/39] Apply suggestions from code review Co-authored-by: Maryam <90181761+maryamsulemani97@users.noreply.github.com> --- reference/api/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/api/pagination.md b/reference/api/pagination.md index e4e066488a..1c0cf7aea6 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -83,7 +83,7 @@ Reset an index's pagination settings to their default value. The index [`uid`](/ ```json { - "uid": 1, + "taskUid": 1, "indexUid": "books", "status": "enqueued", "type": "settingsUpdate", From df1d260d1450dfbe284297af0d53451179699026 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 29 Jun 2022 16:05:53 +0200 Subject: [PATCH 17/39] pagination settings: address review feedback --- reference/api/pagination.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reference/api/pagination.md b/reference/api/pagination.md index 1c0cf7aea6..48cacdc784 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -53,6 +53,10 @@ An integer indicating the maximum number of search results Meilisearch can retur For example, if you set `maxTotalHits` to 100, you will not be able to access search results beyond 100 no matter the value configured for `offset`. +::: note +Setting `maxTotalHits` to a high value might negatively impact performance. +::: + #### Example @@ -61,7 +65,7 @@ For example, if you set `maxTotalHits` to 100, you will not be able to access se ```json { - "uid": 1, + "taskUid": 1, "indexUid": "books", "status": "enqueued", "type": "settingsUpdate", From f5653cf238eaeb5b00e19d6857925e7825d7e146 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 29 Jun 2022 16:17:24 +0200 Subject: [PATCH 18/39] pagination settings: improve note on side effects of high `maxTotalHits` --- reference/api/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/api/pagination.md b/reference/api/pagination.md index 48cacdc784..0e1debe2ce 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -54,7 +54,7 @@ An integer indicating the maximum number of search results Meilisearch can retur For example, if you set `maxTotalHits` to 100, you will not be able to access search results beyond 100 no matter the value configured for `offset`. ::: note -Setting `maxTotalHits` to a high value might negatively impact performance. +Setting `maxTotalHits` to a high value might negatively impact performance and expose instance data to malicious scraping. ::: #### Example From 2e8e715df688e99683c9df1cfb36bce28ad43742 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 29 Jun 2022 16:21:57 +0200 Subject: [PATCH 19/39] pagination settings: fix broken hash --- learn/advanced/known_limitations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/advanced/known_limitations.md b/learn/advanced/known_limitations.md index f76033d033..a383d0420c 100644 --- a/learn/advanced/known_limitations.md +++ b/learn/advanced/known_limitations.md @@ -99,4 +99,4 @@ user = 1 OR user = 2 […] OR user = 1500 OR user = 1501 […] OR user = 2000 OR **Limitation:** By default, Meilisearch returns up to 1000 documents per search. -**Explanation:** Meilisearch limits the maximum amount of returned search results to protect your database from malicious scraping. You may change this by using the `maxTotalHits` property of the [pagination index settings](/reference/api/pagination.md#maxtotalhits-1). `maxTotalHits` only applies to the [search route](/reference/api/search.md) and has no effect on the [get documents endpoint](/reference/api/documents.md#get-documents). +**Explanation:** Meilisearch limits the maximum amount of returned search results to protect your database from malicious scraping. You may change this by using the `maxTotalHits` property of the [pagination index settings](/reference/api/pagination.md#maxtotalhits). `maxTotalHits` only applies to the [search route](/reference/api/search.md) and has no effect on the [get documents endpoint](/reference/api/documents.md#get-documents). From b397e1fd2c5c5d93df57d339d080ae8d392d987b Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 29 Jun 2022 16:31:39 +0200 Subject: [PATCH 20/39] pagination settings: update boxes with warnings on non-customizable maximum number of results --- reference/api/search.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/api/search.md b/reference/api/search.md index 491fc9aa8b..9d2a036608 100644 --- a/reference/api/search.md +++ b/reference/api/search.md @@ -20,7 +20,7 @@ Other than the differences mentioned above, the two routes are strictly equivale Search for documents matching a specific query in the given index. The index [`uid`](/learn/core_concepts/indexes.md#index-uid) is required. ::: note -This endpoint has a [non-customizable limit of 1000 results](/learn/advanced/known_limitations.md#maximum-number-of-results-per-search). If you want to scrape your database, use the [get documents endpoint](/reference/api/documents.md#get-documents) instead. +By default, [this endpoint returns a maximum of 1000 results](/learn/advanced/known_limitations.md#maximum-number-of-results-per-search). If you want to scrape your database, use the [get documents endpoint](/reference/api/documents.md#get-documents) instead. ::: This is the preferred route to perform search when an API key is required, as it allows for [preflight requests](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) to be cached. Caching preflight requests **considerably improves search speed**. @@ -111,7 +111,7 @@ Query terms enclosed in double quotes are treated as [phrase searches](#query-q) Search for documents matching a specific query in the given index. The index [`uid`](/learn/core_concepts/indexes.md#index-uid) is required. :::note -This endpoint has a [non-customizable limit of 1000 results](/learn/advanced/known_limitations.md#maximum-number-of-results-per-search). If you want to scrape your database, you can use the [get documents endpoint](/reference/api/documents.md#get-documents) instead. +By default, [this endpoint returns a maximum of 1000 results](/learn/advanced/known_limitations.md#maximum-number-of-results-per-search). If you want to scrape your database, use the [get documents endpoint](/reference/api/documents.md#get-documents) instead. ::: This route should only be used when no API key is required. If an API key is required, use the POST route instead. From 6a618ad0f5f6810a5516b8b1f3306692d2921fb2 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Thu, 30 Jun 2022 12:37:16 +0200 Subject: [PATCH 21/39] Update reference/api/pagination.md Co-authored-by: Maryam <90181761+maryamsulemani97@users.noreply.github.com> --- reference/api/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/api/pagination.md b/reference/api/pagination.md index 0e1debe2ce..485e99c916 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -73,7 +73,7 @@ Setting `maxTotalHits` to a high value might negatively impact performance and e } ``` -You can use the returned `uid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). +You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). ## Reset pagination settings From f48fe20541a3b129dad1a23c135ea9ef54fa3e27 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Thu, 30 Jun 2022 12:37:30 +0200 Subject: [PATCH 22/39] Update reference/api/pagination.md Co-authored-by: Maryam <90181761+maryamsulemani97@users.noreply.github.com> --- reference/api/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/api/pagination.md b/reference/api/pagination.md index 485e99c916..f4d15d47b8 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -95,4 +95,4 @@ Reset an index's pagination settings to their default value. The index [`uid`](/ } ``` -You can use the returned `uid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). +You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). From 213c326c11ec7b1331adc9382b00515d8af6a25c Mon Sep 17 00:00:00 2001 From: Maryam Sulemani Date: Thu, 30 Jun 2022 14:38:14 +0400 Subject: [PATCH 23/39] Add pagination to core concepts/indexes --- learn/core_concepts/indexes.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/learn/core_concepts/indexes.md b/learn/core_concepts/indexes.md index 36f069949e..600bcd2c63 100644 --- a/learn/core_concepts/indexes.md +++ b/learn/core_concepts/indexes.md @@ -59,6 +59,7 @@ You can customize the following index settings: - [Stop words](#stop-words) - [Displayed and searchable attributes](#displayed-and-searchable-attributes) - [Typo tolerance](#typo-tolerance) +- [Pagination](#pagination) To change index settings, use the [update settings endpoint](/reference/api/settings.md#update-settings) or any of the [child routes](/reference/api/settings.md#all-settings). @@ -130,3 +131,11 @@ Typo tolerance is a built-in feature that helps you find relevant results even w You can update the typo tolerance settings using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update typo tolerance endpoint](/reference/api/typo_tolerance.md#update-typo-tolerance). [Learn more about typo tolerance](/learn/configuration/typo_tolerance.md) + +### Pagination + +To protect your database from malicious scraping, Meilisearch returns upto 1000 results for a search query. You can update this using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update pagination settings endpoint](/reference/api/pagination.md#update-pagination-settings). + +We recommend using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters to implement previous and next buttons for a pagination UI. + +[Learn more about pagination](/learn/advanced/pagination.md) From 0a340c234a8b3810394623a4a580fb5dfe7142e5 Mon Sep 17 00:00:00 2001 From: Maryam <90181761+maryamsulemani97@users.noreply.github.com> Date: Thu, 30 Jun 2022 15:23:55 +0400 Subject: [PATCH 24/39] Update learn/core_concepts/indexes.md Co-authored-by: gui machiavelli --- learn/core_concepts/indexes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/core_concepts/indexes.md b/learn/core_concepts/indexes.md index 600bcd2c63..82f89e944a 100644 --- a/learn/core_concepts/indexes.md +++ b/learn/core_concepts/indexes.md @@ -134,7 +134,7 @@ You can update the typo tolerance settings using the [update settings endpoint]( ### Pagination -To protect your database from malicious scraping, Meilisearch returns upto 1000 results for a search query. You can update this using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update pagination settings endpoint](/reference/api/pagination.md#update-pagination-settings). +To protect your database from malicious scraping, Meilisearch only returns up to 1000 results for a search query. You can change this limit using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update pagination settings endpoint](/reference/api/pagination.md#update-pagination-settings). We recommend using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters to implement previous and next buttons for a pagination UI. From 752f0b3f0cf4820d5b112f839214caa3004646a2 Mon Sep 17 00:00:00 2001 From: Maryam <90181761+maryamsulemani97@users.noreply.github.com> Date: Thu, 30 Jun 2022 15:24:43 +0400 Subject: [PATCH 25/39] Update indexes.md --- learn/core_concepts/indexes.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/learn/core_concepts/indexes.md b/learn/core_concepts/indexes.md index 82f89e944a..41ad38db86 100644 --- a/learn/core_concepts/indexes.md +++ b/learn/core_concepts/indexes.md @@ -136,6 +136,4 @@ You can update the typo tolerance settings using the [update settings endpoint]( To protect your database from malicious scraping, Meilisearch only returns up to 1000 results for a search query. You can change this limit using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update pagination settings endpoint](/reference/api/pagination.md#update-pagination-settings). -We recommend using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters to implement previous and next buttons for a pagination UI. - [Learn more about pagination](/learn/advanced/pagination.md) From 511f90451ae52f15211e645ee2b842d3fe47b1dd Mon Sep 17 00:00:00 2001 From: Maryam Sulemani Date: Thu, 30 Jun 2022 16:48:49 +0400 Subject: [PATCH 26/39] update setings --- .code-samples.meilisearch.yaml | 7 +++++++ .vuepress/public/sample-template.yaml | 1 + learn/configuration/settings.md | 17 +++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 047cb60b9f..b13b1ae4d0 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -958,3 +958,10 @@ getting_started_typo_tolerance: |- --data-binary '{ "minWordSizeForTypos": { "oneTypo": 4 } }' +. + curl \ + -X PATCH 'http://localhost:7700/indexes/movies/settings/pagination' \ + -H 'Content-Type: application/json' \ + --data-binary '{ + "maxTotalHits": 100 + }' \ No newline at end of file diff --git a/.vuepress/public/sample-template.yaml b/.vuepress/public/sample-template.yaml index 8b52eec657..2d1ad7ecd8 100644 --- a/.vuepress/public/sample-template.yaml +++ b/.vuepress/public/sample-template.yaml @@ -146,3 +146,4 @@ updating_guide_retrieve_documents_old: |- updating_guide_update_settings_old: |- updating_guide_add_documents_old: |- getting_started_typo_tolerance: |- +settings_guide_pagination_1: |- \ No newline at end of file diff --git a/learn/configuration/settings.md b/learn/configuration/settings.md index a0380f432d..82860a2eca 100644 --- a/learn/configuration/settings.md +++ b/learn/configuration/settings.md @@ -7,6 +7,7 @@ This page describes the **index-level settings** available in Meilisearch and ho | **[displayedAttributes](/learn/configuration/settings.md#displayed-attributes)** | Fields displayed in the returned documents | All attributes found in the documents | | **[distinctAttribute](/learn/configuration/settings.md#distinct-attribute)** | Search returns documents with distinct (different) values of the given field | `null` | | **[filterableAttributes](/learn/configuration/settings.md#filterable-attributes)** | List of attributes that can be used for filtering | `null` | +| **[pagination](/learn/advanced/pagination.md)** | Pagination settings | `{}` | **[rankingRules](/learn/configuration/settings.md#ranking-rules)** | List of ranking rules sorted by order of importance | [A list of ordered built-in ranking rules](/learn/core_concepts/relevancy.md#built-in-rules) | | **[searchableAttributes](/learn/configuration/settings.md#searchable-attributes)** | Fields in which to search for matching query words sorted by order of importance | All attributes found in the documents | | | **[sortableAttributes](/learn/configuration/settings.md#sortable-attributes)** | List of attributes to use when sorting search results | `[]` | @@ -95,6 +96,22 @@ To be able to filter search results on `director` and `genres` in a movie databa +## Pagination + +The maximum number of results Meilisearch can return. By default, this value is `1000` which means you cannot access results beyond `1000`. + +[Learn more about pagination in our dedicated guide.](/learn/advanced/pagination.md) + +### Example + +The code sample below updates `maxTotalHits` to `50`: + + + +::: note +`maxTotalHits` takes priority over search parameters such as [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset). +::: + ## Ranking rules Built-in ranking rules that **ensure relevancy in search results**. Ranking rules are applied in a default order which can be changed in the settings. You can add or remove rules and change their order of importance. From 8d01e108a525964c2d714c3eeb7fa1daf6a607ec Mon Sep 17 00:00:00 2001 From: Maryam Sulemani Date: Thu, 30 Jun 2022 16:51:11 +0400 Subject: [PATCH 27/39] settings_guide_pagination_1 --- .code-samples.meilisearch.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index b13b1ae4d0..b6769bcec9 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -958,7 +958,7 @@ getting_started_typo_tolerance: |- --data-binary '{ "minWordSizeForTypos": { "oneTypo": 4 } }' -. +settings_guide_pagination_1: |- curl \ -X PATCH 'http://localhost:7700/indexes/movies/settings/pagination' \ -H 'Content-Type: application/json' \ From 085dcb46c14e5997cca0f8fd15be3c1bcbd73517 Mon Sep 17 00:00:00 2001 From: Maryam <90181761+maryamsulemani97@users.noreply.github.com> Date: Thu, 30 Jun 2022 16:52:35 +0400 Subject: [PATCH 28/39] Update .code-samples.meilisearch.yaml --- .code-samples.meilisearch.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index b6769bcec9..530540c2db 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -963,5 +963,5 @@ settings_guide_pagination_1: |- -X PATCH 'http://localhost:7700/indexes/movies/settings/pagination' \ -H 'Content-Type: application/json' \ --data-binary '{ - "maxTotalHits": 100 + "maxTotalHits": 50 }' \ No newline at end of file From 486e470fc4306b5d69c10dffb07a1af0d28e856c Mon Sep 17 00:00:00 2001 From: Maryam <90181761+maryamsulemani97@users.noreply.github.com> Date: Thu, 30 Jun 2022 17:27:11 +0400 Subject: [PATCH 29/39] Update learn/core_concepts/indexes.md --- learn/core_concepts/indexes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/core_concepts/indexes.md b/learn/core_concepts/indexes.md index 41ad38db86..c32a7f8309 100644 --- a/learn/core_concepts/indexes.md +++ b/learn/core_concepts/indexes.md @@ -134,6 +134,6 @@ You can update the typo tolerance settings using the [update settings endpoint]( ### Pagination -To protect your database from malicious scraping, Meilisearch only returns up to 1000 results for a search query. You can change this limit using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update pagination settings endpoint](/reference/api/pagination.md#update-pagination-settings). +To protect your database from malicious scraping, Meilisearch only returns up to `1000` results for a search query. You can change this limit using the [update settings endpoint](/reference/api/settings.md#update-settings) or the [update pagination settings endpoint](/reference/api/pagination.md#update-pagination-settings). [Learn more about pagination](/learn/advanced/pagination.md) From 31a144341d56ac7a27c33fb515b2c2300f794704 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 4 Jul 2022 13:00:03 +0200 Subject: [PATCH 30/39] Apply suggestions from code review --- .code-samples.meilisearch.yaml | 3 ++- .vuepress/public/sample-template.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 530540c2db..b1c501cd1d 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -964,4 +964,5 @@ settings_guide_pagination_1: |- -H 'Content-Type: application/json' \ --data-binary '{ "maxTotalHits": 50 - }' \ No newline at end of file + }' + \ No newline at end of file diff --git a/.vuepress/public/sample-template.yaml b/.vuepress/public/sample-template.yaml index 2d1ad7ecd8..58cf6ba345 100644 --- a/.vuepress/public/sample-template.yaml +++ b/.vuepress/public/sample-template.yaml @@ -146,4 +146,4 @@ updating_guide_retrieve_documents_old: |- updating_guide_update_settings_old: |- updating_guide_add_documents_old: |- getting_started_typo_tolerance: |- -settings_guide_pagination_1: |- \ No newline at end of file +settings_guide_pagination_1: |- From 4827ac35d7ceb4cb09404f40a08c49e864337a16 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 4 Jul 2022 13:00:35 +0200 Subject: [PATCH 31/39] Update .code-samples.meilisearch.yaml --- .code-samples.meilisearch.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index b1c501cd1d..530540c2db 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -964,5 +964,4 @@ settings_guide_pagination_1: |- -H 'Content-Type: application/json' \ --data-binary '{ "maxTotalHits": 50 - }' - \ No newline at end of file + }' \ No newline at end of file From 4257e9066200d8c2ad6d2ea893acac8d5acfd231 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 4 Jul 2022 13:00:52 +0200 Subject: [PATCH 32/39] Update .code-samples.meilisearch.yaml --- .code-samples.meilisearch.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 530540c2db..86ff7b1453 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -964,4 +964,5 @@ settings_guide_pagination_1: |- -H 'Content-Type: application/json' \ --data-binary '{ "maxTotalHits": 50 - }' \ No newline at end of file + }' + \ No newline at end of file From 3d3d3de845ead0d189c90c9d397966a684cb4e93 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 4 Jul 2022 13:02:24 +0200 Subject: [PATCH 33/39] add return to code samples file --- .code-samples.meilisearch.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 86ff7b1453..3253d71579 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -965,4 +965,3 @@ settings_guide_pagination_1: |- --data-binary '{ "maxTotalHits": 50 }' - \ No newline at end of file From 655c2627f7b02dd63136117cb05a198351f736aa Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Mon, 4 Jul 2022 16:42:13 +0200 Subject: [PATCH 34/39] Update learn/advanced/pagination.md Co-authored-by: Guillaume Mourier --- learn/advanced/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index f2bff6a617..f1be11ad01 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -16,7 +16,7 @@ We recommend creating pagination interfaces centered around [previous and next b ## Recommended: Previous and next buttons -Using previous and next buttons for pagination means that users can easily page through results, but don't have the ability to jump to an arbitrary results page. +Using previous and next buttons for pagination means that users can easily navigate through results, but don't have the ability to jump to an arbitrary results page. ![Placeholder image for prev/next interface]() From 60890b667dbfd3d0f5bd0552081d70a0d0cfa6c8 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Tue, 5 Jul 2022 19:15:05 +0200 Subject: [PATCH 35/39] Address review feedback --- learn/advanced/pagination.md | 162 ++++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 33 deletions(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index f1be11ad01..2dc3a42524 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -1,4 +1,4 @@ -# Pagination of search results +# Search result pagination In a perfect world, users would not need to look beyond the first search result to find what they were looking for. In practice, however, it is usually necessary to create some kind of pagination interface to browse through long lists of results. @@ -6,13 +6,13 @@ In this guide, we will discuss some of Meilisearch's current limitations, how th ## Choosing the right pagination UI -There are quite a few pagination interfaces you might want to implement in your application. Many common UI patterns have a page selector allowing users to jump to any search results page. To create a page selector, you must know the exact number of total results so you can calculate the precise number of results pages. +There are quite a few pagination interfaces you might want to implement in your application. Many common UI patterns have a page selector allowing users to jump to any search results page. To create a page selector, you must know the exact number of total results so you can calculate the precise number of result pages. For performance reasons, however, Meilisearch cannot provide the exact number of results for a query. Instead, When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. Because of this, we do not recommend creating interfaces with page selectors. If page selection is crucial to the software you are developing, see the [last section of this page](#not-recommended-page-selection) for tips that might help you work around Meilisearch's current limitations. -We recommend creating pagination interfaces centered around [previous and next buttons](#recommended-previous-and-next-buttons). +Many other pagination UIs are fully compatible with Meilisearch, such as infinite scrolling and buttons that manually load more results on click. For an experience similar to page selection, we recommend creating pagination interfaces centered around [previous and next buttons](#recommended-previous-and-next-buttons). ## Recommended: Previous and next buttons @@ -28,61 +28,106 @@ Though this approach offers less precision than a full-blown page selector, it d Previous and next buttons can be implemented using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters. -`limit` sets the size of page. If you set `limit` to 20, Meilisearch's response will contain a maximum of 20 search results. `offset` skips a number of search results. If you set `offset` to 40, Meilisearch's response will skip the first 40 search results. +`limit` sets the size of a page. If you set `limit` to 10, Meilisearch's response will contain a maximum of 10 search results. `offset` skips a number of search results. If you set `offset` to 20, Meilisearch's response will skip the first 20 search results. -You can use both parameters together to effectively create search pages. +For example, you can use Meilisearch's JavaScript SDK to get the first ten films in a movies database: + +```js +const results = await index.search("tarkovsky", { limit: 10, offset: 0 }); +``` +You can use both parameters together to effectively create search pages. #### Search pages and calculating `offset` -If you set `limit` to 20 and `offset` to 0, you get the first twenty results. We can call this our first page. +If you set `limit` to 20 and `offset` to 0, you get the first twenty search results. We can call this our first page. ```js -const results = await index.search("x", { limit: 20, offset: 0 }); +const results = await index.search("tarkovsky", { limit: 20, offset: 0 }); ``` Likewise, if you set `limit` to 20 and `offset` to 40, you skip the first 40 search results and get documents ranked from 41 through 60. We can call this the third results page. ```js -const results = await index.search("x", { limit: 20, offset: 40 }); +const results = await index.search("tarkovsky", { limit: 20, offset: 40 }); ``` -Use this formula to quickly calculate a page's offset value: `offset = limit * (page number - 1)`. +Use this formula to quickly calculate a page's offset value: `offset = limit * (target page number - 1)`. Once a query returns fewer `hits` than your configured `limit`, you have reached the last results page. +#### Keeping track of the current page number + +Even though this UI pattern does not allow users to jump to a specific page, it is still useful to keep track of the current page number. + +The following JavaScript snippet stores the page number in an HTML element, `.pagination`, and updates it every time the user moves to a different search results page: + +```js +function updatePageNumber(elem) { + const directionBtn = elem.id + // Get the page number stored in the pagination element + let pageNumber = parseInt(document.querySelector('.pagination').dataset.pageNumber) + + // Update page number + if (directionBtn === 'previous_button') { + pageNumber = pageNumber - 1 + } else if (directionBtn === 'next_button') { + pageNumber = pageNumber + 1 + } + + // Store new page number in the pagination element + document.querySelector('.pagination').dataset.pageNumber = pageNumber +} + +// Add data to our HTML element stating the user is on the first page +document.querySelector('.pagination').dataset.pageNumber = 0 +// Each time a user clicks on the previous or next buttons, update the page number +document.querySelector('#previous_button').onclick = function () { updatePageNumber(this) } +document.querySelector('#next_button').onclick = function () { updatePageNumber(this) } +``` + #### Disabling navigation buttons for first and last pages It is often helpful to disable navigation buttons when the user cannot move to the "next" or "previous" page. The "previous" button should be disabled whenever your `offset` is 0, as this indicates your user is on the first results page. -To know when to disable the "next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user. Its purpose is to indicate that there is at least one more document to display on the next page: +To know when to disable the "next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user. Its purpose is to indicate that there is at least one more document to display on the next page. -```js -const results = await index.search("x", { limit: 21, offset: 0 }) - -// If offset equals 0, we're on the first results page -if (offset === 0 ) { - document.querySelector("#previous_button").disabled = true; -} +The following JavaScript snippet runs checks whether we should disable a button every time the user navigates to another search results page: -// If offset is bigger than 0, we're not on the first results page -if (offset > 0 ) { - document.querySelector("#previous_button").disabled = false; +```js +function updatePageNumber() { + const pageNumber = parseInt(document.querySelector('.pagination').dataset.pageNumber) + + const offset = pageNumber * 20 + const results = await index.search('x', { limit: 21, offset }) + + // If offset equals 0, we're on the first results page + if (offset === 0 ) { + document.querySelector('#previous_button').disabled = true; + } + + // If offset is bigger than 0, we're not on the first results page + if (offset > 0 ) { + document.querySelector('#previous_button').disabled = false; + } + + // If Meilisearch returns 20 items or less, + // we are on the last page + if (results.hits.length < 21 ) { + document.querySelector('#next_button').disabled = true; + } + + // If Meilisearch returns exactly 21 results + // and our page can only show 20 items at a time, + // we have at least one more page with one result in it + if (results.hits.length === 21 ) { + document.querySelector('#next_button').disabled = false; + } } -// If Meilisearch returns 20 items or less, -// we are on the last page -if (results.hits.length < 21 ) { - document.querySelector("#next_button").disabled = true; -} - -// If Meilisearch returns exactly 21 results -// and our page can only show 20 items at a time, -// we have at least one more page with one result in it -if (results.hits.length === 21 ) { - document.querySelector("#next_button").disabled = false; -} +document.querySelector('#previous_button').onclick = function () { updatePageNumber(this) } +document.querySelector('#next_button').onclick = function () { updatePageNumber(this) } ``` ## Not recommended: Page selection @@ -109,7 +154,58 @@ By default, a search request returns 20 search results. You can change this valu For example, if you set `limit` to 300, every search request made to Meilisearch returns at most 300 documents. If a query returns a `hits` array with 200 items and you want each page to display 20 results, you can create a page selector with 10 pages. -// perhaps a code sample here? +In the following JavaScript snippet, each time a user searches, we make a new query with `limit` set to 300. Once we receive the search results, we store them in a variable and create a list of numbered pages. When users click on any number in the page list, we display a new page: + +```js +// Retrieve search results and create the page selector +function getSearchResults(searchTerm) { + // The amount of results we want to display in each page + const hitsPerPage = 10 + + // The maximum amount of results we will display + const { hits } = await index.search(searchTerm, { limit: 300 }) + + // Clear the previous buttons… + const pagination = document.querySelector('.pagination') + pagination.innerHTML = '' + + // …and create a new button for each search results page + for (let page = 0; page < hits.length; page += hitsPerPage) { + const numberBtn = document.createElement('button'); + numberBtn.innerText = page / hitsPerPage + + // When the user clicks on a page number, show that results page + numberBtn.onclick = function () { + const pageNumber = parseInt(this.innerText) + changePage(pageNumber, hits, hitsPerPage) + } + + pagination.appendChild(numberBtn) + } + + // Display first search results page + changePage(1, hits, hitsPerPage) +} + +// Display a page of search results +function changePage(pageNumber, hits, hitsPerPage) { + const offset = (pageNumber - 1) * hitsPerPage + const paginatedHits = hits.slice(offset, offset + hitsPerPage) + const resultList = document.querySelector('.results') + + resultList.innerHTML = '' + + paginatedHits.map(hit => { + const resultItem = document.createElement('div'); + resultItem.innerText = hit.title + resultList.appendChild(resultItem) + }) +} + +// Get the search bar and retrieve results every time the user makes a new query +const searchBar = document.querySelector('.searchBar') +searchBar.onChange(function () { getSearchResults('tarkovsky') }) +``` This method provides control and reliability. It also prevents users from paginating too far, which might result in performance gains. However, it limits the number of results your users can see. Additionally, we recommend caution when setting high values for `limit` as it can negatively impact performance. From 1693adaf93dc36e584c09cb966ba64958c9606c8 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 6 Jul 2022 15:42:00 +0200 Subject: [PATCH 36/39] Apply suggestions from code review Co-authored-by: Maryam <90181761+maryamsulemani97@users.noreply.github.com> --- learn/advanced/pagination.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index 2dc3a42524..6defdf7338 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -8,7 +8,7 @@ In this guide, we will discuss some of Meilisearch's current limitations, how th There are quite a few pagination interfaces you might want to implement in your application. Many common UI patterns have a page selector allowing users to jump to any search results page. To create a page selector, you must know the exact number of total results so you can calculate the precise number of result pages. -For performance reasons, however, Meilisearch cannot provide the exact number of results for a query. Instead, When using the search endpoint, responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. +For performance reasons, however, Meilisearch cannot provide the exact number of results for a query. Instead, when using the [search endpoint](/reference/api/search.md), responses contain an `estimatedTotalHits` field. As its name indicates, `estimatedTotalHits` is only an estimate of how many documents match your user's query. Because of this, we do not recommend creating interfaces with page selectors. If page selection is crucial to the software you are developing, see the [last section of this page](#not-recommended-page-selection) for tips that might help you work around Meilisearch's current limitations. @@ -28,7 +28,7 @@ Though this approach offers less precision than a full-blown page selector, it d Previous and next buttons can be implemented using the [`limit`](/reference/api/search.md#limit) and [`offset`](/reference/api/search.md#offset) search parameters. -`limit` sets the size of a page. If you set `limit` to 10, Meilisearch's response will contain a maximum of 10 search results. `offset` skips a number of search results. If you set `offset` to 20, Meilisearch's response will skip the first 20 search results. +`limit` sets the size of a page. If you set `limit` to `10`, Meilisearch's response will contain a maximum of 10 search results. `offset` skips a number of search results. If you set `offset` to `20`, Meilisearch's response will skip the first 20 search results. For example, you can use Meilisearch's JavaScript SDK to get the first ten films in a movies database: @@ -37,15 +37,16 @@ const results = await index.search("tarkovsky", { limit: 10, offset: 0 }); ``` You can use both parameters together to effectively create search pages. + #### Search pages and calculating `offset` -If you set `limit` to 20 and `offset` to 0, you get the first twenty search results. We can call this our first page. +If you set `limit` to `20` and `offset` to `0`, you get the first twenty search results. We can call this our first page. ```js const results = await index.search("tarkovsky", { limit: 20, offset: 0 }); ``` -Likewise, if you set `limit` to 20 and `offset` to 40, you skip the first 40 search results and get documents ranked from 41 through 60. We can call this the third results page. +Likewise, if you set `limit` to `20` and `offset` to `40`, you skip the first 40 search results and get documents ranked from 40 through 59. We can call this the third results page. ```js const results = await index.search("tarkovsky", { limit: 20, offset: 40 }); @@ -89,9 +90,9 @@ document.querySelector('#next_button').onclick = function () { updatePageNumber( It is often helpful to disable navigation buttons when the user cannot move to the "next" or "previous" page. -The "previous" button should be disabled whenever your `offset` is 0, as this indicates your user is on the first results page. +The "Previous" button should be disabled whenever your `offset` is `0`, as this indicates your user is on the first results page. -To know when to disable the "next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user. Its purpose is to indicate that there is at least one more document to display on the next page. +To know when to disable the "Next" button, we recommend setting your query's `limit` to the number of results you wish to display per page plus one. That extra `hit` should not be shown to the user. Its purpose is to indicate that there is at least one more document to display on the next page. The following JavaScript snippet runs checks whether we should disable a button every time the user navigates to another search results page: @@ -152,9 +153,9 @@ We recommend two different workarounds to create this kind of pagination interfa By default, a search request returns 20 search results. You can change this value to a much higher number and treat it as the effective maximum of search results you will show a user. Doing so means the size of your `hits` array is the exact number of search results you have to paginate. -For example, if you set `limit` to 300, every search request made to Meilisearch returns at most 300 documents. If a query returns a `hits` array with 200 items and you want each page to display 20 results, you can create a page selector with 10 pages. +For example, if you set `limit` to `300`, every search request made to Meilisearch returns at most 300 documents. If a query returns a `hits` array with 200 items and you want each page to display 20 results, you can create a page selector with 10 pages. -In the following JavaScript snippet, each time a user searches, we make a new query with `limit` set to 300. Once we receive the search results, we store them in a variable and create a list of numbered pages. When users click on any number in the page list, we display a new page: +In the following JavaScript snippet, each time a user searches, we make a new query with `limit` set to `300`. Once we receive the search results, we store them in a variable and create a list of numbered pages. When users click on any number in the page list, we display a new page: ```js // Retrieve search results and create the page selector From 7b8fbc741e88cd1cd091953d589322f95a9108e6 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 6 Jul 2022 15:44:10 +0200 Subject: [PATCH 37/39] Apply suggestions from code review Co-authored-by: Maryam <90181761+maryamsulemani97@users.noreply.github.com> --- learn/advanced/pagination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index 6defdf7338..a8d7354594 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -224,4 +224,4 @@ This method gives users access to all search results. However, it also results i ## Unsatisfied? Let us know -Is the current state of pagination in Meilisearch negatively impacting you? Please share your thoughts with us in this [GitHub discussion](https://github.com/meilisearch/product/discussions/483). We are actively working on improving this aspect of Meilisearch and your input is greatly appreciated. +Is the current state of pagination in Meilisearch negatively impacting you? Please share your thoughts with us in this [GitHub discussion](https://github.com/meilisearch/product/discussions/483). We are actively working on improving this aspect of Meilisearch, and your input is greatly appreciated. From a12ddd348cf1477f67300954adb82bde59363629 Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Wed, 6 Jul 2022 16:08:10 +0200 Subject: [PATCH 38/39] address review feedback --- .vuepress/config.js | 1 + learn/advanced/pagination.md | 14 +++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.vuepress/config.js b/.vuepress/config.js index 395bd548d8..95f02aa241 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -174,6 +174,7 @@ module.exports = { '/learn/advanced/asynchronous_operations', '/learn/advanced/filtering_and_faceted_search', '/learn/advanced/geosearch', + '/learn/advanced/pagination', '/learn/advanced/sorting', { title: 'Updating Meilisearch', diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index a8d7354594..9decfb54c8 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -14,12 +14,10 @@ Because of this, we do not recommend creating interfaces with page selectors. If Many other pagination UIs are fully compatible with Meilisearch, such as infinite scrolling and buttons that manually load more results on click. For an experience similar to page selection, we recommend creating pagination interfaces centered around [previous and next buttons](#recommended-previous-and-next-buttons). -## Recommended: Previous and next buttons +## Recommended: "Previous" and "Next" buttons Using previous and next buttons for pagination means that users can easily navigate through results, but don't have the ability to jump to an arbitrary results page. -![Placeholder image for prev/next interface]() - Though this approach offers less precision than a full-blown page selector, it does not require knowing the precise number of search results. This makes it a good fit for Meilisearch's current capabilities. ### Implementation @@ -52,7 +50,7 @@ Likewise, if you set `limit` to `20` and `offset` to `40`, you skip the first 40 const results = await index.search("tarkovsky", { limit: 20, offset: 40 }); ``` -Use this formula to quickly calculate a page's offset value: `offset = limit * (target page number - 1)`. +You can use this formula to calculate a page's offset value: `offset = limit * (target page number - 1)`. In the previous example, the calculation would look like this: `offset = 20 * (3 - 1)`. This gives us `40` as the result: `offset = 20 * 2 = 40`. Once a query returns fewer `hits` than your configured `limit`, you have reached the last results page. @@ -135,13 +133,11 @@ document.querySelector('#next_button').onclick = function () { updatePageNumber( This type of pagination consists of a numbered list of pages accompanied by next and previous buttons. -![placeholder page selection UI](https://vuejsexamples.com/content/images/2018/11/vue-pagination.gif) - This is a common UI pattern that offers users a significant amount of precision when navigating results. However, due to Meilisearch's [limitations](#choosing-the-right-pagination-ui), it is not a good fit for pagination with Meilisearch. ### Implementation -The general implementation of a page selection interface is similar to our [recommended solution](#recommended-previous-and-next-buttons), but also includes a numbered page list. +The general implementation of a page selection interface is similar to our [recommended solution](#recommended-previous-and-next-buttons), with one signficant addition: it includes a numbered page list. To create a numbered page list, however, you must know the exact number of total results. For example, if you have 100 results and your search result pages contain 10 results each, your selector must show a list of numbers going from 1 to 10. @@ -218,10 +214,10 @@ By default, Meilisearch returns a maximum of 1000 search results. Consult our [i Though we advise against it, you can use `estimatedTotalHits` to calculate the number of search result pages. This means your number of results and page count are likely to change until Meilisearch retrieves the last search result. -For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page according to Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 10 total pages. +For example, a query's `estimatedTotalHits` might be `100` when you fetch the first page of search results. If you are showing 20 results per page, this means your interface will display a page selector with 5 pages. When you fetch the fifth and last page according to Meilisearch's current estimate, however, `estimatedTotalHits` might change to `300`. Your page list, previously displaying 5 pages, must now show 15 total pages. This method gives users access to all search results. However, it also results in an interface that might feel unreliable due to constant and unpredictable changes. ## Unsatisfied? Let us know -Is the current state of pagination in Meilisearch negatively impacting you? Please share your thoughts with us in this [GitHub discussion](https://github.com/meilisearch/product/discussions/483). We are actively working on improving this aspect of Meilisearch, and your input is greatly appreciated. +Is the current state of pagination in Meilisearch creating problems for you? Please share your thoughts with us in this [GitHub discussion](https://github.com/meilisearch/product/discussions/483). We are actively working on improving this aspect of Meilisearch and your input is greatly appreciated. From 8483f25fc3b307de63b95b67ccc9cb45bf166b7e Mon Sep 17 00:00:00 2001 From: gui machiavelli Date: Thu, 7 Jul 2022 12:37:03 +0200 Subject: [PATCH 39/39] pagination: fix linter errors on guide, reference --- learn/advanced/pagination.md | 2 +- learn/configuration/settings.md | 1 - reference/api/faceting.md | 4 ++-- reference/api/pagination.md | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/learn/advanced/pagination.md b/learn/advanced/pagination.md index 9decfb54c8..a75d723a8b 100644 --- a/learn/advanced/pagination.md +++ b/learn/advanced/pagination.md @@ -207,7 +207,7 @@ searchBar.onChange(function () { getSearchResults('tarkovsky') }) This method provides control and reliability. It also prevents users from paginating too far, which might result in performance gains. However, it limits the number of results your users can see. Additionally, we recommend caution when setting high values for `limit` as it can negatively impact performance. ::: note -By default, Meilisearch returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/pagination.md#maxtotalhits-1) if you need to change this. +By default, Meilisearch returns a maximum of 1000 search results. Consult our [index setting reference](/reference/api/pagination.md) if you need to change this. ::: #### Use `estimatedTotalHits` diff --git a/learn/configuration/settings.md b/learn/configuration/settings.md index 01d58b35c5..8c31f449d7 100644 --- a/learn/configuration/settings.md +++ b/learn/configuration/settings.md @@ -129,7 +129,6 @@ The following code sample will return a maximum of `5` facet values for each fac - ## Ranking rules Built-in ranking rules that **ensure relevancy in search results**. Ranking rules are applied in a default order which can be changed in the settings. You can add or remove rules and change their order of importance. diff --git a/reference/api/faceting.md b/reference/api/faceting.md index a2d32ad122..5c8df72aca 100644 --- a/reference/api/faceting.md +++ b/reference/api/faceting.md @@ -73,7 +73,7 @@ Setting `maxValuesPerFacet` to a high value might negatively impact performance. } ``` -You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). +You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-one-task). ## Reset faceting settings @@ -95,4 +95,4 @@ Reset an index's faceting settings to their default value. The index [`uid`](/le } ``` -You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). +You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-one-task). diff --git a/reference/api/pagination.md b/reference/api/pagination.md index f4d15d47b8..f720402990 100644 --- a/reference/api/pagination.md +++ b/reference/api/pagination.md @@ -73,7 +73,7 @@ Setting `maxTotalHits` to a high value might negatively impact performance and e } ``` -You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). +You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-one-task). ## Reset pagination settings @@ -95,4 +95,4 @@ Reset an index's pagination settings to their default value. The index [`uid`](/ } ``` -You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-task). +You can use the returned `taskUid` to get more details on [the status of the task](/reference/api/tasks.md#get-one-task).