@key
The @key decorator disambiguates relations when multiple relations exist between the same two models.
Disambiguates relations when multiple relations exist between the same two models, or when a model has self-referential relations. Both the forward and reverse relations must share the same @key value to pair correctly.
Syntax
@key(name)The name is an arbitrary string identifier. Matching forward and reverse relations must use the same key.
When Is @key Required?
@key is needed in two situations:
- Multiple relations between the same two models — Cerial cannot automatically determine which forward relation pairs with which reverse relation.
- Self-referential relations with a reverse lookup — A model that relates to itself needs
@keyto distinguish forward and reverse directions.
If there is only one relation between two models, @key is not needed — Cerial resolves it automatically.
Multiple Relations to the Same Model
When a model has two or more relations pointing to the same target, each pair needs a unique @key:
model Document {
id Record @id
title String
authorId Record
author Relation @field(authorId) @model(Writer) @key(author)
reviewerId Record?
reviewer Relation? @field(reviewerId) @model(Writer) @key(reviewer)
}
model Writer {
id Record @id
name String
authoredDocs Relation[] @model(Document) @key(author)
reviewedDocs Relation[] @model(Document) @key(reviewer)
}Without @key, Cerial wouldn't know whether authoredDocs corresponds to the author relation or the reviewer relation.
const writer = await client.db.Writer.findOne({
where: { id: writerId },
include: {
authoredDocs: true, // Documents where this writer is the author
reviewedDocs: true, // Documents where this writer is the reviewer
},
});Self-Referential Relations
A model that references itself needs @key to pair the forward and reverse relations:
model Category {
id Record @id
name String
parentId Record?
parent Relation? @field(parentId) @model(Category) @key(hierarchy)
children Relation[] @model(Category) @key(hierarchy)
}// Get a category with its parent and children
const category = await client.db.Category.findOne({
where: { id: categoryId },
include: {
parent: true,
children: true,
},
});Multiple Self-Referential Relations
If a model has multiple self-referential relation pairs, each pair gets its own key:
model Employee {
id Record @id
name String
managerId Record?
manager Relation? @field(managerId) @model(Employee) @key(management)
directReports Relation[] @model(Employee) @key(management)
mentorId Record?
mentor Relation? @field(mentorId) @model(Employee) @key(mentorship)
mentees Relation[] @model(Employee) @key(mentorship)
}const employee = await client.db.Employee.findOne({
where: { id: empId },
include: {
manager: true,
directReports: true,
mentor: true,
mentees: true,
},
});Allowed On
| Construct | Allowed |
|---|---|
Relation fields | ✅ |
Record fields | — (validation error) |
| Object fields | — |
| Tuple elements | — |
@key is strictly for Relation fields. Placing it on a Record field produces a validation error.
Restrictions
- Key values must match — The forward and reverse relations in a pair must use the exact same
@keyvalue. - Unique per pair — Within the same model, two forward relations to the same target cannot share the same key. Similarly, two reverse relations from the same source cannot share the same key.
- Only on Relation fields —
@keycannot be placed onRecordfields, object fields, or tuple elements. - Compatible with other relation decorators —
@keyworks alongside@field,@model, and@onDelete.