Metadata Filters
Mastra provides a unified metadata filtering syntax across all vector stores, based on MongoDB/Sift query syntax. Each vector store translates these filters into their native format.
Basic Example
import { PgVector } from '@mastra/pg';
const store = new PgVector(connectionString);
const results = await store.query(
"my_index",
queryVector,
10,
{
category: "electronics", // Simple equality
price: { $gt: 100 }, // Numeric comparison
tags: { $in: ["sale", "new"] } // Array membership
}
);
Supported Operators
Basic Comparison
Operator | Description | Example | Supported By |
---|---|---|---|
$eq | Matches values equal to specified value |
| All |
$ne | Matches values not equal |
| All |
$gt | Greater than |
| All |
$gte | Greater than or equal |
| All |
$lt | Less than |
| All |
$lte | Less than or equal |
| All |
Array Operators
Operator | Description | Example | Supported By |
---|---|---|---|
$in | Matches any value in array |
| All |
$nin | Matches none of the values |
| All |
$all | Matches arrays containing all elements |
| AstraPineconeUpstash |
$elemMatch | Matches array elements meeting criteria |
| LibSQLPgVector |
Logical Operators
Operator | Description | Example | Supported By |
---|---|---|---|
$and | Logical AND |
| All except Vectorize |
$or | Logical OR |
| All except Vectorize |
$not | Logical NOT |
| AstraQdrantUpstashPgVectorLibSQL |
$nor | Logical NOR |
| QdrantUpstashPgVectorLibSQL |
Element Operators
Operator | Description | Example | Supported By |
---|---|---|---|
$exists | Matches documents with field |
| All except Vectorize, Chroma |
Custom Operators
Operator | Description | Example | Supported By |
---|---|---|---|
$contains | Text contains substring |
| UpstashLibSQLPgVector |
$regex | Regular expression match |
| QdrantPgVectorUpstash |
$size | Array length check |
| AstraLibSQLPgVector |
$geo | Geospatial query |
| Qdrant |
$datetime | Datetime range query |
| Qdrant |
$hasId | Vector ID existence check |
| Qdrant |
$hasVector | Vector existence check |
| Qdrant |
Common Rules and Restrictions
-
Field names cannot:
- Contain dots (.) unless referring to nested fields
- Start with $ or contain null characters
- Be empty strings
-
Values must be:
- Valid JSON types (string, number, boolean, object, array)
- Not undefined
- Properly typed for the operator (e.g., numbers for numeric comparisons)
-
Logical operators:
- Must contain valid conditions
- Cannot be empty
- Must be properly nested
- Can only be used at top level or nested within other logical operators
- Cannot be used at field level or nested inside a field
- Cannot be used inside an operator
- Valid:
{ "$and": [{ "field": { "$gt": 100 } }] }
- Valid:
{ "$or": [{ "$and": [{ "field": { "$gt": 100 } }] }] }
- Invalid:
{ "field": { "$and": [{ "$gt": 100 }] } }
- Invalid:
{ "field": { "$gt": { "$and": [{...}] } } }
-
$not operator:
- Must be an object
- Cannot be empty
- Can be used at field level or top level
- Valid:
{ "$not": { "field": "value" } }
- Valid:
{ "field": { "$not": { "$eq": "value" } } }
-
Operator nesting:
- Logical operators must contain field conditions, not direct operators
- Valid:
{ "$and": [{ "field": { "$gt": 100 } }] }
- Invalid:
{ "$and": [{ "$gt": 100 }] }
Store-Specific Notes
Astra
- Nested field queries are supported using dot notation
- Array fields must be explicitly defined as arrays in the metadata
- Metadata values are case-sensitive
ChromaDB
- Where filters only return results where the filtered field exists in metadata
- Empty metadata fields are not included in filter results
- Metadata fields must be present for negative matches (e.g., $ne won’t match documents missing the field)
Cloudflare Vectorize
- Requires explicit metadata indexing before filtering can be used
- Use
createMetadataIndex()
to index fields you want to filter on - Up to 10 metadata indexes per Vectorize index
- String values are indexed up to first 64 bytes (truncated on UTF-8 boundaries)
- Number values use float64 precision
- Filter JSON must be under 2048 bytes
- Field names cannot contain dots (.) or start with $
- Field names limited to 512 characters
- Vectors must be re-upserted after creating new metadata indexes to be included in filtered results
- Range queries may have reduced accuracy with very large datasets (~10M+ vectors)
LibSQL
- Supports nested object queries with dot notation
- Array fields are validated to ensure they contain valid JSON arrays
- Numeric comparisons maintain proper type handling
- Empty arrays in conditions are handled gracefully
- Metadata is stored in a JSONB column for efficient querying
PgVector
- Full support for PostgreSQL’s native JSON querying capabilities
- Efficient handling of array operations using native array functions
- Proper type handling for numbers, strings, and booleans
- Nested field queries use PostgreSQL’s JSON path syntax internally
- Metadata is stored in a JSONB column for efficient indexing
Pinecone
- Metadata field names are limited to 512 characters
- Numeric values must be within the range of ±1e38
- Arrays in metadata are limited to 64KB total size
- Nested objects are flattened with dot notation
- Metadata updates replace the entire metadata object
Qdrant
- Supports advanced filtering with nested conditions
- Payload (metadata) fields must be explicitly indexed for filtering
- Efficient handling of geo-spatial queries
- Special handling for null and empty values
- Vector-specific filtering capabilities
- Datetime values must be in RFC 3339 format
Upstash
- 512-character limit for metadata field keys
- Query size is limited (avoid large IN clauses)
- No support for null/undefined values in filters
- Translates to SQL-like syntax internally
- Case-sensitive string comparisons
- Metadata updates are atomic