Filters
A filter keeps only the chunks whose fields match a set of conditions: documents of a given category, published after a date, or from a list of sources. Set it on any retriever that you pass to retrieve. The index applies the filter as part of the search, so top_k only counts chunks that pass the filter.
Import the filters from the same module as the retrievers, mistralai.search.toolkit.mistral_search_index.retriever:
from mistralai.search.toolkit.mistral_search_index.retriever import (
Equal,
NearestNeighbourRetriever,
)
results = await index.retrieve(
NearestNeighbourRetriever(
query="termination clauses",
top_k=10,
filter=Equal(field="category", value="legal"),
)
)Filterable fields
You can filter on the following fields:
- Custom fields of a scalar type:
text,keyword,int,long,float, andtimestamp. Declare them in your schema. For more information, see Declare a collection. - System fields such as
idandsource_id.
You can't filter on array, json, or bool fields. For the type of each field, see Custom fields.
Do you need to index the field?
Filters work on every filterable field, whether it's indexed or not. Indexing a field with MistralSearchIndexField(indexed=True) only makes filtering on that field faster. By default, text and keyword fields are indexed, and number and timestamp fields aren't.
You rarely need to index a field for filtering. Index a field when most of your queries filter on it, or when a filter keeps only a small fraction of the index. In that case, the index can find the matching chunks faster. You can turn on indexed later with update_index.
Conditions
A condition compares one field with one or more values:
| Condition | Matches when | Values |
|---|---|---|
Equal(field, value) | The field equals value | str, int, float, or datetime |
In(field, values) | The field equals one of values | A list of str, int, float, or datetime |
Range(field, gt=, gte=, lt=, lte=) | The field falls within the bounds | int, float, or datetime |
A Range requires at least one bound. You can't set both gt and gte, or both lt and lte. The lower bound must be smaller than the upper bound, and both bounds must have the same type, although you can mix int and float.
from datetime import UTC, datetime, timedelta
from mistralai.search.toolkit.mistral_search_index.retriever import Equal, In, Range
Equal(field="category", value="legal")
In(field="source_id", values=["s3://docs/api-keys.md", "s3://docs/members.md"])
Range(field="published_year", gte=2022, lt=2025)
Range(field="ingested_at", gte=datetime.now(UTC) - timedelta(days=7))Combine conditions
To combine conditions, use And, Or, and Not. You can nest them:
from mistralai.search.toolkit.mistral_search_index.retriever import And, Equal, In, Not, Or, Range
filter = And(matches=[
Or(matches=[
Equal(field="category", value="legal"),
Range(field="published_year", gte=2022),
]),
Not(match=In(field="source_id", values=["s3://docs/draft.md"])),
])To leave out results that you've already seen, for example in a follow-up query, wrap an In condition on source_id or id in Not.
Filters in hybrid retrieval
A filter on an RRFRetriever applies to every child retriever. A child can also carry its own filter. The index combines it with the parent filter using AND, so the child filter narrows only that child:
from mistralai.search.toolkit.mistral_search_index.retriever import (
Equal,
KeywordRetriever,
NearestNeighbourRetriever,
Range,
RRFRetriever,
)
question = "termination clauses"
results = await index.retrieve(
RRFRetriever(
top_k=10,
filter=Range(field="published_year", gte=2022),
retrievers=[
KeywordRetriever(query=question, top_k=20, filter=Equal(field="category", value="legal")),
NearestNeighbourRetriever(query=question, top_k=20),
],
)
)In this example, the keyword child matches only legal documents, and the vector child searches every category. Both children only consider documents published since 2022.
See also
- Retrieval: the retrievers that filters attach to.
- Mistral Search Index: declare the custom fields you filter on.