Icon searching white

Filtering

Last updated 18 October 2017

Filter Overview

Filters allow you to limit the results returned to a specific subset of your data. In terms of user experience, providing filters enables users to drill down and further refine their search based off certain attribute values. Algolia permits you to filter your data in a wide variety of ways.

Basic filtering

Results can be filtered using the filters parameter. There are 3 kinds of filters:

Additionally, if a filtered attribute contains an array of values, any matching value within the array will cause the filter to match.

We will discuss in more detail these categories below, but first: How to use them.

At the most basic level:

  • Filtering is based on the attributes that you create during index time.
  • Non-numeric attributes (e.g. strings) need to be set up as categories, which we call facets. This means you will need to add them to the attributesForFaceting parameter.
  • Numeric attributes, on the other hand, can be filtered without being added as facets - they need only be set up as attributes.
  • Tags need to be set up using the _tags element and can be filtered using either the filters or tagFilters parameter.

Example

If a user wants to search books, you create a productType attribute in your index and then restrict the search to books.

index.search({
  filters: 'productType:book'
});

Or maybe the user wants to search books and DVDs.

index.search({
  filters: 'productType:book OR productType:dvd'
});

Maybe only science fiction.

index.search({
  filters: '(productType:book OR productType:dvd) AND genre:"sci-fi"'
});

Low-cost sci-fi.

index.search({
  filters: '(productType:book OR productType:dvd) AND genre:"sci-fi" AND price < 10'
});

How to format your data to be used as filters

For the above queries to work, you’ll need to create the attributes productType, genre, and price, and then define them as attributesForFaceting.

For creating attributes, check out our indexing overview.

For setting up attributes for faceting, go to our faceting overview.

How to format attributes filters

Adding attributes is as simple as pushing structured data (here, json format) to your index:

var objects = [
  {
    "objectID": "1",
    "title": "2001: A Space Odyssey",
    "productType": "book",
    "genre": "sci-fi",
    "price": 10
  },
  {
    "objectID": "2",
    "title": "2001: A Space Odyssey",
    "productType": "DVD",
    "genre": "sci-fi",
    "price": 15
  }
]);

index.addObjects(objects, function(err, content) {
  console.log(content);
});

And then setting them up as attributes for faceting, which is also done at indexing time:

index.set_settings({
  'attributesForFaceting': ['productType', 'genre', 'price']
});

How to format Tags filters

You can create same filters as above (book or dvd, sci-fi) with tags. All you need to do is push the data using the _tags attribute.

var objects = [
  {
    "objectID": "1",
    "title": "2001: A Space Odyssey",
    "price": 10,
    "_tags": ["book", "sci-fi"]
  },
  {
    "objectID": "2",
    "title": "2001: A Space Odyssey",
    "price": 15,
    "_tags": ["DVD", "sci-fi"]
  }
]);

See below - how to filter by tags - for more detail.

Boolean operators

Algolia allows you to leverage boolean operators and parentheses to combine individual filters, similar to SQL expression syntax.

The following operators, which must be specified in CAPS, are supported:

  • OR: must match any of the combined conditions (disjunction)
  • AND: must match all of the combined conditions (conjunction)
  • NOT: negates a filter

Finally, parentheses, ( and ), can be used for grouping.

Putting all that together, if you would like your retrieved products to be either books or ebooks, as well as by the author JK Rowling, your query would look like this:

index.search({
  filters: '(category:Book OR category:Ebook) AND author:"JK Rowling"'
});

Negative Filters

In order to exclude a subset of items matching a certain filter from a list of results, you will need to negate the filter using NOT. For example, to retrieve all books that are not also ebooks, you would use this filter:

index.search({
  filters: 'category:Book AND NOT category:Ebook'
});

You cannot negate a group of filters, only an individual filter. For example, NOT(filter1 OR filter2) is not allowed.

Some caveats

Combining ANDs and ORs

While you may use as many ANDs and ORs as you need, you’ll need to be careful about how you combine them. For performance reasons, we do not allow you to put AND groups within ORs. Here are some considerations to take into account:

  • We allow ( x AND (y OR z) AND (a OR b) )
  • We allow ( x AND y OR z AND a OR b )*
  • We don’t allow ( x OR ( y AND z) OR ( a AND b) )

*Missing parentheses

If you omit parentheses, the engine will automatically put the ORs inside parenthesis:

  • ( x AND y OR z AND a OR b ) becomes ( x AND (y OR z) AND (a OR b) )
  • ( x OR y AND z OR a AND b ) becomes ( (x OR y) AND (z OR a) AND b )

Given the obvious potential for confusion, we encourage you to use parenthesis.

Mixing Categories

As noted above, there are 3 categories of filters (string, numeric, tags). You cannot mix these different filter categories inside an OR. For example, num=3 OR tag1 OR facet:value is not allowed.

Advanced filtering

Filter by Numerical Value

Algolia allows you to numerically filter results either via a comparison or a range, as long as the operand is a numeric value.

Comparison

Comparison operators can be used to retrieve results matching a specified numeric condition based on a supplied attribute. Supported operators are <, <=, =, !=, >= and >, with the same semantics as in virtually all programming languages. For example, it’s possible to restrict the search to all in stock items with the following filter:

index.search({
  filters: 'stock_quantity > 0'
});

Range

By specifying a lower and upper bound for an attribute, it’s possible to return a range of matching results. The range bounds are inclusive on both ends. As an example, retrieving all results between the years 2011 and 2017 would require this type of filter:

index.search({
  filters: 'year: 2011 TO 2017'
});

Filter by Tag Values

The _tags attribute is reserved for filtering by tag values. _tags:published (or, alternatively published) would match all objects containing exactly the keyword “published” in their _tags attribute.

Note that if no attribute name is specified, the filter applies to _tags. For example: public OR user_42 will translate into _tags:public OR _tags:user_42.

Tag filtering is mainly used for filtering only. You will not get a count of records that match the filters. In this way, it is the same as using filterOnly() in the attributesForFaceting, as discussed here.

Here are 2 records:

{
  "title": "Apple MacBook Pro 15.4-Inch Laptop with Retina Display"
  "_tags": ["laptop", "computer", "retina"],
},
{
  "title": "Apple iPhone 5S - 32GB",
  "_tags": ["phone", "smartphone", "retina"]
},
// [...]

This query will find the first record by using the _tags.

index.search({
  filters: 'smartphone AND retina'
});

To compare, here are the same 2 records with 2 new (device and display):

{
  "title": "Apple MacBook Pro 15.4-Inch Laptop with Retina Display"
  "device": ["laptop", "computer"],
  "display": "retina"
},
{
  "title": "Apple iPhone 5S - 32GB",
  "device": ["phone", "smartphone"],
  "display": "retina"
},
// [...]

This query will find the same record as before with _tags, but using attributes as filters:

index.search({
  filters: 'device:smartphone AND display:retina'
});

The last example would need the device and display attributes to be set up initially as attributesForFaceting.

Filter by an array of values

An attribute can contain an array of values, and any one of its values can be used as a filter. Therefore, in the example below, a search for an “apple” with a filter on “laptop” will find the first record, because the device attribute/facet contains the word “laptop”.

{
  "brand": "Apple",
  "device": ["laptop", "computer"],
},
{
  "brand": "Apple",
  "device": ["desktop", "computer"],
},
// [...]
index.search("apple",{
  filters: 'device:computer'
});

Filter by Date

By default the engine doesn’t interpret strings following the ISO date format. To enable filtering by date, you must convert your dates into numeric values (generally a UNIX timestamp).

{
  "objectID": "myID1",
  "date": 1362873600 // UNIX timestamp as an integer
}

Check out our tutorial on filter&faceting, which explains how to filter by date.

Filters Scoring

Algolia provides the ability to rank records by filter scores. As an example, consider a case where a user has created a portfolio, and assigned an interest level score to certain companies. By leveraging filter scores and the sumOrFiltersScores parameter (see below), it’s possible to rank items with the highest summed filter score first.

Here’s what this query might look like:

index.search({
  filters: "(company:Google<score=3> OR company:Amazon<score=2> OR company:Facebook<score=1>)",
});

Results that contained the companies Google, Amazon, and Facebook as company attributes would rank highest, as they would have a score of 3 (google has the highest score). Results containing only the company Facebook would rank lowest, with a score of 1.

Check out an example of how to score in our discussion about personalization.

Scoring ANDs and ORs

It is important to note that filtering only with ANDs will remove the effect of scoring. Essentially, with an AND, the record will only be chosen if all filters match - so all records will have the same score.

Scoring only makes sense when you want to weigh terms differently: records with different terms will have different scores depending on the individual scores of the terms found.

Accumulating scores with sumOrFiltersScores

You can fine-tune the scoring with the boolean parameter sumOrFiltersScores. If not specified, this parameter is false. False means that the total score of a record is the maximum score of an individual filter. Setting it to true changes the total score by adding together the scores of each filter that matches.

For example, a query filtered on “google amazon” with sumOrFiltersScores = false will return a score of 3 (google(3) > amazon(2)).

index.search("", {
  filters: "(company:Google<score=3> OR company:Amazon<score=2> OR company:Facebook<score=1>)",
  sumOrFiltersScores: false
});

The same query with sumOrFiltersScores = true will return a score of 5 (google (3) + amazon(2)).

Facet Filters

While it’s generally easier to use the filters syntax, it is possible to filter hits by facet value using the facetFilters parameter.

Facet filters is discussed in more detail in our Faceting overview.

In the case of multiple filters, they are interpreted as a conjunction (AND). If you want to use a disjunction (OR), you will need to use a nested array.

For example, a simple facet filter that would retrieve books or ebooks by the author JK Rowling would be written like this:

index.search({
  facetFilters: [["category:Book", "category:Ebook"], "author:JK Rowling"]
});

Additionally, Algolia allows you to negate facet filters using a minus sign (-). In this example, any ebooks would be excluded from the results.

index.search({
  facetFilters: "category:-Ebook"
});

Syntax difference between filters and facetFilters

Lastly, the syntax for multiple filters is different. For filtering, you use ANDs and ORs when combining more than one filter.

index.search({
  filters: '("author:Stephen King" OR "genre:Horror") AND "publisher:Penguin"'
});

For faceting, you simply list the attributes. Without brackets, the entire list is interpreted as combing filters with AND. Within brackets [,], the list is interpreted with ORs.

So the equivalent factor filtering for the above is as follows:

index.search({
  facetFilters: [["author:Stephen King", "genre:Horror"], "publisher:Penguin"]
});

What’s Next

Continue building your Algolia knowledge with these concepts:

If you want to get started implementing filters, we have a tutorial you might find helpful:

© Algolia - Privacy Policy