API Reference / iOS InstantSearch Widgets / Filter State
Apr. 24, 2019

Filter State

About this widget

A FilterState consists of one or several filters, organized in groups. Each group can contain multiple filters.

There are three types of filters:

  • Facet.Filter
  • Facet.Numeric
  • Facet.Tag

You can read more about each filter type in our filtering guide. FilterState provides a simple interface to deal with filter grouping and their respective boolean operator. For more details, you can read more about filter grouping and boolean operators.

There are two types of filter groups:

Conjunctive groups

Search results will only contain hits that match all the filters in a conjunctive filter group. In other words, it represents a boolean and relationship between filters in this group.

For example, if FilterState contains a conjunctive group of filters size:42 and category:shirt, records that match both filters will be returned. A conjunctive group may contain filters of any type at the same time.

Disjunctive groups

Search results will contain hits that match any the filters in a disjuncitve filter group. In other words, it represents a boolean or relationship between filters in this group.

For example, if FilterState contains a disjunctive group of filters color:red and color:blue, records that match any of these filters will be returned. Disjunctive group may only contain filters of the same type. For example, you can’t put a facet filter and a tag filter in the same disjunctive group.

The set of the groups in FilterState are related with each other via the and operator. That means that a record matches the set of filters in FilterState only if it satisfies all the groups simultaneously.

Examples

To access filter groups, FilterState provides a subscript syntax. Each group can be identified by its name which is represented as a string. Groups may be accessed via [and: "groupName"] and [or: "groupName"] subscripts for conjunctive and disjunctive groups respectively. There is no need to create or remove groups. A group is created automatically when a first filter is added, and is deleted when it does not contain any filters.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  let filterState = FilterState()

  // Add filter to conjunctive group
  filterState[and: "conjunctiveGroup"].add(Filter.Facet(attribute: "category", stringValue: "shirts"))

  // Add filter to disjunctive group
  filterState[or: "disjunctiveGroup"].add(Filter.Facet(attribute: "color", stringValue: "red"))

  print(filterState.debugDescription)

  /* Output:
  FilterState {
   "conjunctiveGroup": ( "category":"shirts" )
   "disjunctiveGroup": ( "color":"red" )
  }
  */    

Please note that disjunctive groups with different type of filters are considered as different groups.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  let filterState = FilterState()
      
  filterState[or: "disjunctiveGroup"].add(Filter.Facet(attribute: "color", stringValue: "red"),
                                          Filter.Facet(attribute: "color", stringValue: "blue"))
  filterState[or: "disjunctiveGroup"].add(Filter.Numeric(attribute: "price", range: 10...100))
  filterState[or: "disjunctiveGroup"].add(Filter.Tag(stringLiteral: "sales"))

  print(filterState.debugDescription)
  
  // Three different groups have been created with the same name according to type
  /* Output:
  FilterState {
   "disjunctiveGroup": ( "_tags":"sales" )
   "disjunctiveGroup": ( "color":"blue" OR "color":"red" )
   "disjunctiveGroup": ( "price":10.0 TO 100.0 )
  }
  */

Group accessors in FilterState provide convenient functionalities such as filter removal:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  let filterState = FilterState()
  let tagFilter = Filter.Tag(stringLiteral: "sales")

  filterState[and: "conjunctiveGroup"].add(tagFilter)
  print(filterState.debugDescription)

  /* Output:
  FilterState {
    "conjunctiveGroup": ( "_tags":"sales" )
  }
  */

  filterState[and: "conjunctiveGroup"].remove(tagFilter)
  print(filterState.debugDescription)

  /* Output:
  FilterState {}
  */

and toggling:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  let filterState = FilterState()
  let tagFilter = Filter.Tag(stringLiteral: "sales")

  filterState[and: "conjunctiveGroup"].toggle(tagFilter)
  print(filterState.debugDescription)

  /* Output:
  FilterState {
    "conjunctiveGroup": ( "_tags":"sales" )
  }
  */

  filterState[and: "conjunctiveGroup"].toggle(tagFilter)
  print(filterState.debugDescription)

  /* Output:
  FilterState {}
  */

Transform to SQL syntax string

InstantSearch provides a convenient way to transform a FilterState into a valid SQL-like string expression which can be used with Query.

1
2
3
4
5
6
7
8
9
10
11
12
let filterState: FilterState = ...

// convert FilterState to list of filter groups
let filterGroups = filterState.toFilterGroups()

// convert list of filter groups to Algolia filter SQL syntax
let filters = FilterGroupConverter().sql(filterGroups)

// set filters to Query
let query: Query = ...
query.filters = filters

CustomStringConvertible conformity

FilterState conforms to the CustomStringConvertible protocol which provides the same valid SQL-like string via the description property. Therefore, the previous snippet can be significantly reduced as follows:

1
2
3
4
5
let filterState: FilterState = ...
let query: Query = ...

query.filters = filterState.description

Did you find this page helpful?