diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 3bfe60dbba..231cd45d96 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -1053,7 +1053,9 @@ filtering_update_settings_1: |- -H 'Content-Type: application/json' \ --data-binary '[ "genres", - "director" + "director", + "release_date", + "ratings" ]' get_documents_post_1: |- curl \ diff --git a/config/redirects.json b/config/redirects.json index ab2f724061..60360e34f4 100644 --- a/config/redirects.json +++ b/config/redirects.json @@ -51,7 +51,7 @@ }, { "source": "/docs/learn/advanced/sorting", - "destination": "/docs/learn/filtering_and_sorting/sorting", + "destination": "/docs/learn/filtering_and_sorting/sort_search_results", "permanent": true }, { @@ -378,5 +378,30 @@ "source": "learn/configuration/settings", "destination": "reference/api/settings", "permanent": true + }, + { + "source": "/docs/learn/fine_tuning_results/faceted_search", + "destination": "/docs/learn/filtering_and_sorting/search_with_facet_filters", + "permanent": true + }, + { + "source": "/docs/learn/fine_tuning_results/filtering", + "destination": "/docs/learn/filtering_and_sorting/filter_search_results", + "permanent": true + }, + { + "source": "/docs/learn/fine_tuning_results/working_with_dates", + "destination": "/docs/learn/filtering_and_sorting/working_with_dates", + "permanent": true + }, + { + "source": "/docs/learn/fine_tuning_results/geosearch", + "destination": "/docs/learn/filtering_and_sorting/geosearch", + "permanent": true + }, + { + "source": "/docs/learn/fine_tuning_results/sorting", + "destination": "/docs/learn/filtering_and_sorting/sort_search_results", + "permanent": true } ] diff --git a/config/sidebar-learn.json b/config/sidebar-learn.json index a1373e30fc..cf889ee3bb 100644 --- a/config/sidebar-learn.json +++ b/config/sidebar-learn.json @@ -193,33 +193,38 @@ ] }, { - "title": "Fine-tuning results", - "slug": "fine_tuning_results", + "title": "Filtering and sorting", + "slug": "filtering_and_sorting", "routes": [ { - "source": "learn/fine_tuning_results/faceted_search.mdx", - "label": "Faceted search", - "slug": "faceted_search" + "source": "learn/filtering_and_sorting/filter_search_results.mdx", + "label": "Filter search results", + "slug": "filter_search_results" }, { - "source": "learn/fine_tuning_results/filtering.mdx", - "label": "Filtering", - "slug": "filtering" + "source": "learn/filtering_and_sorting/search_with_facet_filters.mdx", + "label": "Search with facet filters", + "slug": "search_with_facet_filters" }, { - "source": "learn/fine_tuning_results/working_with_dates.mdx", - "label": "Filtering and sorting by date", + "source": "learn/filtering_and_sorting/working_with_dates.mdx", + "label": "Filter and sort by date", "slug": "working_with_dates" }, { - "source": "learn/fine_tuning_results/geosearch.mdx", + "source": "learn/filtering_and_sorting/sort_search_results.mdx", + "label": "Sort search results", + "slug": "sort_search_results" + }, + { + "source": "learn/filtering_and_sorting/geosearch.mdx", "label": "Geosearch", "slug": "geosearch" }, { - "source": "learn/fine_tuning_results/sorting.mdx", - "label": "Sorting", - "slug": "sorting" + "source": "learn/filtering_and_sorting/filter_expression_reference.mdx", + "label": "Filter expression reference", + "slug": "filter_expression_reference" } ] }, diff --git a/guides/indexing_best_practices.mdx b/guides/indexing_best_practices.mdx index 96d3b8ea8d..20a0fa50f5 100644 --- a/guides/indexing_best_practices.mdx +++ b/guides/indexing_best_practices.mdx @@ -14,7 +14,7 @@ To speed up indexing, review your list of [searchable attributes](/learn/relevan ### Review filterable and sortable attributes -Some document fields are necessary for [filtering](/learn/fine_tuning_results/filtering) and [sorting](/learn/fine_tuning_results/sorting) results, but they dot not need to be _searchable_. Generally, **numeric and boolean fields** fall into this category. Make sure to review your list of searchable attributes and remove any fields that are only used for filtering or sorting. +Some document fields are necessary for [filtering](/learn/filtering_and_sorting/filter_search_results) and [sorting](/learn/filtering_and_sorting/sort_search_results) results, but they dot not need to be _searchable_. Generally, **numeric and boolean fields** fall into this category. Make sure to review your list of searchable attributes and remove any fields that are only used for filtering or sorting. ## Set ranking rules before indexing diff --git a/guides/laravel_scout.mdx b/guides/laravel_scout.mdx index ae0eeca74f..9e31ffb76b 100644 --- a/guides/laravel_scout.mdx +++ b/guides/laravel_scout.mdx @@ -133,7 +133,7 @@ class Contact extends Model ## Configuring filterable and sortable attributes -Configure which attributes are [filterable](/learn/fine_tuning_results/filtering) and [sortable](/learn/fine_tuning_results/sorting) via your Meilisearch index settings. +Configure which attributes are [filterable](/learn/filtering_and_sorting/filter_search_results) and [sortable](/learn/filtering_and_sorting/sort_search_results) via your Meilisearch index settings. In Laravel, you can configure your index settings via the `config/scout.php` file: @@ -182,7 +182,7 @@ You built an example application to demonstrate how to use Meilisearch with Lara This demo application uses the following features: - [Multi-search](/reference/api/multi_search) (search across multiple indexes) - [Multi-tenancy](/learn/security/multitenancy_tenant_tokens) -- [Filtering](/learn/fine_tuning_results/filtering) -- [Sorting](/learn/fine_tuning_results/sorting) +- [Filtering](/learn/filtering_and_sorting/filter_search_results) +- [Sorting](/learn/filtering_and_sorting/sort_search_results) Of course, the code is open-sourced on [Github](https://github.com/meilisearch/saas-demo). 🎉 diff --git a/learn/core_concepts/documents.mdx b/learn/core_concepts/documents.mdx index 3cb6ac10f6..2bd143b3d4 100644 --- a/learn/core_concepts/documents.mdx +++ b/learn/core_concepts/documents.mdx @@ -37,7 +37,7 @@ If a field contains an object, Meilisearch flattens it during indexing using dot With [ranking rules](/learn/relevancy/ranking_rules), you can decide which fields are more relevant than others. For example, you may decide recent movies should be more relevant than older ones. You can also designate certain fields as displayed or searchable. -Some features require Meilisearch to reserve attributes. For example, to use [geosearch functionality](/learn/fine_tuning_results/geosearch) your documents must include a `_geo` field. +Some features require Meilisearch to reserve attributes. For example, to use [geosearch functionality](/learn/filtering_and_sorting/geosearch) your documents must include a `_geo` field. Reserved attributes are always prefixed with an underscore (`_`). diff --git a/learn/core_concepts/indexes.mdx b/learn/core_concepts/indexes.mdx index e8f8ad1885..deb690e08a 100644 --- a/learn/core_concepts/indexes.mdx +++ b/learn/core_concepts/indexes.mdx @@ -99,7 +99,7 @@ Facets are a specific use-case of filters in Meilisearch: whether something is a By default, Meilisearch returns `100` facet values for each faceted field. You can change this using the [update settings endpoint](/reference/api/settings#update-settings) or the [update faceting settings endpoint](/reference/api/settings#update-faceting-settings). -[Learn more about faceting.](/learn/fine_tuning_results/faceted_search) +[Learn more about faceting.](/learn/filtering_and_sorting/search_with_facet_filters) ### Filterable attributes @@ -107,7 +107,7 @@ Filtering allows you to refine your search based on different categories. For ex Before filtering on any document attribute, you must add it to `filterableAttributes` using the [update settings endpoint](/reference/api/settings#update-settings) or the [update filterable attributes endpoint](/reference/api/settings#update-filterable-attributes). Then, make a search query using the [`filter` search parameter](/reference/api/search#filter). -[Learn more about filtering.](/learn/fine_tuning_results/filtering) +[Learn more about filtering.](/learn/filtering_and_sorting/filter_search_results) ### Pagination @@ -129,7 +129,7 @@ By default, Meilisearch orders results according to their relevancy. You can alt Add the attributes you'd like to sort by to `sortableAttributes` using the [update settings endpoint](/reference/api/settings#update-settings) or the [update sortable attributes endpoint](/reference/api/settings#update-sortable-attributes). You can then use the [`sort` search parameter](/reference/api/search#sort) to sort your results in ascending or descending order. -[Learn more about sorting.](/learn/fine_tuning_results/sorting) +[Learn more about sorting.](/learn/filtering_and_sorting/sort_search_results) ### Stop words diff --git a/learn/core_concepts/relevancy.mdx b/learn/core_concepts/relevancy.mdx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/learn/engine/datatypes.mdx b/learn/engine/datatypes.mdx index d8ee953df4..57b516272c 100644 --- a/learn/engine/datatypes.mdx +++ b/learn/engine/datatypes.mdx @@ -79,7 +79,7 @@ A numeric type (`integer`, `float`) is converted to a human-readable decimal num You can add [custom ranking rules](/learn/relevancy/custom_ranking_rules) to create an ascending or descending sorting rule on a given attribute that has a numeric value in the documents. -You can also create [filters](/learn/fine_tuning_results/filtering). The `>`, `>=`, `<`, `<=`, and `TO` relational operators apply only to numerical values. +You can also create [filters](/learn/filtering_and_sorting/filter_search_results). The `>`, `>=`, `<`, `<=`, and `TO` relational operators apply only to numerical values. ## Boolean diff --git a/learn/filtering_and_sorting/facet_types.mdx b/learn/filtering_and_sorting/facet_types.mdx new file mode 100644 index 0000000000..cbc55dc9a2 --- /dev/null +++ b/learn/filtering_and_sorting/facet_types.mdx @@ -0,0 +1,62 @@ +--- +title: Faceted search — Meilisearch documentation +description: Faceted search interfaces provide users with a quick way to narrow down search results by selecting categories relevant to their query. +sidebarDepth: 3 +--- + +# Facet types + +## Conjunctive facets + +Conjunctive facets use the `AND` logical operator. When users select multiple values for a facet, returned results must contain all selected facet values. + +With conjunctive facets, when a user selects `English` from the `language` facet, all returned books must be in English. If the user further narrows down the search by selecting `Fiction` and `Literature` as `genres`, all returned books must be in English and contain both `genres`. + +``` +"language = English AND genres = Fiction AND genres = Literature" +``` + +The GIF below shows how the facet count for `genres` updates to only include books that meet **all three conditions**. + +![Selecting English books with 'Fiction' and 'Literature' as 'genres' for the books dataset](/assets/images/faceted-search/conjunctive-factes.gif) + +## Disjunctive facets + +Disjunctive facets use the `OR` logical operator. When users select multiple values for a facet, returned results must contain at least one of the selected values. + +With disjunctive facets, when a user selects `Fiction`, and `Literature`, Meilisearch returns all books that are either `Fiction`, `Literature`, or both: + +``` +"genres = Fiction OR genres = Literature" +``` + +The GIF below shows the `books` dataset with disjunctive facets. Notice how the facet count for `genres` updates based on the selection. + +![Selecting 'Fiction' and 'Literature' as 'genres' for the books dataset](/assets/images/faceted-search/disjunctive_facets.gif) + +### Combining conjunctive and disjunctive facets + +It is possible to create search queries with both conjunctive and disjunctive facets. + +For example, a user might select `English` and `French` from the `language` facet so they can see books written either in English or in French. This query uses an `OR` operator and is a disjunctive facet: + +``` +"language = English OR language = French" +``` + +The same user might also be interested in literary fiction books and select `Fiction` and `Literature` as `genres`. Since the user wants a specific combination of genres, their query uses an `AND` operator: + +``` +"genres = Fiction AND genres = Literature" +``` + +The user can combine these two filter expressions in one by wrapping them in parentheses and using an `AND` operator: + +``` +"(language = English OR language = French) AND (genres = Fiction AND genres = Literature)" +``` + +The GIF below shows the `books` dataset with conjunctive and disjunctive facets. Notice how the facet count for each facet updates based on the selection. + +![Selecting 'Fiction' and 'Literature' as 'genres' for English books](/assets/images/faceted-search/conjunctive-and-disjunctive-facets.gif) + diff --git a/learn/filtering_and_sorting/facets_vs_filters.mdx b/learn/filtering_and_sorting/facets_vs_filters.mdx new file mode 100644 index 0000000000..877244244b --- /dev/null +++ b/learn/filtering_and_sorting/facets_vs_filters.mdx @@ -0,0 +1,27 @@ +--- +title: Faceted search — Meilisearch documentation +description: Faceted search interfaces provide users with a quick way to narrow down search results by selecting categories relevant to their query. +sidebarDepth: 3 +--- + +You can use Meilisearch filters to build faceted search interfaces. This type of interface allows users to refine search results based on broad categories or facets. Faceted search provides users with a quick way to narrow down search results by selecting categories relevant to what they are looking for. A faceted navigation system is an **intuitive interface to display and navigate through content**. + +Facets are common in ecommerce sites like Amazon. When users search for products, they are presented with a list of results and a list of facets which you can see on the sidebar in the image below: + +[![Meilisearch demo for an ecommerce website displaying faceting UI](/assets/images/faceted-search/facets-ecommerce.png)](https://ecommerce.meilisearch.com/?utm_campaign=oss&utm_source=docs&utm_medium=faceted-search&utm_content=image) + +Faceted search interfaces often have a count of how many results belong to each facet. This gives users a visual clue of the range of results available for each facet. + +### Filters or facets + +Meilisearch does not differentiate between facets and filters. Facets are a specific use-case of filters, meaning you can use any attribute added to `filterableAttributes` as a facet. Whether something is a filter or a facet depends above all on UX and UI design. + +## Example application + +The Meilisearch ecommerce demo makes heavy use of faceting features to enable: +- Filtering products by category and brand +- Filtering products by price range and rating +- Searching through facet values (e.g. category) +- Sorting facet values (count or alphabetical order) + +Check out the [ecommerce demo](https://ecommerce.meilisearch.com/?utm_campaign=oss&utm_source=docs&utm_medium=faceted-search&utm_content=link) and the [GitHub repository](https://github.com/meilisearch/ecommerce-demo/). \ No newline at end of file diff --git a/learn/filtering_and_sorting/filter_expression_reference.mdx b/learn/filtering_and_sorting/filter_expression_reference.mdx new file mode 100644 index 0000000000..a5eb5746e4 --- /dev/null +++ b/learn/filtering_and_sorting/filter_expression_reference.mdx @@ -0,0 +1,254 @@ +--- +title: Filter expression reference — Meilisearch documentation +description: The `filter` search parameter expects a filter expression. Filter expressions are made of attributes, values, and several operators. +--- + +# Filter expression reference + +The `filter` search parameter expects a filter expression. Filter expressions are made of attributes, values, and several operators. + +`filter` expects a **filter expression** containing one or more **conditions**. A filter expression can be written as a string, array, or mix of both. + +## Data types + +Filters accept numeric and string values. Empty fields or fields containing an empty array will be ignored. + +Filters do not work with [`NaN`](https://en.wikipedia.org/wiki/NaN) and infinite values such as `inf` and `-inf` as they are [not supported by JSON](https://en.wikipedia.org/wiki/JSON#Data_types). It is possible to filter infinite and `NaN` values if you parse them as strings, except when handling [`_geo` fields](/learn/filtering_and_sorting/geosearch#preparing-documents-for-location-based-search). + + +For best results, enforce homogeneous typing across fields, especially when dealing with large numbers. Meilisearch does not enforce a specific schema when indexing data, but the filtering engine may coerce the type of `value`. This can lead to undefined behavior, such as when big floating-point numbers are coerced into integers. + + +## Conditions + +Conditions are a filter's basic building blocks. They are written in the `attribute OPERATOR value` format, where: + +- `attribute` is the attribute of the field you want to filter on +- `OPERATOR` can be `=`, `!=`, `>`, `>=`, `<`, `<=`, `TO`, `EXISTS`, `IN`, `NOT`, `AND`, or `OR` +- `value` is the value the `OPERATOR` should look for in the `attribute` + +### Examples + +A basic condition requesting movies whose `genres` attribute is equal to `horror`: + +``` +genres = horror +``` + +String values containing whitespace must be enclosed in single or double quotes: + +``` +director = 'Jordan Peele' +director = "Tim Burton" +``` + +## Filter operators + +### Equality (`=`) + +The equality operator (`=`) returns all documents containing a specific value for a given attribute: + +``` +genres = action +``` + +When operating on strings, `=` is case-insensitive. + +The equality operator does not return any results for `null` and empty arrays. + +### Inequality (`!=`) + +The inequality operator (`!=`) returns all documents not selected by the equality operator. When operating on strings, `!=` is case-insensitive. + +The following expression returns all movies without the `action` genre: + +``` +genres != action +``` + +### Comparison (`>`, `<`, `>=`, `<=`) + +The comparison operators (`>`, `<`, `>=`, `<=`) select documents satisfying a comparison. Comparison operators only apply only to numerical values. + +The expression below returns all documents with a user rating above 85: + +``` +rating.users > 85 +``` + +### `TO` + +`TO` is equivalent to `>= AND <=`. The following expression returns all documents with a rating of 80 or above but below 90: + +``` +rating.users 80 TO 89 +``` + +### `EXISTS` + +The `EXISTS` operator checks for the existence of a field. Fields with empty or `null` values count as existing. + +The following expression returns all documents containing the `release_date` field: + +``` +release_date EXISTS +``` + +The negated form of the above expression can be written in two equivalent ways: + +``` +release_date NOT EXISTS +NOT release_date EXISTS +``` + +### `IS EMPTY` + +The `IS EMPTY` operator selects documents in which the specified attribute exists but contains empty values. The following expression only returns documents with an empty `overview` field: + +``` +overview IS EMPTY +``` + +`IS EMPTY` matches the following JSON values: + +- `""` +- `[]` +- `{}` + +Meilisearch does not treat `null` values as empty. To match `null` fields, use the [`IS NULL`](#is-null) operator. + +Use `NOT` to build the negated form of `IS EMPTY`: + +``` +overview IS NOT EMPTY +NOT overview IS EMPTY +``` + +### `IS NULL` + +The `IS NULL` operator selects documents in which the specified attribute exists but contains a `null` value. The following expression only returns documents with a `null` `overview` field: + +``` +overview IS NULL +``` + +Use `NOT` to build the negated form of `IS NULL`: + +``` +overview IS NOT NULL +NOT overview IS NULL +``` + +### `IN` + +`IN` combines equality operators by taking an array of comma-separated values delimited by square brackets. It selects all documents whose chosen field contains at least one of the specified values. + +The following expression returns all documents whose `genres` includes either `horror`, `comedy`, or both: + +``` +genres IN [horror, comedy] +genres = horror OR genres = comedy +``` + +The negated form of the above expression can be written as: + +``` +genres NOT IN [horror, comedy] +NOT genres IN [horror, comedy] +``` + +### `NOT` + +The negation operator (`NOT`) selects all documents that do not satisfy a condition. It has higher precedence than `AND` and `OR`. + +The following expression will return all documents whose `genres` does not contain `horror` and documents with a missing `genres` field: + +``` +NOT genres = horror +``` + +## Filter expressions + +You can build filter expressions by grouping basic conditions using `AND` and `OR`. Filter expressions can be written as strings, arrays, or a mix of both. + +### Filter expression grouping operators + +#### `AND` + +`AND` connects two conditions and only returns documents that satisfy both of them. `AND` has higher precedence than `OR`. + +The following expression returns all documents matching both conditions: + +``` +genres = horror AND director = 'Jordan Peele' +``` + +#### `OR` + +`OR` connects two conditions and returns results that satisfy at least one of them. + +The following expression returns documents matching either condition: + +``` +genres = horror OR genres = comedy +``` + +### Creating filter expressions with string operators and parentheses + +Meilisearch reads string expressions from left to right. You can use parentheses to ensure expressions are correctly parsed. + +For instance, if you want your results to only include `comedy` and `horror` documents released after March 1995, the parentheses in the following query are mandatory: + +``` +(genres = horror OR genres = comedy) AND release_date > 795484800 +``` + +Failing to add these parentheses will cause the same query to be parsed as: + +``` +genres = horror OR (genres = comedy AND release_date > 795484800) +``` + +Translated into English, the above expression will only return comedies released after March 1995 or horror movies regardless of their `release_date`. + + +When creating an expression with a field name or value identical to a filter operator such as `AND` or `NOT`, you must wrap it in quotation marks: `title = "NOT" OR title = "AND"`. + + +### Creating filter expressions with arrays + +Array expressions establish logical connectives by nesting arrays of strings. **Array filters can have a maximum depth of two.** Expressions with three or more levels of nesting will throw an error. + +Outer array elements are connected by an `AND` operator. The following expression returns `horror` movies directed by `Jordan Peele`: + +``` +["genres = horror", "director = 'Jordan Peele'"] +``` + +Inner array elements are connected by an `OR` operator. The following expression returns either `horror` or `comedy` films: + +``` +[["genres = horror", "genres = comedy"]] +``` + +Inner and outer arrays can be freely combined. The following expression returns both `horror` and `comedy` movies directed by `Jordan Peele`: + +``` +[["genres = horror", "genres = comedy"], "director = 'Jordan Peele'"] +``` + +### Combining arrays and string operators + +You can also create filter expressions that use both array and string syntax. + +The following filter is written as a string and only returns movies not directed by `Jordan Peele` that belong to the `comedy` or `horror` genres: + +``` +"(genres = comedy OR genres = horror) AND director != 'Jordan Peele'" +``` + +You can write the same filter mixing arrays and strings: + +``` +[["genres = comedy", "genres = horror"], "NOT director = 'Jordan Peele'"] +``` diff --git a/learn/filtering_and_sorting/filter_search_results.mdx b/learn/filtering_and_sorting/filter_search_results.mdx new file mode 100644 index 0000000000..122327944f --- /dev/null +++ b/learn/filtering_and_sorting/filter_search_results.mdx @@ -0,0 +1,77 @@ +--- +title: Filter search results — Meilisearch documentation +description: In this guide you will see how to configure and use Meilisearch filters in a hypothetical movie database. +--- + +# Filter search results + +In this guide you will see how to configure and use Meilisearch filters in a hypothetical movie database. + +## Configure index settings + +Suppose you have a collection of movies called `movie_ratings` containing the following fields: + +```json +[ + { + "id": 458723, + "title": "Us", + "director": "Jordan Peele", + "release_date": 1552521600, + "genres": [ + "Thriller", + "Horror", + "Mystery" + ], + "rating": { + "critics": 86, + "users": 73 + }, + }, + … +] +``` + +If you want to filter results based on an attribute, you must first add it to the `filterableAttributes` list: + + + +**This step is mandatory and cannot be done at search time**. Updating `filterableAttributes` requires Meilisearch to re-index all your data, which will take an amount of time proportionate to your dataset size and complexity. + + +By default, `filterableAttributes` is empty. Filters do not work without first explicitly adding attributes to the `filterableAttributes` list. + + +## Use `filter` when searching + +After updating the [`filterableAttributes` index setting](//reference/api/settings#filterable-attributes), you can use `filter` to fine-tune your search results. + +`filter` is a search parameter you may use at search time. `filter` accepts [filter expressions](/learn/filtering_and_sorting/filter_expression_reference) built using any attributes present in the `filterableAttributes` list. + +The following code sample returns `Avengers` movies released after 18 March 1995: + + + +Use dot notation to filter results based on a document's [nested fields](/learn/engine/datatypes). The following query only returns thrillers with good user reviews: + + + +You can also combine multiple conditions. For example, you can limit your search so it only includes `Batman` movies directed by either `Tim Burton` or `Christopher Nolan`: + + + +Here, the parentheses are mandatory: without them, the filter would return movies directed by `Tim Burton` and released after 1995 or any film directed by `Christopher Nolan`, without constraints on its release date. This happens because `AND` takes precedence over `OR`. + +If you only want recent `Planet of the Apes` movies that weren't directed by `Tim Burton`, you can use this filter: + + + +`NOT director = "Tim Burton"` will include both documents that do not contain `"Tim Burton"` in its `director` field and documents without a `director` field. To return only documents that have a `director` field, expand the filter expression with the `EXISTS` operator: + +``` +release_date > 1577884550 AND (NOT director = "Tim Burton" AND director EXISTS) +``` + + +[Synonyms](/learn/configuration/synonyms) don't apply to filters. Meaning, if you have `SF` and `San Francisco` set as synonyms, filtering by `SF` and `San Francisco` will show you different results. + diff --git a/learn/fine_tuning_results/geosearch.mdx b/learn/filtering_and_sorting/geosearch.mdx similarity index 97% rename from learn/fine_tuning_results/geosearch.mdx rename to learn/filtering_and_sorting/geosearch.mdx index 9b45bbc2f3..047a9f5e00 100644 --- a/learn/fine_tuning_results/geosearch.mdx +++ b/learn/filtering_and_sorting/geosearch.mdx @@ -127,7 +127,7 @@ In order to filter results based on their location, you must add the `_geo` attr Meilisearch will rebuild your index whenever you update `filterableAttributes`. Depending on the size of your dataset, this might take a considerable amount of time. -[You can read more about configuring `filterableAttributes` in our dedicated filtering guide.](/learn/fine_tuning_results/filtering#configuring-filters) +[You can read more about configuring `filterableAttributes` in our dedicated filtering guide.](/learn/filtering_and_sorting/filter_search_results) ### Usage @@ -230,7 +230,7 @@ Before using geosearch for sorting, you must add the `_geo` attribute to the `so Note that Meilisearch will rebuild your index whenever you update `sortableAttributes`. Depending on the size of your dataset, this might take a considerable amount of time. -[You can read more about configuring `sortableAttributes` in our dedicated sorting guide.](/learn/fine_tuning_results/sorting#configuring-meilisearch-for-sorting-at-search-time) +[You can read more about configuring `sortableAttributes` in our dedicated sorting guide.](/learn/filtering_and_sorting/sort_search_results) ### Usage @@ -244,7 +244,7 @@ _geoPoint(0.0, 0.0):asc If either `lat` or `lng` is invalid or missing, Meilisearch will return an [`invalid_search_sort`](/reference/errors/error_codes#invalid_search_sort) error. An error will also be thrown if you fail to indicate a sorting order. -[You can read more about sorting in our dedicated guide.](/learn/fine_tuning_results/sorting#sorting-results-at-search-time) +[You can read more about sorting in our dedicated guide.](/learn/filtering_and_sorting/sort_search_results) `_geo`, `_geoDistance`, and `_geoRadius` are not valid `sort` values. Trying to use any of them with the `sort` search parameter will result in an [`invalid_search_sort`](/reference/errors/error_codes#invalid_search_sort) error. @@ -346,7 +346,7 @@ By default, Meilisearch emphasizes relevant sorting over exhaustive sorting. Thi Since `_geoPoint` is part of the `sort` search parameter, its weight when ranking results is controlled by the position of the `"sort"` rule in the `rankingRules` array. -[You can read more about the `"sort"` ranking rule and how to customize it in our dedicated sorting guide.](/learn/fine_tuning_results/sorting#sorting-and-custom-ranking-rules) +[You can read more about the `"sort"` ranking rule and how to customize it in our dedicated sorting guide.](/learn/filtering_and_sorting/sort_search_results#sorting-and-custom-ranking-rules) ## Finding the distance between a document and a `_geoPoint` diff --git a/learn/filtering_and_sorting/search_with_facet_filters.mdx b/learn/filtering_and_sorting/search_with_facet_filters.mdx new file mode 100644 index 0000000000..18cf5f21d1 --- /dev/null +++ b/learn/filtering_and_sorting/search_with_facet_filters.mdx @@ -0,0 +1,152 @@ +--- +title: Search with facets — Meilisearch documentation +description: Faceted search interfaces provide users with a quick way to narrow down search results by selecting categories relevant to their query. +--- + +# Search with facets + +In Meilisearch, facets are a specialized type of filter. This guide shows you how to configure facets and use them when searching a database of books. It also gives you instruction on how to get + +## Requirements + +- a Meilisearch project +- a command-line terminal + +## Configure facet index settings + +First, create a new index using this books dataset. Documents in this dataset have the following fields: + +```json +{ + "id": 5, + "title": "Hard Times", + "genres": ["Classics","Fiction", "Victorian", "Literature"], + "publisher": "Penguin Classics", + "language": "English", + "author": "Charles Dickens", + "description":"Hard Times is a novel of social […] ", + "format": "Hardcover", + "rating": 3 +} +``` + +Next, add `genres`, `language`, and `rating` to the list of `filterableAttributes`: + + + +You have now configured your index to use these attributes as filters. + +## Use facets in a search query + +Make a search query setting the `facets` search parameter: + + + +The response returns all books matching the query. It also returns two fields you can use to create a faceted search interface, `facetDistribution` and `facetStats`: + +```json +{ + "hits":[ + … + ], + … + "facetDistribution":{ + "genres":{ + "Classics":6, + … + }, + "language":{ + "English":6, + "French":1, + "Spanish":1 + }, + "rating":{ + "2.5":1, + … + } + }, + "facetStats":{ + "rating":{ + "min":2.5, + "max":4.7 + } + } +} +``` + +`facetDistribution` lists all facets present in your search results, along with the number of documents returned for each facet. + +`facetStats` contains the highest and lowest values for all facets containing numeric values. + +### Sorting facet values + +By default, all facet values are sorted in ascending alphanumeric order. You can change this using the `sortFacetValuesBy` property of the [`faceting` index settings](/reference/api/settings#faceting): + + + +The above code sample sorts the `genres` facet by descending value count. + +Repeating the previous query using the new settings will result in a different order in `facetsDistribution`: + +```json +{ + … + "facetDistribution": { + "genres": { + "Fiction": 8, + "Literature": 7, + "Classics": 6, + "Novel": 2, + "Horror": 2, + "Fantasy": 2, + "Victorian": 2, + "Vampires": 1, + "Tragedy": 1, + "Satire": 1, + "Romance": 1, + "Historical Fiction": 1, + "Coming-of-Age": 1, + "Comedy": 1 + }, + … + } +} +``` + +## Searching facet values + +You can also search for facet values with the [facet search endpoint](/reference/api/facet_search): + + + +The following code sample searches the `genres` facet for values starting with `c`: + +The response contains a `facetHits` array listing all matching facets, together with the total number of documents that include that facet: + +```json +{ + … + "facetHits": [ + { + "value": "Children's Literature", + "count": 1 + }, + { + "value": "Classics", + "count": 6 + }, + { + "value": "Comedy", + "count": 2 + }, + { + "value": "Coming-of-Age", + "count": 1 + } + ], + "facetQuery": "c", + … +} +``` + +You can further refine results using the `q`, `filter`, and `matchingStrategy` parameters. [Learn more about them in the API reference.](/reference/api/facet_search) diff --git a/learn/fine_tuning_results/sorting.mdx b/learn/filtering_and_sorting/sort_search_results.mdx similarity index 76% rename from learn/fine_tuning_results/sorting.mdx rename to learn/filtering_and_sorting/sort_search_results.mdx index 4705b2f565..77097c771c 100644 --- a/learn/fine_tuning_results/sorting.mdx +++ b/learn/filtering_and_sorting/sort_search_results.mdx @@ -1,10 +1,10 @@ --- -title: Sorting — Meilisearch documentation +title: Sort search results — Meilisearch documentation description: By default, Meilisearch sorts results according to their relevancy. You can alter this behavior so users can decide at search time results they want to see first. sidebarDepth: 3 --- -# Sorting +# Sort search results By default, Meilisearch focuses on ordering results according to their relevancy. You can alter this sorting behavior so users can decide at search time what type of results they want to see first. @@ -14,7 +14,7 @@ This can be useful in many situations, such as when a user wants to see the chea Sorting at search time can be particularly effective when combined with [placeholder searches](/reference/api/search#placeholder-search). -## Configuring Meilisearch for sorting at search time +## Configure Meilisearch for sorting at search time To allow your users to sort results at search time you must: @@ -28,22 +28,18 @@ Meilisearch sorts strings in lexicographic order based on their byte values. For Uppercase letters are sorted as if they were lowercase. They will still appear uppercase in search results. -### Select attributes for sorting +### Add attributes to `sortableAttributes` Meilisearch allows you to sort results based on document fields. Only fields containing numbers, strings, arrays of numeric values, and arrays of string values can be used for sorting. +After you have decided which fields you will allow your users to sort on, you must add their attributes to the [`sortableAttributes` index setting](/reference/api/settings#sortable-attributes). + If a field has values of different types across documents, Meilisearch will give precedence to numbers over strings. This means documents with numeric field values will be ranked higher than those with string values. -This can lead to unexpected behavior when sorting, so we strongly recommend you only allow sorting at query time on fields containing the same type of value. +This can lead to unexpected behavior when sorting. For optimal user experience, only sort based on fields containing the same type of value. -### Adding attributes to `sortableAttributes` - -After you have decided which fields you will allow your users to sort on, you must add their attributes to the [`sortableAttributes` index setting](/reference/api/settings#sortable-attributes). - -`sortableAttributes` accepts an array of strings, each corresponding to one attribute. Note that the attribute order in `sortableAttributes` has no impact on sorting. - #### Example Suppose you have collection of books containing the following fields: @@ -63,46 +59,6 @@ Suppose you have collection of books containing the following fields: }, "price": 5.00 }, - { - "id": 2, - "title": "The Parable of the Sower", - "author": "Octavia E. Butler", - "genres": [ - "science fiction" - ], - "rating": { - "critics": 90, - "users": 92 - }, - "price": 10.00 - }, - { - "id": 3, - "title": "Gender Trouble", - "author": "Judith Butler", - "genres": [ - "feminism", - "philosophy" - ], - "rating": { - "critics": 86, - "users": 73 - }, - "price": 10.00 - }, - { - "id": 4, - "title": "Wild Seed", - "author": "Octavia E. Butler", - "genres": [ - "fantasy" - ], - "rating": { - "critics": 84, - "users": 80 - }, - "price": 5.00 - }, … ] ``` @@ -142,15 +98,13 @@ If your users care more about finding cheaper books than they care about finding -## Sorting results at search time +## Sort results at search time After configuring `sortableAttributes`, you can use the [`sort` search parameter](/reference/api/search#sort) to control the sorting order of your search results. -### Using `sort` - `sort` expects a list of attributes that have been added to the `sortableAttributes` list. -**Attributes must be given as** `attribute:sorting_order`. In other words, each attribute must be followed by a colon (`:`) and a sorting order: either ascending (`asc`) or descending (`desc`). +Attributes must be given as `attribute:sorting_order`. In other words, each attribute must be followed by a colon (`:`) and a sorting order: either ascending (`asc`) or descending (`desc`). When using the `POST` route, `sort` expects an array of strings: @@ -167,8 +121,6 @@ When using the `GET` route, `sort` expects a comma-separated string: sort="price:desc,author:asc" ``` -We strongly recommend using `POST` over `GET` routes whenever possible. - The order of `sort` values matter: the higher an attribute is in the search parameter value, the more Meilisearch will prioritize it over attributes placed lower. In our example, if multiple documents have the same value for `price`, Meilisearch will decide the order between these similarly-priced documents based on their `author`. #### Example @@ -259,7 +211,7 @@ It is common to search books based on an author's name. `sort` can help grouping ] ``` -#### Sorting by nested fields +### Sort by nested fields Use dot notation to sort results based on a document's nested fields. The following query sorts returned documents by their user review scores: @@ -273,44 +225,6 @@ Sorting is most useful when you want your users to be able to alter the order of Custom ranking rules, instead, establish a default sorting rule that is enforced in every search. This approach can be useful when you want to promote certain results above all others, regardless of a user's preferences. For example, you might want a webshop to always feature discounted products first, no matter what a user is searching for. -## Sorting with `_geoPoint` - -If your documents contain `_geo` data, you can use `_geoPoint` to sort results based on their distance from a geographic position. - -`_geoPoint` is a sorting function that requires two floating point numbers indicating a location's latitude and longitude. You must also specify whether the sort should be ascending (`asc`) or descending (`desc`): - -```json -{ - "sort": [ - "_geoPoint(0.0, 0.0):asc" - ] -} -``` - -Queries using `_geoPoint` will always include a `geoDistance` field containing the distance in meters between the document location and the `_geoPoint`: - -```json -[ - { - "id": 1, - "name": "Nàpiz' Milano", - "_geo": { - "lat": 45.4777599, - "lng": 9.1967508 - }, - "_geoDistance": 1532 - } -] -``` - -[You can read more about location-based sorting in our geosearch guide.](/learn/fine_tuning_results/geosearch#sorting-results-with-_geopoint) - -### Example - -The following query will sort results based on how close they are to the Eiffel Tower: - - - ## Example application Take a look at our demos for examples of how to implement sorting: diff --git a/learn/fine_tuning_results/working_with_dates.mdx b/learn/filtering_and_sorting/working_with_dates.mdx similarity index 100% rename from learn/fine_tuning_results/working_with_dates.mdx rename to learn/filtering_and_sorting/working_with_dates.mdx diff --git a/learn/fine_tuning_results/faceted_search.mdx b/learn/fine_tuning_results/faceted_search.mdx deleted file mode 100644 index 77414fb915..0000000000 --- a/learn/fine_tuning_results/faceted_search.mdx +++ /dev/null @@ -1,301 +0,0 @@ ---- -title: Faceted search — Meilisearch documentation -description: Faceted search interfaces provide users with a quick way to narrow down search results by selecting categories relevant to their query. -sidebarDepth: 3 ---- - -# Faceted search - -You can use Meilisearch filters to build faceted search interfaces. This type of interface allows users to refine search results based on broad categories or facets. Faceted search provides users with a quick way to narrow down search results by selecting categories relevant to what they are looking for. A faceted navigation system is an **intuitive interface to display and navigate through content**. - -Facets are common in ecommerce sites like Amazon. When users search for products, they are presented with a list of results and a list of facets which you can see on the sidebar in the image below: - -[![Meilisearch demo for an ecommerce website displaying faceting UI](/assets/images/faceted-search/facets-ecommerce.png)](https://ecommerce.meilisearch.com/?utm_campaign=oss&utm_source=docs&utm_medium=faceted-search&utm_content=image) - -Faceted search interfaces often have a count of how many results belong to each facet. This gives users a visual clue of the range of results available for each facet. - -### Filters or facets - -Meilisearch does not differentiate between facets and filters. Facets are a specific use-case of filters, meaning you can use any attribute added to `filterableAttributes` as a facet. Whether something is a filter or a facet depends above all on UX and UI design. - -## Configuring and using facets - -Like any other filter, you must add any attributes you want to use as facets to the [`filterableAttributes`](/reference/api/settings#filterable-attributes) list in an index's settings. Once you have configured `filterableAttributes`, you can search for facets with [the `facets` search parameter](/reference/api/search#facets). - - -Synonyms don't apply to facets. If you have `SF` and `San Francisco` set as synonyms, faceting by `SF` and `San Francisco` will show you different results. - - -Suppose you have a books dataset containing the following fields: - -```json -{ - "id":5, - "title": "Hard Times", - "genres": ["Classics","Fiction", "Victorian", "Literature"], - "publisher": "Penguin Classics", - "language": "English", - "author": "Charles Dickens", - "description":"Hard Times is a novel of social … ", - "format": "Hardcover", - "rating": 3 -} -``` - -The following code sample allows you to create facets for the `genres`, `language`, and `rating` attributes: - - - -Now, if you were to search the `books` index for `classic` using the following code sample: - - - -The response would return `classic` books along with two new fields: [`facetDistribution`](#facet-distribution) and [`facetStats`](#facet-stats): - -```json -{ - "hits":[ - … - ], - "query":"classic", - … - "facetDistribution":{ - "genres":{ - "Classics":6, - … - }, - "language":{ - "English":6, - "French":1, - "Spanish":1 - }, - "rating":{ - "2.5":1, - … - } - }, - "facetStats":{ - "rating":{ - "min":2.5, - "max":4.7 - } - } -} -``` - -### Facet distribution - -The `facetDistribution` object contains the number of matching documents distributed among the values of a given facet. Meilisearch automatically adds `facetDistribution` to the response of any query using the `facets` search parameter. - -The following response shows the facet distribution when searching for `classics`: - -```json -{ - … - "facetDistribution":{ - "genres":{ - "Classics":6, - "Comedy":1, - "Coming-of-Age":1, - "Fantasy":2, - "Fiction":8, - … - }, - "language":{ - "English":6, - "French":1, - "Spanish":1 - }, - "rating":{ - "2.5":1, - "3":2, - "3.9":1, - "4":3, - "4.7":1 - } - }, - … -} -``` - -`facetDistribution` contains an object for every attribute passed to the `facets` parameter. Each object contains the returned values for that attribute and the count of matching documents with that value. Meilisearch does not return empty facets: if there are no results for the Arabic language, it will not be present in `facetDistribution`. - - -By default, `facets` returns a maximum of 100 facet values for each faceted field. You can change this value using the `maxValuesPerFacet` property of the [`faceting` index settings](/reference/api/settings#faceting). - - -### Facet stats - -When using the `facets` parameter, search results include a `facetStats` object. `facetStats` contains the lowest (`min`) and highest (`max`) numerical values across all documents in each facet. Only numeric values are considered; string values are ignored, even if the string contains a number. - -`facetStats` is useful when creating UI components such as range sliders. These allow users to refine their search by selecting from a range of facet values. - -The following response shows the lowest and highest book ratings when searching for `"classic"`: - -```json -{ - … -"facetStats":{ - "rating":{ - "min":2.5, - "max":4.7 - } - } - … -} -``` - -If none of the matching documents have a numeric value for a facet, that facet is not included in the `facetStats` object. Since `rating` was the only numeric facet in our example, it is the only facet returned in the `facetStats` object. - -## Sorting facet values - -By default, all facet values are sorted in ascending alphanumeric order. You can change this using the `sortFacetValuesBy` property of the [`faceting` index settings](/reference/api/settings#faceting): - - - -The above code sample sorts the `genres` facet by descending value count. If you searched the `books` index for `classic` using the new settings, you would get the following response: - -```json -{ - … - "facetDistribution": { - "genres": { - "Fiction": 8, - "Literature": 7, - "Classics": 6, - "Novel": 2, - "Horror": 2, - "Fantasy": 2, - "Victorian": 2, - "Vampires": 1, - "Tragedy": 1, - "Satire": 1, - "Romance": 1, - "Historical Fiction": 1, - "Coming-of-Age": 1, - "Comedy": 1 - }, - … - } -} -``` - -## Searching facet values - -Once you have configured [filterableAttributes](/reference/api/settings#filterable-attributes), you can also search for facet values with the [facet search endpoint](/reference/api/facet_search). Facet search supports [prefix search](/learn/engine/prefix) and [typo tolerance](/learn/relevancy/typo_tolerance_settings). - - -Meilisearch does not support facet search on numbers. Convert numeric facets to strings to make them searchable. - -Internally, Meilisearch represents numbers as [`float64`](https://en.wikipedia.org/wiki/Double-precision_floating-point_format). This means they lack precision and can be represented in different ways, making it difficult to search facet values effectively. - - -The following code sample searches the `genres` facet for values starting with `c`: - - - -The response contains a `facetHits` array: - -```json -{ - "facetHits": [ - { - "value": "Children's Literature", - "count": 1 - }, - { - "value": "Classics", - "count": 6 - }, - { - "value": "Comedy", - "count": 2 - }, - { - "value": "Coming-of-Age", - "count": 1 - } - ], - "facetQuery": "c", - … -} -``` - -Each object in `facetHits` contains the following fields: - -- `value`: Facet value matching the `facetQuery` -- `count`: Number of documents with a facet value matching `value` - - -Meilisearch's facet search does not support multi-word facets and only considers the first term in the `facetQuery`. - -For example, searching for `Jane` will return `Jane Austen`, but searching for `Austen` will not return `Jane Austen`. - - -You can further refine results using the `q`, `filter`, and `matchingStrategy` parameters. [Learn more about them in the API reference.](/reference/api/facet_search) - -## Facet types - -### Conjunctive facets - -Conjunctive facets use the `AND` logical operator. When users select multiple values for a facet, returned results must contain all selected facet values. - -With conjunctive facets, when a user selects `English` from the `language` facet, all returned books must be in English. If the user further narrows down the search by selecting `Fiction` and `Literature` as `genres`, all returned books must be in English and contain both `genres`. - -``` -"language = English AND genres = Fiction AND genres = Literature" -``` - -The GIF below shows how the facet count for `genres` updates to only include books that meet **all three conditions**. - -![Selecting English books with 'Fiction' and 'Literature' as 'genres' for the books dataset](/assets/images/faceted-search/conjunctive-factes.gif) - -### Disjunctive facets - -Disjunctive facets use the `OR` logical operator. When users select multiple values for a facet, returned results must contain at least one of the selected values. - -With disjunctive facets, when a user selects `Fiction`, and `Literature`, Meilisearch returns all books that are either `Fiction`, `Literature`, or both: - -``` -"genres = Fiction OR genres = Literature" -``` - -The GIF below shows the `books` dataset with disjunctive facets. Notice how the facet count for `genres` updates based on the selection. - -![Selecting 'Fiction' and 'Literature' as 'genres' for the books dataset](/assets/images/faceted-search/disjunctive_facets.gif) - -### Combining conjunctive and disjunctive facets - -It is possible to create search queries with both conjunctive and disjunctive facets. - -For example, a user might select `English` and `French` from the `language` facet so they can see books written either in English or in French. This query uses an `OR` operator and is a disjunctive facet: - -``` -"language = English OR language = French" -``` - -The same user might also be interested in literary fiction books and select `Fiction` and `Literature` as `genres`. Since the user wants a specific combination of genres, their query uses an `AND` operator: - -``` -"genres = Fiction AND genres = Literature" -``` - -The user can combine these two filter expressions in one by wrapping them in parentheses and using an `AND` operator: - -``` -"(language = English OR language = French) AND (genres = Fiction AND genres = Literature)" -``` - -The GIF below shows the `books` dataset with conjunctive and disjunctive facets. Notice how the facet count for each facet updates based on the selection. - -![Selecting 'Fiction' and 'Literature' as 'genres' for English books](/assets/images/faceted-search/conjunctive-and-disjunctive-facets.gif) - -## Example application - -The Meilisearch ecommerce demo makes heavy use of faceting features to enable: -- Filtering products by category and brand -- Filtering products by price range and rating -- Searching through facet values (e.g. category) -- Sorting facet values (count or alphabetical order) - -Check out the [ecommerce demo](https://ecommerce.meilisearch.com/?utm_campaign=oss&utm_source=docs&utm_medium=faceted-search&utm_content=link) and the [GitHub repository](https://github.com/meilisearch/ecommerce-demo/). diff --git a/learn/fine_tuning_results/filtering.mdx b/learn/fine_tuning_results/filtering.mdx deleted file mode 100644 index 9996ff8a9e..0000000000 --- a/learn/fine_tuning_results/filtering.mdx +++ /dev/null @@ -1,390 +0,0 @@ ---- -title: Filtering — Meilisearch documentation -description: Filters allow your users to refine search results. They can also be used when creating faceted search interfaces. -sidebarDepth: 4 ---- - -# Filtering - -Filters have several use-cases, such as refining search results and creating faceted search interfaces. Faceted search interfaces are particularly efficient in helping users navigate a great number of results across many broad categories. - -## Configuring filters - -Suppose you have a collection of movies called `movie_ratings` containing the following fields: - -```json -[ - { - "id": 458723, - "title": "Us", - "director": "Jordan Peele", - "genres": [ - "Thriller", - "Horror", - "Mystery" - ], - "rating": { - "critics": 86, - "users": 73 - }, - "overview": "Husband and wife Gabe and Adelaide Wilson take their…" - }, - … -] -``` - -If you want to filter results based on the `director` and `genres` attributes, you must first add them to the `filterableAttributes` list: - - - -**This step is mandatory and cannot be done at search time**. Updating `filterableAttributes` requires Meilisearch to re-configure your index, which will take an amount of time proportionate to your dataset size and complexity. - - -By default, `filterableAttributes` is empty. Filters do not work without first explicitly adding attributes to the `filterableAttributes` list. - - -### Filters and data types - -Filters work with numeric and string values. Empty fields or fields containing an empty array will be ignored. - -Filters do not work with [`NaN`](https://en.wikipedia.org/wiki/NaN) and infinite values such as `inf` and `-inf` as they are [not supported by JSON](https://en.wikipedia.org/wiki/JSON#Data_types). It is possible to filter infinite and `NaN` values if you parse them as strings, except when handling [`_geo` fields](/learn/fine_tuning_results/geosearch#preparing-documents-for-location-based-search). - -We recommend homogeneous typing across fields, especially when dealing with large numbers. This is because Meilisearch does not enforce a specific schema when indexing data, the filtering engine will try to coerce the type of `value`. This can lead to undefined behavior when big floats are coerced into integers and reciprocally. - -## Filter basics - -Once you have designated certain attributes as `filterableAttributes`, you can use [the `filter` search parameter](/reference/api/search#filter) to filter your search according to those attributes. The `filter` search parameter refines search results by selecting documents matching the given filter and running the search query only on those documents. - -`filter` expects a **filter expression** containing one or more **conditions**. A filter expression can be written as a string, array, or mix of both. - -### Conditions - -Conditions are a filter's basic building blocks. They are written in the `attribute OPERATOR value` format, where: - -- `attribute` is the attribute of the field you want to filter on -- `OPERATOR` can be `=`, `!=`, `>`, `>=`, `<`, `<=`, `TO`, `EXISTS`, `IN`, `NOT`, `AND`, or `OR` -- `value` is the value the `OPERATOR` should look for in the `attribute` - -#### Examples - -A basic condition could request movies containing the `horror` genre: - -``` -genres = horror -``` - -String values containing whitespace must be enclosed in single or double quotes: - -``` -director = 'Jordan Peele' -director = "Tim Burton" -``` - -Another condition could request movies released after 18 March 1995 (written as `795484800` in UNIX Epoch time): - -``` -release_date > 795484800 -``` - -### Filter operators - -#### Equality - -The equality operator (`=`) returns all documents containing a specific value for a given attribute. When operating on strings, `=` is case-insensitive. - -The following expression returns all action movies: - -``` -genres = action -``` - - -The equality operator does not return any results for `null` and empty arrays. - - -#### Inequality - -The inequality operator (`!=`) returns all documents not selected by the equality operator. When operating on strings, `!=` is case-insensitive. - -The following expression returns all movies without the `action` genre: - -``` -genres != action -``` - -#### Comparison - -The comparison operators (`>`, `<`, `>=`, `<=`, `TO`) select documents satisfying a comparison. Comparison operators only apply only to numerical values. - -The expression below returns all documents with a user rating above 85: - -``` -rating.users > 85 -``` - -To filter documents with a user rating of 80 or above but below 90, you would use: - -``` -rating.users >= 80 AND rating.users < 90 -``` - -#### `TO` - -`TO` is equivalent to `>= AND <=`. The following expression returns all movies with a user rating of 80 or above but below 90: - -``` -rating.users 80 TO 89 -``` - -#### `EXISTS` - -The `EXISTS` operator checks for the existence of a field. Fields with empty or `null` values count as existing. - -The following expression returns all documents that contain the `release_date` field, even if it is empty or `null`: - -``` -release_date EXISTS -``` - -The negated form of the above expression can be written as: - -``` -release_date NOT EXISTS -NOT release_date EXISTS -``` - -Both forms are equivalent. - -#### `IS EMPTY` - -The `IS EMPTY` operator selects documents in which the specified attribute exists but contains empty values. The following expression only returns documents with an empty `overview` field: - -``` -overview IS EMPTY -``` - -`IS EMPTY` matches the following JSON values: - -- `""` -- `[]` -- `{}` - -Meilisearch does not treat `null` values as empty. To match `null` fields, use the [`IS NULL`](#is-null) operator. - -Use `NOT` to build the negated form of `IS EMPTY`. This returns documents in which the specified attribute either does not exist or does not contain empty values: - -``` -overview IS NOT EMPTY -NOT overview IS EMPTY -``` - -Both forms are equivalent. - -#### `IS NULL` - -The `IS NULL` operator selects documents in which the specified attribute exists but contains a `null` value. The following expression only returns documents with a `null` `overview` field: - -``` -overview IS NULL -``` - -Use `NOT` to build the negated form of `IS NULL`. This returns documents in which the specified attribute is either not `null` or does not contain empty values: - -``` -overview IS NOT NULL -NOT overview IS NULL -``` - -Both forms are equivalent. - -#### `IN` - -`IN` combines equality operators by taking an array of comma-separated values delimited by square brackets. It selects all documents whose chosen field contains at least one of the specified values. - -Both of the following expressions are equivalent and return all documents whose `genres` includes either `horror`, `comedy`, or both: - -``` -genres IN [horror, comedy] -genres = horror OR genres = comedy -``` - -The negated form of the above expression can be written as: - -``` -genres NOT IN [horror, comedy] -NOT genres IN [horror, comedy] -``` - -Both are equivalent and mean: - -``` -genres != horror AND genres != comedy -``` - -#### `NOT` - -The negation operator (`NOT`) selects all documents that do not satisfy a condition. It has higher precedence than `AND` and `OR`. - -The following expression will return all documents whose `genres` does not contain `horror` and documents with a missing `genres` field: - -``` -NOT genres = horror -``` - -### Filter expressions - -You can build filter expressions by grouping basic conditions using `AND` and `OR`. Filter expressions can be written as strings, arrays, or a mix of both. - -#### `AND` - -`AND` connects two conditions and only returns documents that satisfy both of them. `AND` has higher precedence than `OR`. - -The following expression returns all `horror` movies directed by `Jordan Peele`: - -``` -genres = horror AND director = 'Jordan Peele' -``` - -#### `OR` - -`OR` connects two conditions and returns results that satisfy at least one of them. - -The following expression returns either `horror` or `comedy` films: - -``` -genres = horror OR genres = comedy -``` - -#### Creating filter expressions with strings - -Meilisearch reads string expressions from left to right. You can use parentheses to ensure expressions are correctly parsed. - - -Filtering on string values is case-insensitive. - - -For instance, if you want your results to only include `comedy` and `horror` movies released after March 1995, the parentheses in the following query are mandatory: - -``` -(genres = horror OR genres = comedy) AND release_date > 795484800 -``` - -Failing to add these parentheses will cause the same query to be parsed as: - -``` -genres = horror OR (genres = comedy AND release_date > 795484800) -``` - -Translated into English, the above expression will only return comedies released after March 1995 or horror movies regardless of their `release_date`. - - -When creating an expression with a field name or value identical to a filter operator such as `AND` or `NOT`, you must wrap it in quotation marks: `title = "NOT" OR title = "AND"`. - - -#### Creating filter expressions with arrays - -Array expressions establish logical connectives by nesting arrays of strings. **Array filters can have a maximum depth of two**—expressions with three or more levels of nesting will throw an error. - -Outer array elements are connected by an `AND` operator. The following expression returns `horror` movies directed by `Jordan Peele`: - -``` -["genres = horror", "director = 'Jordan Peele'"] -``` - -Inner array elements are connected by an `OR` operator. The following expression returns either `horror` or `comedy` films: - -``` -[["genres = horror", "genres = comedy"]] -``` - -Inner and outer arrays can be freely combined. The following expression returns both `horror` and `comedy` movies directed by `Jordan Peele`: - -``` -[["genres = horror", "genres = comedy"], "director = 'Jordan Peele'"] -``` - -#### Combining arrays and strings - -You can also create filter expressions that use both array and string syntax. - -The following filter is written as a string and only returns movies not directed by `Jordan Peele` that belong to the `comedy` or `horror` genres: - -``` -"(genres = comedy OR genres = horror) AND director != 'Jordan Peele'" -``` - -You can write the same filter mixing arrays and strings: - -``` -[["genres = comedy", "genres = horror"], "NOT director = 'Jordan Peele'"] -``` - -## Using filters - -Suppose that your `movie_ratings` dataset contains several movies in the following format: - -```json -[ - … - { - "id": 458723, - "title": "Us", - "director": "Jordan Peele", - "poster": "https://image.tmdb.org/t/p/w1280/ux2dU1jQ2ACIMShzB3yP93Udpzc.jpg", - "overview": "Husband and wife Gabe and Adelaide Wilson take their…", - "release_date": 1552521600, - "genres": [ - "Comedy", - "Horror", - "Thriller" - ], - "rating": { - "critics": 86, - "users": 73 - }, - }, - … -] -``` - - -[Synonyms](/learn/relevancy/synonyms) don't apply to filters. Meaning, if you have `SF` and `San Francisco` set as synonyms, filtering by `SF` and `San Francisco` will show you different results. - - -After adding `director`, `release_date`, and `genres` to the [`filterableAttributes` index setting](//reference/api/settings#filterable-attributes), you can use them for filtering. - -The following code sample returns `Avengers` movies released after 18 March 1995: - - - -You can also combine multiple conditions. For example, you can limit your search so it only includes `Batman` movies directed by either `Tim Burton` or `Christopher Nolan`: - - - -Here, the parentheses are mandatory: without them, the filter would return movies directed by `Tim Burton` and released after 1995 or any film directed by `Christopher Nolan`, without constraints on its release date. This happens because `AND` takes precedence over `OR`. - -If you only want recent `Planet of the Apes` movies that weren't directed by `Tim Burton`, you can use this filter: - - - -`NOT director = "Tim Burton"` will include both documents that do not contain `"Tim Burton"` in its `director` field and documents without a `director` field. To return only documents that have a `director` field, expand the filter expression with the `EXISTS` operator: - -``` -release_date > 1577884550 AND (NOT director = "Tim Burton" AND director EXISTS) -``` - -### Filtering by geographic location - -If your documents contain `_geo` data, you can filter results according to their geographic position using one of our built-in geosearch filter rules: - - - -[Read more about filtering results with `_geoRadius` and `_geoBoundingBox` in our geosearch guide.](/learn/fine_tuning_results/geosearch#filtering-results-with-_georadius-and-_geoboundingbox) - -### Filtering by nested fields - -Use dot notation to filter results based on a document's nested fields. The following query only returns thrillers with good user reviews: - - - -[You can read more about nested fields in our guide on data types.](/learn/engine/datatypes) diff --git a/learn/meilisearch_101/customizing_relevancy.mdx b/learn/meilisearch_101/customizing_relevancy.mdx index ac07c33aa9..f4d746e453 100644 --- a/learn/meilisearch_101/customizing_relevancy.mdx +++ b/learn/meilisearch_101/customizing_relevancy.mdx @@ -169,7 +169,7 @@ Suppose your results contain the following values for the `genres` facet: `Actio -You can read more about faceting in our [dedicated guide](/learn/fine_tuning_results/faceted_search). +You can read more about faceting in our [dedicated guide](/learn/filtering_and_sorting/search_with_facet_filters). ## Pagination diff --git a/learn/meilisearch_101/filtering_and_sorting.mdx b/learn/meilisearch_101/filtering_and_sorting.mdx index 83d4a1fc98..1081b95ba0 100644 --- a/learn/meilisearch_101/filtering_and_sorting.mdx +++ b/learn/meilisearch_101/filtering_and_sorting.mdx @@ -56,7 +56,7 @@ Let's say you only want to view meteorites that weigh less than 200g: Filtering is intended to be combined with search queries to refine your results. -To learn more about filters and how to configure them, refer to our [dedicated guide](/learn/fine_tuning_results/filtering). +To learn more about filters and how to configure them, refer to our [dedicated guide](/learn/filtering_and_sorting/filter_search_results). ## Sorting @@ -93,7 +93,7 @@ You will see all meteorites weighing less than 200g sorted by increasing mass. T Sorting is intended to be combined with search queries to refine your results. -To learn more about sorting and how to configure it, refer to our [dedicated guide](/learn/fine_tuning_results/sorting). +To learn more about sorting and how to configure it, refer to our [dedicated guide](/learn/filtering_and_sorting/sort_search_results). ## Geosearch @@ -193,6 +193,6 @@ The following command sorts meteorites by how close they were to the Taj Mahal: This response returns an additional field, `_geoDistance`, representing the distance between the Taj Mahal and each meteorite in meters. -To learn more about geosearch and how to configure it, refer to our [dedicated guide](/learn/fine_tuning_results/geosearch). +To learn more about geosearch and how to configure it, refer to our [dedicated guide](/learn/filtering_and_sorting/geosearch). The next chapter dives deeper into the `settings` object and how you can use it to fine-tune results. diff --git a/learn/relevancy/custom_ranking_rules.mdx b/learn/relevancy/custom_ranking_rules.mdx index d682596ad4..267a48b28c 100644 --- a/learn/relevancy/custom_ranking_rules.mdx +++ b/learn/relevancy/custom_ranking_rules.mdx @@ -56,7 +56,7 @@ The following array includes all built-in ranking rules and places the custom ru ## Sorting at search time and custom ranking rules -Meilisearch allows users to define [sorting order at query time](/learn/fine_tuning_results/sorting) by using the [`sort` search parameter](/reference/api/search#sort). There is some overlap between sorting and custom ranking rules, but the two do have different uses. +Meilisearch allows users to define [sorting order at query time](/learn/filtering_and_sorting/sort_search_results) by using the [`sort` search parameter](/reference/api/search#sort). There is some overlap between sorting and custom ranking rules, but the two do have different uses. In general, `sort` will be most useful when you want to allow users to define what type of results they want to see first. A good use-case for `sort` is creating a webshop interface where customers can sort products by descending or ascending product price. diff --git a/learn/security/tenant_token_reference.mdx b/learn/security/tenant_token_reference.mdx index 91d292054d..97d2a09c48 100644 --- a/learn/security/tenant_token_reference.mdx +++ b/learn/security/tenant_token_reference.mdx @@ -39,7 +39,7 @@ The search rules object are a set of instructions defining search parameters Mei } ``` -Each search rule object may contain a single `filter` key. This `filter`'s value must be a [filter expression](/learn/fine_tuning_results/filtering#filter-expressions): +Each search rule object may contain a single `filter` key. This `filter`'s value must be a [filter expression](/learn/filtering_and_sorting/filter_expression_reference): ```json { diff --git a/learn/update_and_migration/updating.mdx b/learn/update_and_migration/updating.mdx index 66ed32f85d..9159838282 100644 --- a/learn/update_and_migration/updating.mdx +++ b/learn/update_and_migration/updating.mdx @@ -149,7 +149,7 @@ It should return something like this: _geo field in v0.27, v0.28, and v0.29}> -Due to an error allowing malformed `_geo` fields in Meilisearch **v0.27, v0.28, and v0.29**, you might not be able to import your dump. Please ensure the `_geo` field follows the [correct format](/learn/fine_tuning_results/geosearch#preparing-documents-for-location-based-search) before creating your dump. +Due to an error allowing malformed `_geo` fields in Meilisearch **v0.27, v0.28, and v0.29**, you might not be able to import your dump. Please ensure the `_geo` field follows the [correct format](/learn/filtering_and_sorting/geosearch#preparing-documents-for-location-based-search) before creating your dump. You can then create a dump of your database: diff --git a/learn/what_is_meilisearch/overview.mdx b/learn/what_is_meilisearch/overview.mdx index 1ccab6dc4a..992ef19f96 100644 --- a/learn/what_is_meilisearch/overview.mdx +++ b/learn/what_is_meilisearch/overview.mdx @@ -24,17 +24,17 @@ _Meilisearch helps you find where to watch a movie at [where2watch.meilisearch.c - [Comprehensive language support](/learn/what_is_meilisearch/language): Optimized support for **Chinese, Japanese, Hebrew, and languages using the Latin alphabet** - **Returns the whole document**: The entire document is returned upon search - **Highly customizable search and indexing**: Customize search behavior to better meet your needs - - [Custom ranking](/learn/relevancy/relevancy): Customize the relevancy of the search engine and the ranking of the search results - - [Filtering](/learn/fine_tuning_results/filtering) and [faceted search](/learn/fine_tuning_results/faceted_search): Enhance user search experience with custom filters and build a faceted search interface in a few lines of code - - [Highlighting](/reference/api/search#highlight-tags): Highlighted search results in documents - - [Stop words](/reference/api/settings#stop-words): Ignore common non-relevant words like `of` or `the` - - [Synonyms](/reference/api/settings#synonyms): Configure synonyms to include more relevant content in your search results +- [Custom ranking](/learn/relevancy/relevancy): Customize the relevancy of the search engine and the ranking of the search results +- [Filtering](/learn/filtering_and_sorting/filter_search_results) and [faceted search](/learn/filtering_and_sorting/search_with_facet_filters): Enhance user search experience with custom filters and build a faceted search interface in a few lines of code +- [Highlighting](/reference/api/search#highlight-tags): Highlighted search results in documents +- [Stop words](/reference/api/settings#stop-words): Ignore common non-relevant words like `of` or `the` +- [Synonyms](/reference/api/settings#synonyms): Configure synonyms to include more relevant content in your search results - **RESTful API**: Integrate Meilisearch in your technical stack with our plugins and SDKs - [Search preview](/learn/getting_started/search_preview): Allows you to test your search settings without implementing a front-end - [API key management](/learn/security/basic_security): Protect your instance with API keys. Set expiration dates and control access to indexes and endpoints so that your data is always safe - [Multitenancy and tenant tokens](/learn/security/multitenancy_tenant_tokens): Manage complex multi-user applications. Tenant tokens help you decide which documents each one of your users can search - [Multi-search](/reference/api/multi_search): Perform multiple search queries on multiple indexes with a single HTTP request -- [Geosearch](/learn/fine_tuning_results/geosearch): Filter and sort results based on their geographic location +- [Geosearch](/learn/filtering_and_sorting/geosearch): Filter and sort results based on their geographic location - [Index swapping](/learn/core_concepts/indexes#swapping-indexes): Deploy major database updates with zero search downtime ## Philosophy diff --git a/reference/api/documents.mdx b/reference/api/documents.mdx index 9167ccc35b..23ffd71ca9 100644 --- a/reference/api/documents.mdx +++ b/reference/api/documents.mdx @@ -18,7 +18,7 @@ Get a set of documents. Use `offset` and `limit` to browse through documents. -`filter` will not work without first explicitly adding attributes to the [`filterableAttributes` list](/reference/api/settings#update-filterable-attributes). [Learn more about filters in our dedicated guide.](/learn/fine_tuning_results/filtering#filter-basics) +`filter` will not work without first explicitly adding attributes to the [`filterableAttributes` list](/reference/api/settings#update-filterable-attributes). [Learn more about filters in our dedicated guide.](/learn/filtering_and_sorting/filter_search_results#filter-basics) ### Path parameters @@ -97,10 +97,10 @@ This endpoint will be deprecated in the near future. Consider using POST `/index Get a set of documents. -Using the query parameters `offset` and `limit`, you can browse through all your documents.`filter` must be a string. To create [filter expressions](/learn/fine_tuning_results/filtering#filter-expressions) use `AND` or `OR`. +Using the query parameters `offset` and `limit`, you can browse through all your documents.`filter` must be a string. To create [filter expressions](/learn/filtering_and_sorting/filter_expression_reference) use `AND` or `OR`. -`filter` will not work without first explicitly adding attributes to the [`filterableAttributes` list](/reference/api/settings#update-filterable-attributes). [Learn more about filters in our dedicated guide.](/learn/fine_tuning_results/filtering#filter-basics) +`filter` will not work without first explicitly adding attributes to the [`filterableAttributes` list](/reference/api/settings#update-filterable-attributes). [Learn more about filters in our dedicated guide.](/learn/filtering_and_sorting/filter_search_results#filter-basics) ### Path parameters @@ -468,7 +468,7 @@ Delete a set of documents based on a filter. A filter expression written as a string or array of array of strings for the documents to be deleted. -`filter` will not work without first explicitly adding attributes to the [`filterableAttributes` list](/reference/api/settings#update-filterable-attributes). [Learn more about filters in our dedicated guide.](/learn/fine_tuning_results/filtering#filter-basics) +`filter` will not work without first explicitly adding attributes to the [`filterableAttributes` list](/reference/api/settings#update-filterable-attributes). [Learn more about filters in our dedicated guide.](/learn/filtering_and_sorting/filter_search_results#filter-basics) ``` diff --git a/reference/api/facet_search.mdx b/reference/api/facet_search.mdx index c671e821b4..69279e2bed 100644 --- a/reference/api/facet_search.mdx +++ b/reference/api/facet_search.mdx @@ -20,7 +20,7 @@ Search for a facet value within a given facet. -This endpoint will not work without first explicitly adding attributes to the [`filterableAttributes`](/reference/api/settings#update-filterable-attributes) list. [Learn more about facets in our dedicated guide.](/learn/fine_tuning_results/faceted_search#configuring-and-using-facets) +This endpoint will not work without first explicitly adding attributes to the [`filterableAttributes`](/reference/api/settings#update-filterable-attributes) list. [Learn more about facets in our dedicated guide.](/learn/filtering_and_sorting/search_with_facet_filters) @@ -36,7 +36,7 @@ For example, searching for `Jane` will return `Jane Austen`, but searching for ` | **`facetName`** * | String | `null` | Facet name to search values on | | **`facetQuery`** | String | `null` | Search query for a given facet value. If `facetQuery` isn't specified, Meilisearch performs a [placeholder search](/reference/api/search#placeholder-search) which returns all facet values for the searched facet, limited to 100 | | [**`q`**](/reference/api/search#query-q) | String | `""` | Query string | -| **[`filter`](/reference/api/search#filter)** | [String*](/learn/fine_tuning_results/filtering#filter-expressions) | `null` | Filter queries by an attribute's value | +| **[`filter`](/reference/api/search#filter)** | [String*](/learn/filtering_and_sorting/filter_expression_reference) | `null` | Filter queries by an attribute's value | | **[`matchingStrategy`](/reference/api/search#matching-strategy)** | String | `last` | Strategy used to match query terms within documents | | **[`attributesToSearchOn`](/reference/api/search##customize-attributes-to-search-on-at-search-time)** | Array of strings | `null` | Restrict search to the specified attributes | diff --git a/reference/api/multi_search.mdx b/reference/api/multi_search.mdx index 1403b6e685..2adeb1be7d 100644 --- a/reference/api/multi_search.mdx +++ b/reference/api/multi_search.mdx @@ -33,7 +33,7 @@ If Meilisearch encounters an error when handling any of the queries in a multi-s | **[`limit`](/reference/api/search#limit)** | Integer | `20` | Maximum number of documents returned | | **[`hitsPerPage`](/reference/api/search#number-of-results-per-page)** | Integer | `1` | Maximum number of documents returned for a page | | **[`page`](/reference/api/search#page)** | Integer | `1` | Request a specific page of results | -| **[`filter`](/reference/api/search#filter)** | [String](/learn/fine_tuning_results/filtering#filter-expressions) | `null` | Filter queries by an attribute's value | +| **[`filter`](/reference/api/search#filter)** | [String](/learn/filtering_and_sorting/filter_expression_reference) | `null` | Filter queries by an attribute's value | | **[`facets`](/reference/api/search#facets)** | Array of strings | `null` | Display the count of matches per facet | | **[`attributesToRetrieve`](/reference/api/search#attributes-to-retrieve)** | Array of strings | `["*"]` | Attributes to display in the returned documents | | **[`attributesToCrop`](/reference/api/search#attributes-to-crop)** | Array of strings | `null` | Attributes whose values have to be cropped | diff --git a/reference/api/search.mdx b/reference/api/search.mdx index 0b3500ee56..fd60bbb153 100644 --- a/reference/api/search.mdx +++ b/reference/api/search.mdx @@ -40,7 +40,7 @@ By default, [this endpoint returns a maximum of 1000 results](/learn/advanced/kn | **[`limit`](#limit)** | Integer | `20` | Maximum number of documents returned | | **[`hitsPerPage`](#number-of-results-per-page)** | Integer | `1` | Maximum number of documents returned for a page | | **[`page`](#page)** | Integer | `1` | Request a specific page of results | -| **[`filter`](/reference/api/search#filter)** | [String](/learn/fine_tuning_results/filtering#filter-expressions) | `null` | Filter queries by an attribute's value | +| **[`filter`](/reference/api/search#filter)** | [String](/learn/filtering_and_sorting/filter_expression_reference) | `null` | Filter queries by an attribute's value | | **[`facets`](#facets)** | Array of strings | `null` | Display the count of matches per facet | | **[`attributesToRetrieve`](#attributes-to-retrieve)** | Array of strings | `["*"]` | Attributes to display in the returned documents | | **[`attributesToCrop`](#attributes-to-crop)** | Array of strings | `null` | Attributes whose values have to be cropped | @@ -129,7 +129,7 @@ You can [read more about pagination in our dedicated guide](/guides/front_end/pa Search for documents matching a specific query in the given index. -This endpoint only accepts [string filter expressions](/learn/fine_tuning_results/filtering#filter-expressions). +This endpoint only accepts [string filter expressions](/learn/filtering_and_sorting/filter_expression_reference). This endpoint should only be used when no API key is required. If an API key is required, use the [POST](/reference/api/search#search-in-an-index-with-post) route instead. @@ -153,7 +153,7 @@ By default, [this endpoint returns a maximum of 1000 results](/learn/advanced/kn | **[`limit`](#limit)** | Integer | `20` | Maximum number of documents returned | | **[`hitsPerPage`](#number-of-results-per-page)** | Integer | `1` | Maximum number of documents returned for a page | | **[`page`](#page)** | Integer | `1` | Request a specific page of results | -| **[`filter`](/reference/api/search#filter)** | [String](/learn/fine_tuning_results/filtering#filter-expressions) | `null` | Filter queries by an attribute's value | +| **[`filter`](/reference/api/search#filter)** | [String](/learn/filtering_and_sorting/filter_expression_reference) | `null` | Filter queries by an attribute's value | | **[`facets`](#facets)** | Array of strings | `null` | Display the count of matches per facet | | **[`attributesToRetrieve`](#attributes-to-retrieve)** | Array of strings | `["*"]` | Attributes to display in the returned documents | | **[`attributesToCrop`](#attributes-to-crop)** | Array of strings | `null` | Attributes whose values have to be cropped | @@ -315,7 +315,7 @@ When `q` isn't specified, Meilisearch performs a **placeholder search**. A plac If the index has no sort or custom ranking rules, the results are returned in the order of their internal database position. -Placeholder search is particularly useful when building a [faceted search interfaces](/learn/fine_tuning_results/faceted_search), as it allows users to view the catalog and alter sorting rules without entering a query. +Placeholder search is particularly useful when building a [faceted search interfaces](/learn/filtering_and_sorting/search_with_facet_filters), as it allows users to view the catalog and alter sorting rules without entering a query. #### Phrase search @@ -450,7 +450,7 @@ The following example returns the second page of search results: Uses filter expressions to refine search results. Attributes used as filter criteria must be added to the [`filterableAttributes` list](/reference/api/settings#filterable-attributes). -For more information, [read our guide on how to use filters and build filter expressions](/learn/fine_tuning_results/filtering). +For more information, [read our guide on how to use filters and build filter expressions](/learn/filtering_and_sorting/filter_search_results). #### Example @@ -518,7 +518,9 @@ Returns the number of documents matching the current search query for each given - An array of attributes: `facets=["attributeA", "attributeB", …]` - An asterisk—this will return a count for all facets present in `filterableAttributes` -When `facets` is set, the search results object contains the [`facetDistribution`](#facetdistribution) and [`facetStats`](#facetstats) fields. +By default, `facets` returns a maximum of 100 facet values for each faceted field. You can change this value using the `maxValuesPerFacet` property of the [`faceting` index settings](/reference/api/settings#faceting). + +When `facets` is set, the search results object includes the [`facetDistribution`](#facetdistribution) and [`facetStats`](#facetstats) fields. If an attribute used on `facets` has not been added to the `filterableAttributes` list, it will be ignored. @@ -526,12 +528,48 @@ If an attribute used on `facets` has not been added to the `filterableAttributes #### `facetDistribution` -`facetDistribution` contains the number of matching documents distributed among the values of a given facet. Each facet is represented as an object. +`facetDistribution` contains the number of matching documents distributed among the values of a given facet. Each facet is represented as an object: + +```json +{ + … + "facetDistribution": { + "FACET_A": { + "FACET_VALUE_X": 6, + "FACET_VALUE_Y": 1, + }, + "FACET_B": { + "FACET_VALUE_Z": 3, + "FACET_VALUE_W": 9, + }, + }, + … +} +``` + +`facetDistribution` contains an object for every attribute passed to the `facets` parameter. Each object contains the returned values for that attribute and the count of matching documents with that value. Meilisearch does not return empty facets. + + + #### `facetStats` -When using the `facets` parameter, any matching documents with facets containing numeric values are displayed in a `facetStats` object. `facetStats` contains the numeric minimum (`min`) and maximum (`max`) values per facet for all documents matching the search query. -If none of the matching documents have a numeric value for a facet, that facet is not included in the `facetStats` object. +`facetStats` contains the lowest (`min`) and highest (`max`) numerical values across all documents in each facet. Only numeric values are considered: + +```json +{ + … +"facetStats":{ + "rating":{ + "min":2.5, + "max":4.7 + } + } + … +} +``` + +If none of the matching documents have a numeric value for a facet, that facet is not included in the `facetStats` object. `facetStats` ignores string values, even if the string contains a number. #### Example @@ -568,7 +606,7 @@ The response shows the facet distribution for `genres` and `rating`. Since `rati } ``` -[Learn more about facet distribution in the faceted search guide.](/learn/fine_tuning_results/faceted_search#configuring-and-using-facets) +[Learn more about facet distribution in the faceted search guide.](/learn/filtering_and_sorting/search_with_facet_filters) ### Distinct attributes at search time @@ -868,7 +906,7 @@ When using the `POST` route, `sort` expects an array of strings. When using the `GET` route, `sort` expects the list as a comma-separated string. -[Read more about sorting search results in our dedicated guide.](/learn/fine_tuning_results/sorting) +[Read more about sorting search results in our dedicated guide.](/learn/filtering_and_sorting/sort_search_results) #### Example @@ -900,7 +938,7 @@ Queries using `_geoPoint` will always include a `geoDistance` field containing t ] ``` -[You can read more about location-based sorting in our dedicated guide.](/learn/fine_tuning_results/geosearch#sorting-results-with-_geopoint) +[You can read more about location-based sorting in our dedicated guide.](/learn/filtering_and_sorting/geosearch#sorting-results-with-_geopoint) ### Matching strategy @@ -1039,7 +1077,7 @@ The `sort` ranking rule does not appear as a single field in the score details o - `order`: order in which this ranking rule was applied - `value`: value of the field used for sorting -- `distance`: same as [_geoDistance](/learn/fine_tuning_results/geosearch#finding-the-distance-between-a-document-and-a-_geopoint) +- `distance`: same as [_geoDistance](/learn/filtering_and_sorting/geosearch#finding-the-distance-between-a-document-and-a-_geopoint) ##### `vectorSort(target_vector)` diff --git a/reference/api/settings.mdx b/reference/api/settings.mdx index f25e6441a7..8102ea86a0 100644 --- a/reference/api/settings.mdx +++ b/reference/api/settings.mdx @@ -550,12 +550,12 @@ You can use this `taskUid` to get more details on [the status of the task](/refe ## Faceting -With Meilisearch, you can create [faceted search interfaces](/learn/fine_tuning_results/faceted_search). This setting allows you to: +With Meilisearch, you can create [faceted search interfaces](/learn/filtering_and_sorting/search_with_facet_filters). This setting allows you to: - Define the maximum number of values returned by the `facets` search parameter - Sort facet values by value count or alphanumeric order -[To learn more about faceting, refer to our dedicated guide.](/learn/fine_tuning_results/faceted_search) +[To learn more about faceting, refer to our dedicated guide.](/learn/filtering_and_sorting/search_with_facet_filters) ### Faceting object @@ -682,7 +682,7 @@ Attributes in the `filterableAttributes` list can be used as filters or facets. Updating filterable attributes will re-index all documents in the index, which can take some time. We recommend updating your index settings first and then adding documents as this reduces RAM consumption. -[To learn more about filterable attributes, refer to our dedicated guide.](/learn/fine_tuning_results/filtering) +[To learn more about filterable attributes, refer to our dedicated guide.](/learn/filtering_and_sorting/filter_search_results) ### Get filterable attributes @@ -736,7 +736,7 @@ If an attribute contains an object, you can use dot notation to set one or more If the field does not exist, no error will be thrown. -[To learn more about filterable attributes, refer to our dedicated guide.](/learn/fine_tuning_results/filtering) +[To learn more about filterable attributes, refer to our dedicated guide.](/learn/filtering_and_sorting/filter_search_results) #### Example @@ -1553,7 +1553,7 @@ Attributes that can be used when sorting search results using the [`sort` search Updating sortable attributes will re-index all documents in the index, which can take some time. We recommend updating your index settings first and then adding documents as this reduces RAM consumption. -[To learn more about sortable attributes, refer to our dedicated guide.](/learn/fine_tuning_results/sorting) +[To learn more about sortable attributes, refer to our dedicated guide.](/learn/filtering_and_sorting/sort_search_results) ### Get sortable attributes @@ -1586,7 +1586,7 @@ Get the sortable attributes of an index. Update an index's sortable attributes list. -[You can read more about sorting at query time on our dedicated guide.](/learn/fine_tuning_results/sorting) +[You can read more about sorting at query time on our dedicated guide.](/learn/filtering_and_sorting/sort_search_results) #### Path parameters @@ -1608,7 +1608,7 @@ If an attribute contains an object, you can use dot notation to set one or more If the field does not exist, no error will be thrown. -[To learn more about sortable attributes, refer to our dedicated guide.](/learn/fine_tuning_results/sorting) +[To learn more about sortable attributes, refer to our dedicated guide.](/learn/filtering_and_sorting/sort_search_results) #### Example diff --git a/reference/errors/error_codes.mdx b/reference/errors/error_codes.mdx index c9f446077c..229da30606 100644 --- a/reference/errors/error_codes.mdx +++ b/reference/errors/error_codes.mdx @@ -159,7 +159,7 @@ This error occurs if: - It should be a string, array of strings, or array of array of strings for the [get documents with POST endpoint](/reference/api/documents#get-documents-with-post) - It should be a string for the [get documents with GET endpoint](/reference/api/documents#get-documents-with-get) - The attribute used for filtering is not defined in the [`filterableAttributes` list](/reference/api/settings#filterable-attributes) -- The [filter expression](/learn/fine_tuning_results/filtering#filter-expressions) has a missing or invalid operator. [Read more about our supported operators](/learn/fine_tuning_results/filtering#filter-operators) +- The [filter expression](/learn/filtering_and_sorting/filter_expression_reference) has a missing or invalid operator. [Read more about our supported operators](/learn/filtering_and_sorting/filter_expression_reference) ## `invalid_document_limit` @@ -171,7 +171,7 @@ The [`offset`](/reference/api/documents#query-parameters) parameter is invalid. ## `invalid_document_geo_field` -The provided `_geo` field of one or more documents is invalid. Meilisearch expects `_geo` to be an object with two fields, `lat` and `lng`, each containing geographic coordinates expressed as a string or floating point number. Read more about `_geo` and how to troubleshoot it in [our dedicated guide](/learn/fine_tuning_results/geosearch). +The provided `_geo` field of one or more documents is invalid. Meilisearch expects `_geo` to be an object with two fields, `lat` and `lng`, each containing geographic coordinates expressed as a string or floating point number. Read more about `_geo` and how to troubleshoot it in [our dedicated guide](/learn/filtering_and_sorting/geosearch). ## `invalid_facet_search_facet_name`