filter@v1 stages.
Payload Indexes
Create indexes on your namespace before using filters:
If you filter on an unindexed field, the response includes a
warnings array telling you which fields need indexes:
System fields (
collection_id, bucket_id, object_id, batch_id) and _internal.* fields are indexed automatically — you only need to create indexes for your own fields.Logical Operators
Mixpeek filters support three logical operators for composing conditions:AND Operator
Requires all nested conditions to match:OR Operator
Matches if any nested condition is true:NOT Operator
Excludes documents matching the condition:Nesting Operators
Logical operators can be nested to create complex filter logic:- Published AND
- Either video or audio AND
- Not restricted
Comparison Operators
Use these operators within conditions:Use
text to match any of the query tokens (BM25); use phrase when word
order matters — e.g. find a transcript where someone says an exact quote.
{ "field": "transcription", "operator": "phrase", "value": "make america great again" }
matches “…make america great again…” but not “america will be great again”.Geospatial Operators
Geospatial operators filter documents by a location field, a payload value holding a geographic point. A point may be either an object{ "lat": <num>, "lon": <num> }
or a GeoJSON-style [lon, lat] array. A field holding a list of points matches
if any point satisfies the predicate. See
Geospatial filtering for
how the same operators behave inside the attribute_filter stage.
Each operator takes a structured
value:
Distances use the haversine formula on a spherical earth (R = 6,371,000 m).
Bounding boxes handle the antimeridian: when
top_left.lon > bottom_right.lon
the box is treated as wrapping across ±180°. Malformed geometry (out-of-range
lat/lon, a missing corner, or fewer than 3 polygon points) is rejected at
request time with a descriptive error; a document whose location field is
missing or unparseable is a non-match (it is never an error).Lineage Shortcuts
Every Mixpeek document carries a_internal.lineage block recording where it
came from. To filter by lineage you don’t have to use the underscore-prefixed
paths — use the friendly aliases below in any field position.
field is used.
The _internal Envelope
Every document carries an _internal envelope that Mixpeek writes and owns. The
rule for what lives there: content at the root, record-keeping in _internal.
Content is what the asset is — anything you filter on, rank by, or show a user,
including everything Mixpeek derived for you (embeddings, transcripts, taxonomy
labels). _internal is what the row is — how it came to exist, who may read it,
and the identity and timestamps of the record. You can filter on these fields
anywhere field is used; system-owned ones are rejected if you try to set them on
write.
Range filtering works on these timestamps and on any Datetime index you define.
Pass RFC 3339 strings as the bounds:
Every _internal field
This table is generated from the server’s field registry (shared/databases/internal_field_registry.py), so it is the complete, authoritative set — if a name is not here, Mixpeek does not write it under _internal. Filter on the field / alias column; the storage path is shown so you can address a nested value explicitly.
Identity
Timestamps
Lineage
System metadata
Blobs
Provenance
Tenancy
Access control
Using Templates
Reference request inputs or stage outputs in filter values:Filter Stage Example
Stage Pre-Filters and Post-Filters
Every stage accepts optionalpre_filters and post_filters as siblings of
parameters. Use pre_filters. They narrow the candidate set before the
stage runs, pushed down into the vector store as native filters. Both take the
same logical-operator shape as any other filter.
Canonical shape — wrap conditions in an explicit logical operator:
{ "AND": [ ... ] } form — it is unambiguous and
nests cleanly with OR/NOT.
For convenience, two shorthand forms are coerced to an
AND group:- a single bare condition —
{ "field": "...", "operator": "...", "value": "..." }becomes{ "AND": [ <condition> ] } - a list of conditions —
[ { ... }, { ... } ]becomes{ "AND": [ ... ] }
field, operator, and value. An
incomplete condition (for example, a missing operator) is rejected with a
clear error rather than silently ignored. That guarantee covers the shape of a
condition, not where you place it. A well-formed condition placed in
post_filters still degrades into an unfiltered result, as described above.
