Skip to main content
Optional filters use the same syntax as facetFilters, but they behave differently:
They don’t exclude records. Instead, they influence the record’s ranking.
Use them to promote or demote results without filtering them out. For example:
  • To promote books by John Doe: ["category:Book", "author:John Doe"]
  • To demote items from the Books category: ["category:-Books"]

Usage

  • Optional filters only have an effect if the Filters ranking criterion is present in your ranking formula (default behavior).
  • They’re applied after any sorting criteria (sorting by attribute)
  • On virtual replicas, optional filters are applied after the replica’s relevant sort.
  • Numeric comparisons aren’t supported.
  • If the Filters ranking criterion is applied before custom ranking (default), the optional filters take precedence over the custom ranking in the tie-breaking algorithm.
  • To use an attribute as an optional filter, it must be included in the attributesForFaceting setting.

Escape minus signs

If a facet value starts with - and isn’t a negative filter, escape it: category:\-movie.

Example

Current API clients

var response = await client.SearchSingleIndexAsync<Hit>(
  "INDEX_NAME",
  new SearchParams(
    new SearchParamsObject
    {
      OptionalFilters = new OptionalFilters(
        new List<OptionalFilters> { new OptionalFilters("can_deliver_quickly:true") }
      ),
    }
  )
);
final response = await client.searchSingleIndex(
  indexName: "INDEX_NAME",
  searchParams: SearchParamsObject(
    optionalFilters: [
      "can_deliver_quickly:true",
    ],
  ),
);
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)
}
SearchResponse response = client.searchSingleIndex(
  "INDEX_NAME",
  new SearchParamsObject().setOptionalFilters(OptionalFilters.of(Arrays.asList(OptionalFilters.of("can_deliver_quickly:true")))),
  Hit.class
);
const response = await client.searchSingleIndex({
  indexName: 'indexName',
  searchParams: { optionalFilters: ['can_deliver_quickly:true'] },
});
var response =
  client.searchSingleIndex(
    indexName = "INDEX_NAME",
    searchParams =
      SearchParamsObject(
        optionalFilters =
          OptionalFilters.of(listOf(OptionalFilters.of("can_deliver_quickly:true")))
      ),
  )
$response = $client->searchSingleIndex(
    'INDEX_NAME',
    ['optionalFilters' => [
        'can_deliver_quickly:true',
    ],
    ],
);
response = client.search_single_index(
    index_name="INDEX_NAME",
    search_params={
        "optionalFilters": [
            "can_deliver_quickly:true",
        ],
    },
)
response = client.search_single_index(
  "INDEX_NAME",
  Algolia::Search::SearchParamsObject.new(optional_filters: ["can_deliver_quickly:true"])
)
val response = Await.result(
  client.searchSingleIndex(
    indexName = "INDEX_NAME",
    searchParams = Some(
      SearchParamsObject(
        optionalFilters = Some(OptionalFilters(Seq(OptionalFilters("can_deliver_quickly:true"))))
      )
    )
  ),
  Duration(100, "sec")
)
let response: SearchResponse<Hit> = try await client.searchSingleIndex(
    indexName: "INDEX_NAME",
    searchParams: SearchSearchParams
        .searchSearchParamsObject(SearchSearchParamsObject(optionalFilters: SearchOptionalFilters
                .arrayOfSearchOptionalFilters([SearchOptionalFilters.string("can_deliver_quickly:true")])))
)
var query = new Query()
{
  SearchQuery = "query",
  OptionalFilters = new List>
  {
    new List { "category:Book", "author:John Doe" }
  }
};
res, err := index.Search(
	"query",
	opt.OptionalFilterAnd("category:Book", "author:John Doe"),
)
index.search(
  new Query("query").setOptionalFilters(
    Collections.singletonList(Arrays.asList(
      "category:Book",
      "author:John Doe")))
);
index
  .search("query", {
    optionalFilters: ["category:Book", "author:John Doe"],
  })
  .then(({ hits }) => {
    console.log(hits);
  });
val query = query("query") {
    optionalFilters {
        and {
            facet("category", "Book")
            facet("author", "John Doe")
        }
    }
}

index.search(query)
$results = $index->search('query', [
  'optionalFilters' => [
    "category:Book",
    "author:John Doe"
  ]
]);
results = index.search(
    "query", {"optionalFilters": ["category:Book", "author:John Doe"]}
)
results = index.search(
  "query",
  {
    optionalFilters: [
      "category:Book",
      "author:John Doe"
    ]
  }
)
client.execute {
  search into "myIndex" query Query(
    customParameters = Some(
      Map(
        "optionalFilters" -> Some(Seq(
          "category:Book",
          "author:John Doe"
        ))
      )
    )
}
let query = Query()
  .set(\.optionalFilters, to: ["category:Book", "author:John Doe"])

index.search(query: query) { result in
  if case .success(let response) = result {
    print("Response: \(response)")
  }
}
Last modified on May 19, 2026