Skip to main content

About this widget

A FilterState consists of one or several filters, organized in groups. Each group can contain one or more of these filter types:
  • Facet.Filter
  • Facet.Numeric
  • Facet.Tag
You can read more about each filter type in the 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. Filter groups can be:
  • 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, 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 disjunctive 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 groups in FilterState behave as if they’re combined by an AND operator. That means that a record matches the set of filters in FilterState only if it satisfies all the groups simultaneously.

Explore example code

Browse the FilterState example code on GitHub.

Examples

To access filter groups, FilterState provides a subscript syntax. Each group is identified by its name (string). You can access groups by using [and: "groupName"] for conjunctive groups and [or: "groupName"] for disjunctive groups. Groups are automatically created when you add the first filter, and are deleted when they’re empty.
Swift
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" )
}
*/
Disjunctive groups with different type of filters are considered as different groups.
Swift
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:
Swift
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:
Swift
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.
Swift
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.facetFilters = filters

CustomStringConvertible conformity

FilterState conforms to the CustomStringConvertible protocol which provides the same valid SQL-like string with the description property. Therefore, the previous snippet can be reduced to this:
Swift
let filterState: FilterState = ...
let query: Query = ...

query.facetFilters = filterState.description
Last modified on March 23, 2026