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:

    [
      {
        "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:

    curl \
      -X PUT 'http://localhost:7700/indexes/movie_ratings/settings/filterable-attributes' \
      -H 'Content-Type: application/json' \
      --data-binary '[
        "genres",
        "director",
        "release_date",
        "ratings"
      ]'

    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.

    NOTE

    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, 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 built using any attributes present in the filterableAttributes list.

    The following code sample returns Avengers movies released after 18 March 1995:

    curl \
      -X POST 'http://localhost:7700/indexes/movie_ratings/search' \
      -H 'Content-Type: application/json' \
      --data-binary '{
        "q": "Avengers",
        "filter": "release_date > 795484800"
      }'

    Use dot notation to filter results based on a document's nested fields. The following query only returns thrillers with good user reviews:

    curl \
      -X POST 'http://localhost:7700/indexes/movie_ratings/search' \
      -H 'Content-Type: application/json' \
      --data-binary '{
        "q": "thriller",
        "filter": "rating.users >= 90"
      }'

    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:

    curl \
      -X POST 'http://localhost:7700/indexes/movie_ratings/search' \
      -H 'Content-Type: application/json' \
      --data-binary '{
        "q": "Batman",
        "filter": "release_date > 795484800 AND (director = \"Tim Burton\" OR director = \"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:

    curl \
      -X POST 'http://localhost:7700/indexes/movie_ratings/search' \
      -H 'Content-Type: application/json' \
      --data-binary '{
        "q": "Planet of the Apes",
        "filter": "release_date > 1577884550 AND (NOT director = \"Tim Burton\")"
      }' \

    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)
    
    WARNING

    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.