@@index
Create non-unique composite indexes spanning multiple fields for query performance.
Creates a non-unique composite index spanning multiple fields. This improves query performance for filters on the listed combination of fields, without enforcing uniqueness.
Syntax
model LogEntry {
id Record @id
userId String
action String
timestamp Date @createdAt
@@index(userAction, [userId, action])
}Composite directives are placed at the end of the model block:
@@index(name, [field1, field2, ...])- name — A unique identifier for this composite. Must be globally unique across all models.
- fields — At least 2 field references. Supports dot notation for object subfields.
Behavior
- A
DEFINE INDEXstatement (withoutUNIQUE) is generated in migrations for the listed fields. - The index speeds up lookups but does not prevent duplicate combinations.
@@indexcomposites cannot be used withfindUnique,updateUnique,deleteUnique, orupsert— those require@@uniqueor a single@unique/@idfield.
Difference from @@unique
| Aspect | @@index | @@unique |
|---|---|---|
| Duplicate combos | Allowed | Rejected by DB |
| Unique lookups | Not available | findUnique, updateUnique, deleteUnique |
| Use case | Performance optimization | Data integrity constraint |
Object Subfields (Dot Notation)
Like @@unique, composite @@index supports dot notation for object subfields:
object Address {
city String
state String
}
model Customer {
id Record @id
name String
address Address
@@index(cityState, [address.city, address.state])
}Null and Optional Fields
Since @@index does not enforce uniqueness, null/NONE values have no special behavior — multiple records with the same combination (including nulls) are always allowed.
For null behavior on unique constraints, see @@unique — Null Behavior and @unique — Null Behavior.
Rules
- Requires at least 2 fields.
- Composite names must be globally unique across all models.
- @id fields cannot be part of a composite (they are already unique).
- Relation fields (virtual) cannot be indexed — use the underlying Record field instead.
- Array fields (
String[],Record[]) cannot be part of a composite. - An object field and its own subfield cannot both appear in the same composite (e.g.,
[address, address.city]is rejected as redundant).
Use @@index for performance optimization on frequently queried field combinations. Use @@unique when you need to enforce data integrity constraints.