> ## Documentation Index
> Fetch the complete documentation index at: https://www.algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Promote records with optional filters

> Learn how to use optional filters to modify your custom ranking.

Optional filters are a powerful tool for influencing the ranking of search results.
Use them to boost or bury records based on specific criteria, but without hiding those records.

For example, on a website that handles fast food deliveries, if a user types "hungry" and clicks the "deliver quickly" option, the website will show the restaurants that can deliver the fastest at the top of the list but still show other restaurants.

You can also use negative optional filters to demote records.
For example, to lower the ranking of restaurants with poor reviews.

This feature isn't available on every plan.
Refer to your [pricing plan](https://www.algolia.com/pricing) to see if it's included.

## Update your records

Since optional filters only work with exact matches,
you might need to update your records.
Using the fast food delivery website as an example,
flag restaurants that can deliver within 20 minutes by adding a boolean attribute called `can_deliver_quickly`
and set it to `true` or `false` for each record.

```json JSON icon=braces theme={"system"}
[
  {
    "name": "Pasta Bolognese",
    "restaurant": "Millbrook Deli",
    "delivery_waiting_time": 20,
    "can_deliver_quickly": true,
    "popularity": 80
  },
  {
    "name": "Pasta Bolognese",
    "restaurant": "The Hive",
    "delivery_waiting_time": 15,
    "can_deliver_quickly": true,
    "popularity": 80
  },
  {
    "name": "Pasta Bolognese",
    "restaurant": "Bert's Inn",
    "delivery_waiting_time": 40,
    "can_deliver_quickly": false,
    "popularity": 90
  }
]
```

## How to apply optional filters

To use optional filters, you need to:

* Set the attribute in `attributesForFaceting` at indexing time.
  You can do this either through the API or the Algolia dashboard.
* Add the optional filter through a rule or send it with your query using the API.

### Using the dashboard

Set the attribute to use for faceting in your Algolia dashboard:

1. Go to the [Algolia dashboard](https://dashboard.algolia.com/explorer/browse) and select your Algolia application (An Algolia application is a self-contained environment with its own indices, configuration, and API keys. Applications don't share data or settings with each other.).
2. On the left sidebar, select  **Search**.
3. Select your Algolia index and go to the **Configuration** tab.
4. Under **Filtering and Faceting > Facets**, click **Add an attribute** and select the optional filter attributes (for example, `can_deliver_quickly`).
5. Save your changes.

You can create a rule to boost records where `can_deliver_quickly` is `true` using either the Visual Editor or the Manual Editor.

> [tab] Visual Editor
>
> 1. Open **Rules** and select **New rule > Visual Editor**.
> 2. In **Conditions**, select **Create conditionless rule** and click **Apply** to apply the boost to every search.
>    To limit the boost to specific queries, select **Set query condition(s)** instead.
> 3. In **Consequences**, select **Boost categories**.
>    Select `can_deliver_quickly` as the attribute and `true` as its value, then click **Apply**.
> 4. Preview the results with an empty query, click **Review and Publish**, and click **Publish**.

> [tab] Manual Editor
>
> 1. Open [**Rules**](https://dashboard.algolia.com/rules), select **Create your first rule** or **New rule**, and select **Manual Editor**.
> 2. In **Condition(s)**, remove the default condition to make the rule apply to every search.
>    To limit the boost to specific queries, configure a query condition instead.
> 3. In **Consequence(s)**, click **Add consequence** and select **Add Query Parameter**.
>    Enter `{ "optionalFilters": ["can_deliver_quickly:true"] }`.
> 4. Save your changes.

Using the [example dataset](#update-your-records), the rule boosts records where `can_deliver_quickly` is `true`, while the other record remains in the results.

To demote records instead, use **Bury categories** in the Visual Editor.
For example, select `can_deliver_quickly` as the attribute and `false` as its value.
In the Manual Editor, use **Add Query Parameter** with `{ "optionalFilters": ["can_deliver_quickly:-false"] }` for the same effect.

### Using the API

To run the code examples on this page, [install the latest API client](https://www.algolia.com/doc/libraries/sdk/install.md).

Set the attribute to use for faceting with [`attributesForFaceting`](https://www.algolia.com/doc/api-reference/api-parameters/attributesForFaceting).
For example:

```cs C# theme={"system"}
var response = await client.SetSettingsAsync(
  "INDEX_NAME",
  new IndexSettings
  {
    AttributesForFaceting = new List<string> { "can_deliver_quickly", "restaurant" },
  }
);
```

```dart Dart theme={"system"}
final response = await client.setSettings(
  indexName: "INDEX_NAME",
  indexSettings: IndexSettings(
    attributesForFaceting: [
      "can_deliver_quickly",
      "restaurant",
    ],
  ),
);
```

```go Go theme={"system"}
response, err := client.SetSettings(client.NewApiSetSettingsRequest(
  "INDEX_NAME",
  search.NewEmptyIndexSettings().SetAttributesForFaceting(
    []string{"can_deliver_quickly", "restaurant"})))
if err != nil {
  // handle the eventual error
  panic(err)
}
```

```java Java theme={"system"}
UpdatedAtResponse response = client.setSettings(
  "INDEX_NAME",
  new IndexSettings().setAttributesForFaceting(Arrays.asList("can_deliver_quickly", "restaurant"))
);
```

```js JavaScript theme={"system"}
const response = await client.setSettings({
  indexName: 'INDEX_NAME',
  indexSettings: { attributesForFaceting: ['can_deliver_quickly', 'restaurant'] },
});
```

```kotlin Kotlin theme={"system"}
var response =
  client.setSettings(
    indexName = "INDEX_NAME",
    indexSettings =
      IndexSettings(attributesForFaceting = listOf("can_deliver_quickly", "restaurant")),
  )
```

```php PHP theme={"system"}
$response = $client->setSettings(
    'INDEX_NAME',
    ['attributesForFaceting' => [
        'can_deliver_quickly',

        'restaurant',
    ],
    ],
);
```

```python Python theme={"system"}
response = client.set_settings(
    index_name="INDEX_NAME",
    index_settings={
        "attributesForFaceting": [
            "can_deliver_quickly",
            "restaurant",
        ],
    },
)
```

```ruby Ruby theme={"system"}
response = client.set_settings(
  "INDEX_NAME",
  Algolia::Search::IndexSettings.new(attributes_for_faceting: ["can_deliver_quickly", "restaurant"])
)
```

```scala Scala theme={"system"}
val response = Await.result(
  client.setSettings(
    indexName = "INDEX_NAME",
    indexSettings = IndexSettings(
      attributesForFaceting = Some(Seq("can_deliver_quickly", "restaurant"))
    )
  ),
  Duration(100, "sec")
)
```

```swift Swift theme={"system"}
let response = try await client.setSettings(
    indexName: "INDEX_NAME",
    indexSettings: IndexSettings(attributesForFaceting: ["can_deliver_quickly", "restaurant"])
)
```

Send the optional filters with your query.
For example:

```cs C# theme={"system"}
var response = await client.SearchSingleIndexAsync<Hit>(
  "INDEX_NAME",
  new SearchParams(
    new SearchParamsObject
    {
      OptionalFilters = new OptionalFilters(
        new List<OptionalFilters> { new OptionalFilters("can_deliver_quickly:true") }
      ),
    }
  )
);
```

```dart Dart theme={"system"}
final response = await client.searchSingleIndex(
  indexName: "INDEX_NAME",
  searchParams: SearchParamsObject(
    optionalFilters: [
      "can_deliver_quickly:true",
    ],
  ),
);
```

```go Go theme={"system"}
response, err := client.SearchSingleIndex(client.NewApiSearchSingleIndexRequest(
  "INDEX_NAME").WithSearchParams(search.SearchParamsObjectAsSearchParams(
  search.NewEmptySearchParamsObject().SetOptionalFilters(search.ArrayOfOptionalFiltersAsOptionalFilters(
    []search.OptionalFilters{*search.StringAsOptionalFilters("can_deliver_quickly:true")})))))
if err != nil {
  // handle the eventual error
  panic(err)
}
```

```java Java theme={"system"}
SearchResponse response = client.searchSingleIndex(
  "INDEX_NAME",
  new SearchParamsObject().setOptionalFilters(OptionalFilters.of(Arrays.asList(OptionalFilters.of("can_deliver_quickly:true")))),
  Hit.class
);
```

```js JavaScript theme={"system"}
const response = await client.searchSingleIndex({
  indexName: 'indexName',
  searchParams: { optionalFilters: ['can_deliver_quickly:true'] },
});
```

```kotlin Kotlin theme={"system"}
var response =
  client.searchSingleIndex(
    indexName = "INDEX_NAME",
    searchParams =
      SearchParamsObject(
        optionalFilters =
          OptionalFilters.of(listOf(OptionalFilters.of("can_deliver_quickly:true")))
      ),
  )
```

```php PHP theme={"system"}
$response = $client->searchSingleIndex(
    'INDEX_NAME',
    ['optionalFilters' => [
        'can_deliver_quickly:true',
    ],
    ],
);
```

```python Python theme={"system"}
response = client.search_single_index(
    index_name="INDEX_NAME",
    search_params={
        "optionalFilters": [
            "can_deliver_quickly:true",
        ],
    },
)
```

```ruby Ruby theme={"system"}
response = client.search_single_index(
  "INDEX_NAME",
  Algolia::Search::SearchParamsObject.new(optional_filters: ["can_deliver_quickly:true"])
)
```

```scala Scala theme={"system"}
val response = Await.result(
  client.searchSingleIndex(
    indexName = "INDEX_NAME",
    searchParams = Some(
      SearchParamsObject(
        optionalFilters = Some(OptionalFilters(Seq(OptionalFilters("can_deliver_quickly:true"))))
      )
    )
  ),
  Duration(100, "sec")
)
```

```swift Swift theme={"system"}
let response: SearchResponse<Hit> = try await client.searchSingleIndex(
    indexName: "INDEX_NAME",
    searchParams: SearchSearchParams
        .searchSearchParamsObject(SearchSearchParamsObject(optionalFilters: SearchOptionalFilters
                .arrayOfSearchOptionalFilters([SearchOptionalFilters.string("can_deliver_quickly:true")])))
)
```

You can also add negative optional filters.
For example, to demote a specific restaurant:

```cs C# theme={"system"}
var response = await client.SearchSingleIndexAsync<Hit>(
  "INDEX_NAME",
  new SearchParams(
    new SearchParamsObject
    {
      Query = "query",
      OptionalFilters = new OptionalFilters(
        new List<OptionalFilters> { new OptionalFilters("restaurant:-Bert's Inn") }
      ),
    }
  )
);
```

```dart Dart theme={"system"}
final response = await client.searchSingleIndex(
  indexName: "INDEX_NAME",
  searchParams: SearchParamsObject(
    query: "query",
    optionalFilters: [
      "restaurant:-Bert's Inn",
    ],
  ),
);
```

```go Go theme={"system"}
response, err := client.SearchSingleIndex(client.NewApiSearchSingleIndexRequest(
  "INDEX_NAME").WithSearchParams(search.SearchParamsObjectAsSearchParams(
  search.NewEmptySearchParamsObject().SetQuery("query").SetOptionalFilters(search.ArrayOfOptionalFiltersAsOptionalFilters(
    []search.OptionalFilters{*search.StringAsOptionalFilters("restaurant:-Bert's Inn")})))))
if err != nil {
  // handle the eventual error
  panic(err)
}
```

```java Java theme={"system"}
SearchResponse response = client.searchSingleIndex(
  "INDEX_NAME",
  new SearchParamsObject()
    .setQuery("query")
    .setOptionalFilters(OptionalFilters.of(Arrays.asList(OptionalFilters.of("restaurant:-Bert's Inn")))),
  Hit.class
);
```

```js JavaScript theme={"system"}
const response = await client.searchSingleIndex({
  indexName: 'indexName',
  searchParams: { query: 'query', optionalFilters: ["restaurant:-Bert's Inn"] },
});
```

```kotlin Kotlin theme={"system"}
var response =
  client.searchSingleIndex(
    indexName = "INDEX_NAME",
    searchParams =
      SearchParamsObject(
        query = "query",
        optionalFilters =
          OptionalFilters.of(listOf(OptionalFilters.of("restaurant:-Bert's Inn"))),
      ),
  )
```

```php PHP theme={"system"}
$response = $client->searchSingleIndex(
    'INDEX_NAME',
    ['query' => 'query',
        'optionalFilters' => [
            "restaurant:-Bert's Inn",
        ],
    ],
);
```

```python Python theme={"system"}
response = client.search_single_index(
    index_name="INDEX_NAME",
    search_params={
        "query": "query",
        "optionalFilters": [
            "restaurant:-Bert's Inn",
        ],
    },
)
```

```ruby Ruby theme={"system"}
response = client.search_single_index(
  "INDEX_NAME",
  Algolia::Search::SearchParamsObject.new(query: "query", optional_filters: ["restaurant:-Bert's Inn"])
)
```

```scala Scala theme={"system"}
val response = Await.result(
  client.searchSingleIndex(
    indexName = "INDEX_NAME",
    searchParams = Some(
      SearchParamsObject(
        query = Some("query"),
        optionalFilters = Some(OptionalFilters(Seq(OptionalFilters("restaurant:-Bert's Inn"))))
      )
    )
  ),
  Duration(100, "sec")
)
```

```swift Swift theme={"system"}
let response: SearchResponse<Hit> = try await client.searchSingleIndex(
    indexName: "INDEX_NAME",
    searchParams: SearchSearchParams.searchSearchParamsObject(SearchSearchParamsObject(
        query: "query",
        optionalFilters: SearchOptionalFilters
            .arrayOfSearchOptionalFilters([SearchOptionalFilters.string("restaurant:-Bert's Inn")])
    ))
)
```

## Optional or facet filters

Whether to use optional filters or [facet filters](https://www.algolia.com/doc/guides/managing-results/refine-results/filtering/in-depth/filters-and-facetfilters.md)
depends on your goals:

* Use optional filters to boost records.
* Use facet filters if you need to filter out records.

## See also

* [Filter scoring](https://www.algolia.com/doc/guides/managing-results/refine-results/filtering/in-depth/filter-scoring.md)
* [Fuzzy search: optional filters](https://www.algolia.com/blog/engineering/discover-what-fuzzy-search-is-with-fuzzy-matching)
