Guides / Managing results / Refine results / Filtering

Filters can work with strings, numbers, booleans, dates, tags, or lists.

Filter by string

Example dataset

Algolia lets you filter search results by string attributes. For example, users of an online bookstore might want to search for books from different publishers. With filters, they can refine results by:

  • Showing books published by Penguin
  • Showing books published by Bloomsbury or Scribe
  • Showing all books except those published by Penguin

Apply a string filter

Set author as an attribute for faceting, then apply your string filters with the filters parameter in your search code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Published by Penguin
$results = $index->search('books', [
  'filters' => 'publisher:Penguin'
]);

// Published by Bloomsbury or Scribe
$results2 = $index->search('books', [
  'filters' => 'publisher:Bloomsbury OR publisher:Scribe'
]);

// Everything but Penguin books
$results3 = $index->search('books', [
  'filters' => 'NOT publisher:Penguin'
]);

Filter by numeric value

Algolia lets you numerically filter results with a comparison or a range. This only works with numeric values. For example, you could allow users to only show books that cost less than a certain price or those in a specific price range.

The price attribute is a numeric attribute, not a string attribute.

Apply a numeric filter

Example dataset

Using the example dataset, you’ve decided to let users define a price limit. For example, they may only want books that cost less than $10:

1
2
3
$results = $index->search('books', [
  'filters' => 'price < 10'
]);

Algolia filters use an SQL-like syntax, which lets you use comparison operator attributes: <, <=, =, !=, >=, and >.

To allow users to retrieve books between a range, say $10 and $20, set a range filter:

1
2
3
$results = $index->search('query', [
  'filters' => 'price:10 TO 20'
]);

Filter by date

Example dataset

As well as sorting, you can use dates to filter search results within a specific period. For example, you can allow users to filter on recently published books or only see books published within a certain period.

Format your dates suitably

Algolia can filter on date attributes, but they must be formatted as Unix timestamps. For more information, see Formatting dates

Instead of changing the date attribute, you could add an additional timestamp attribute. In the example dataset, the publication_date attribute has the formatted date for display, while the date_timestamp attribute can be used for filtering.

Apply a date filter

With dates represented as Unix timestamp, use the filters parameter to only retrieve some results. For example:

Recently published books

If you want users to filter for recent books, first decide what recent means to you. For example, a recent book might be a book published less than a year ago. This means you must set a filter that excludes records with date_timestamp greater than now minus one year.

1
2
3
4
5
$dateTimestamp = strtotime('-1 years');

$results = $index->search('YourSearchQuery', [
  'filters' => "date_timestamp > $dateTimestamp"
]);

Algolia filters use an SQL-like syntax, which lets you use comparison operators: <, <=, =, !=, >=, and >.

Books for a particular year

If you want to only retrieve books from 2018, set a range filter and provide it with Unix timestamps for the first and last day of the year:

1
2
3
$results = $index->search('YourSearchQuery', [
  'filters' => 'date_timestamp:1514764800 TO 1546300799'
]);

If you want to exclude a particular year or search for all books published outside a specific time you can combine time periods with the NOT boolean operator:

1
2
3
$results = $index->search('YourSearchQuery', [
  'filters' => 'NOT date_timestamp:1514764800 TO 1546300799'
]);

Closest dates

If your index contains books that will be published in the future, it can be helpful to sort results from sooner to later, so that users will see the next published books first.

First, sort records by ascending date so that books due to be published later sit lower in the search results:

1
2
3
4
5
6
7
8
9
10
11
12
13
$index->setSettings([
  'ranking' => [
    'asc(date_timestamp)',
    'typo',
    'geo',
    'words',
    'filters',
    'proximity',
    'attribute',
    'exact',
    'custom'
  ]
]);

Then, filter out every record with past dates:

1
2
3
4
5
$nowTimestamp = time();

$results = $index->search('YourSearchQuery', [
  'filters' => "date_timestamp >= $nowTimestamp"
]);

Filter by array

Example dataset

Some attributes, such as the genre of a book, are lists of values. One book can belong to multiple genres. Hence, the genre attribute should be an array.

If you have a chain of bookstores with an accompanying ecommerce website, you may want to let users filter by book genre and store. To do this, the example dataset has two array attributes: store and categories.

Using this dataset, users could, for example, retrieve all books about politics in stock in The Corner Bookshop.

Apply an array filter

Once you’ve set categories and store as attributes for faceting, apply string filters with the filters parameter in your search code:

1
2
3
$results = $index->search('ben', [
  'filters' => 'categories:politics AND store:Gibert Joseph Saint-Michel'
]);

Filter by boolean

Example dataset

Algolia lets you filter results by boolean attributes.

For example, you can use the is_available boolean attribute in the example dataset to exclude all records where is_available is false. To do this, first declare is_available as an attribute for faceting.

Apply a boolean filter

If you want users to see only the available books, do the following:

1
2
3
$results = $index->search('books', [
  'filters' => 'is_available:true'
]);

The engine considers booleans as integers: false as 0 and true as 1. This means you can apply numeric filters for boolean attributes. With the example dataset, is_available=0 is the same as is_available:false.

If creating numeric or boolean filters, you don’t need to declare the attribute as attributesForFaceting.

Filter by tags

Example dataset

Sometimes, you may want to filter search results based on specific metadata, like a type or a category.

Using the example dataset, the accompanying online bookstore has fiction and non-fiction sections. Depending on which section users are searching from, you can provide a context-sensitive search experience. For example, a user goes to the website’s non-fiction section, then starts searching for the biography of President Harry S. Truman. If your search relevance is primarily based on popularity, by typing “harry”, they might retrieve Harry Potter books first, which wouldn’t make sense to them.

Instead, what you can do is filter results based on what they most likely want to find. Algolia lets you add tags to your records with the reserved _tags attribute.

Using the example dataset, if users type “harry” with the search restricted to “non-fiction”, it would retrieve “Where the Buck Stops” because it has “non-fiction” in the _tags attribute and contains the word “harry” in the record.

1
2
3
$results = $index->search('harry', [
  'filters' => 'non-fiction' // Same as '_tags:non-fiction'
]);

If you don’t specify an attribute name, the filter is assumed to apply to the _tags attribute. For example, fiction translates into _tags:fiction.

You can also use tagFilters to do the same thing.

The difference between _tags and custom attributes

It’s important to consider the following when deciding whether to use the Algolia _tags attribute or a custom attribute for faceting:

  • _tags is a reserved attribute which means it automatically works as a string filter without you having to set it as an attribute for faceting or use the filterOnly modifier.
  • _tags isn’t searchable by default.
  • You can’t use _tags for non-filtering purposes, such as displaying in search results or computing counts of records that match the filters.
  • _tags can only contain strings.

In short, if you have several types of string filters or any non-string filters, creating a custom attribute is usually the way to go.

Filter by null or missing attributes

Since Algolia doesn’t support filtering on null values or missing attributes, what happens when your index contains an attribute that isn’t present in all records? For example, consider an online bookstore where people can buy and rate books from 0 to 5. Any record without the rating attribute is assumed to be unrated. If you want users to search for both rated and unrated books in the same filter, you must modify your data. To do this, you can take one of two approaches:

Create a tag

Example dataset

At indexing time, you can add a tag value to indicate if a record is or isn’t rated. In the example dataset, some records have a rating attribute and value, others have a null rating, and some don’t have a rating attribute.

A null or nonexistent attribute is different from zero, which represents a book with the lowest rating.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
  {
    // ...
    "rating": 5,
    "_tags": ["is_rated"]
  },
  {
    // ...
    "rating": null,
    "_tags": ["is_not_rated"]
  },
  {
    // ...
    "_tags": ["is_not_rated"]
  }
]

To search for records without the attribute or have a null value, you can now use tags filtering.

Create a boolean attribute

At indexing time, you can add a boolean value to indicate if a record is or isn’t rated:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
  {
    // ...
    "rating": 5,
    "is_rated": true
  },
  {
    // ...
    "rating": null,
    "is_rated": false
  },
  {
    // ...
    "is_rated": false
  }
]

To search for records without the attribute or have a null value, you can now use boolean filtering.

Filter by objectID

By default, the engine sets a record’s objectID attribute as a filter-only facet. This means you can use the filters parameter to filter on objectID. This is helpful when you want to include or exclude specific records in the current search. For example, to exclude the record with objectID “1234”, use the filter NOT objectID:1234 in the filters parameter of your search.

Example dataset

All the examples on this page use a bookstore index: books. The index has records that look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
[
  {
    "title": "Harry Potter and the Philosopher's Stone",
    "author": "J. K. Rowling",
    "publisher": "Bloomsbury",
    "price": 7.94,
    "publication_date": "1996-06-17",
    "date_timestamp": 866505600,
    "is_available": true,
    "rating": 5,
    "_tags": [
      "fiction",
      "is_rated"
    ],
    "popularity": 1000,
    "store": [
      "The Corner Bookshop",
      "Gibert Joseph Barbès",
      "Gibert Joseph Paris 13 - Grande Bibliothèque"
    ],
    "categories": [
      "fantasy",
      "science fiction",
      "children's literature"
    ]
  },
  {
    "title": "A Perfect Crime",
    "author": "Peter Abrahams",
    "publisher": "Penguin",
    "price": 7.94,
    "publication_date": "1998-09-16",
    "date_timestamp": 905904000,
    "is_available": true,
    "rating": null,
    "_tags": [
      "fiction",
      "is_not_rated"
    ],
    "popularity": 800,
    "store": [
      "The Corner Bookshop",
      "Gibert Joseph Barbès"
    ],
    "categories": [
      "thriller",
      "crime fiction"
    ]
  },
  {
    "title": "The World as It Is",
    "author": "Ben Rhodes",
    "publisher": "Penguin",
    "price": 9.54,
    "publication_date": "2018-06-05",
    "date_timestamp": 1528156800,
    "is_available": false,
    "_tags": [
      "non-fiction",
      "is_not_rated"
    ],
    "popularity": 900,
    "store": [
      "The Corner Bookshop"
    ],
    "categories": [
      "history",
      "politics"
    ]
  },
  {
    "title": "Yellowface",
    "author": "R.F. Kuang",
    "publisher": "The Borough Press",
    "price": 9.19,
    "publication_date": "2023-05-16",
    "date_timestamp": 1684108800,
    "is_available": true,
    "_tags": [
      "fiction",
      "is_not_rated"
    ],
    "popularity": 900,
    "store": [
      "The Corner Bookshop"
    ],
    "categories": [
      "dark humor",
      "satire"
    ]
  },
  {
    "title": "A Fighting Chance",
    "author": "Elizabeth Warren",
    "publisher": "Scribe",
    "price": 12.97,
    "publication_date": "2014-04-22",
    "date_timestamp": 1398124800,
    "is_available": false,
    "rating": 5,
    "_tags": [
      "non-fiction",
      "is_rated"
    ],
    "popularity": 800,
    "store": [
      "The Corner Bookshop"
    ],
    "categories": [
      "history",
      "politics"
    ]
  },
  {
    "title": "Where the Buck Stops",
    "author": "Harry S Truman",
    "publisher": "Warner Books",
    "price": 15.014,
    "publication_date": "1990-10-01",
    "date_timestamp": 654739200,
    "is_available": true,
    "_tags": [
      "non-fiction",
      "is_not_rated"
    ],
    "popularity": 800,
    "store": [
      "The Corner Bookshop"
    ],
    "categories": [
      "history",
      "politics",
      "biography"
    ]
  },
]