一对多关系
本页介绍一对多关系并解释如何在 Prisma 模式中使用它们。
¥This page introduces one-to-many relations and explains how to use them in your Prisma schema.
概述
¥Overview
一对多 (1-n) 关系是指关系一侧的一条记录可以连接到另一侧的零个或多个记录的关系。在以下示例中,User
和 Post
模型之间存在一对多关系:
¥One-to-many (1-n) relations refer to relations where one record on one side of the relation can be connected to zero or more records on the other side. In the following example, there is one one-to-many relation between the User
and Post
models:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}
注意
posts
字段在底层数据库模式中不存在 "manifest"。在关系的另一侧,带注释的关系字段author
及其关系标量authorId
表示关系中将外键存储在基础数据库中的一侧。¥The
posts
field does not "manifest" in the underlying database schema. On the other side of the relation, the annotated relation fieldauthor
and its relation scalarauthorId
represent the side of the relation that stores the foreign key in the underlying database.
这种一对多关系表达如下:
¥This one-to-many relation expresses the following:
-
"一个用户可以有零个或多个帖子"
¥"a user can have zero or more posts"
-
"帖子必须始终有作者"
¥"a post must always have an author"
在前面的示例中,Post
模型的 author
关系字段引用了 User
模型的 id
字段。你还可以引用不同的字段。在这种情况下,你需要使用 @unique
属性来标记该字段,以保证每个 Post
上只有一个 User
连接。在以下示例中,author
字段引用 User
模型中的 email
字段,该字段用 @unique
属性标记:
¥In the previous example, the author
relation field of the Post
model references the id
field of the User
model. You can also reference a different field. In this case, you need to mark the field with the @unique
attribute, to guarantee that there is only a single User
connected to each Post
. In the following example, the author
field references an email
field in the User
model, which is marked with the @unique
attribute:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
email String @unique // <-- add unique attribute
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
authorEmail String
author User @relation(fields: [authorEmail], references: [email])
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique // <-- add unique attribute
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
authorEmail String
author User @relation(fields: [authorEmail], references: [email])
}
在 MySQL 中,你可以创建仅在引用端有索引且没有唯一约束的外键。在 Prisma ORM 版本 4.0.0 及更高版本中,如果你内省这种类型的关系,它将触发验证错误。要解决此问题,你需要向引用的字段添加 @unique
约束。
¥In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma ORM versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a @unique
constraint to the referenced field.
关系数据库中的多字段关系
¥Multi-field relations in relational databases
仅在关系数据库中,你还可以使用 多字段 ID/复合键定义此关系:
¥In relational databases only, you can also define this relation using multi-field IDs/composite key:
model User {
firstName String
lastName String
post Post[]
@@id([firstName, lastName])
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorFirstName, authorLastName], references: [firstName, lastName])
authorFirstName String // relation scalar field (used in the `@relation` attribute above)
authorLastName String // relation scalar field (used in the `@relation` attribute above)
}
数据库中的 1-n 关系
¥1-n relations in the database
关系数据库
¥Relational databases
以下示例演示如何在 SQL 中创建 1-n 关系:
¥The following example demonstrates how to create a 1-n relation in SQL:
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"authorId" integer NOT NULL,
FOREIGN KEY ("authorId") REFERENCES "User"(id)
);
由于 authorId
列(外键)上没有 UNIQUE
约束,因此你可以创建指向同一 User
记录的多个 Post
记录。这使得关系成为一对多而不是一对一。
¥Since there's no UNIQUE
constraint on the authorId
column (the foreign key), you can create multiple Post
records that point to the same User
record. This makes the relation a one-to-many rather than a one-to-one.
以下示例演示如何使用组合键(firstName
和 lastName
)在 SQL 中创建 1-n 关系:
¥The following example demonstrates how to create a 1-n relation in SQL using a composite key (firstName
and lastName
):
CREATE TABLE "User" (
firstName TEXT,
lastName TEXT,
PRIMARY KEY ("firstName","lastName")
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"authorFirstName" TEXT NOT NULL,
"authorLastName" TEXT NOT NULL,
FOREIGN KEY ("authorFirstName", "authorLastName") REFERENCES "User"("firstName", "lastName")
);
比较一对一和一对多关系
¥Comparing one-to-one and one-to-many relations
在关系数据库中,1-1 和 1-n 关系之间的主要区别在于,在 1-1 关系中,外键必须定义有 UNIQUE
约束。
¥In relational databases, the main difference between a 1-1 and a 1-n-relation is that in a 1-1-relation the foreign key must have a UNIQUE
constraint defined on it.
MongoDB
对于 MongoDB,Prisma ORM 目前使用 规范化数据模型设计,这意味着文档以与关系数据库类似的方式通过 ID 相互引用。
¥For MongoDB, Prisma ORM currently uses a normalized data model design, which means that documents reference each other by ID in a similar way to relational databases.
以下 MongoDB 文档代表 User
:
¥The following MongoDB document represents a User
:
{ "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" }
以下每个 Post
MongoDB 文档都有一个引用同一用户的 authorId
字段:
¥Each of the following Post
MongoDB documents has an authorId
field which references the same user:
[
{
"_id": { "$oid": "60d5922e00581b8f0062e3a9" },
"title": "How to make sushi",
"authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
},
{
"_id": { "$oid": "60d5922e00581b8f0062e3aa" },
"title": "How to re-install Windows",
"authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
}
]
比较一对一和一对多关系
¥Comparing one-to-one and one-to-many relations
在 MongoDB 中,1-1 和 1-n 之间的唯一区别是引用数据库中另一个文档的文档数量 - 没有任何限制。
¥In MongoDB, the only difference between a 1-1 and a 1-n is the number of documents referencing another document in the database - there are no constraints.
一对多关系中的必填和可选关系字段
¥Required and optional relation fields in one-to-many relations
1-n-关系始终有两个关系字段:
¥A 1-n-relation always has two relation fields:
-
未使用
@relation
注释的 list 关系字段¥a list relation field which is not annotated with
@relation
-
带注释的关系字段(包括其关系标量)
¥the annotated relation field (including its relation scalar)
1-n 关系的带注释的关系字段和关系标量可以都是可选的,也可以都是强制的。另一方面,该列表始终是强制性的。
¥The annotated relation field and relation scalar of a 1-n relation can either both be optional, or both be mandatory. On the other side of the relation, the list is always mandatory.
可选的一对多关系
¥Optional one-to-many relation
在以下示例中,你可以创建 Post
而不分配 User
:
¥In the following example, you can create a Post
without assigning a User
:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User? @relation(fields: [authorId], references: [id])
authorId String? @db.ObjectId
}
强制一对多关系
¥Mandatory one-to-many relation
在以下示例中,你在创建 Post
时必须分配 User
:
¥In the following example, you must assign a User
when you create a Post
:
- Relational databases
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}