跳至主要内容

一对多关系

本页介绍了一对多关系,并解释了如何在 Prisma 模式中使用它们。

概述

一对多 (1-n) 关系指的是一种关系,其中一方的一个记录可以连接到另一方的零个或多个记录。在以下示例中,UserPost 模型之间存在一对多关系

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
}

注意 posts 字段不会在底层数据库模式中“显现”。在关系的另一边,带注释的关系字段 author 及其关系标量 authorId 表示在底层数据库中存储外键的一侧。

这种一对多关系表达以下意思

  • "一个用户可以拥有零个或多个帖子"
  • "一个帖子必须始终有一个作者"

在前面的示例中,Post 模型的 author 关系字段引用了 User 模型的 id 字段。你也可以引用其他字段。在这种情况下,你需要用 @unique 属性标记该字段,以确保只有一个 User 连接到每个 Post。在以下示例中,author 字段引用了 User 模型中的 email 字段,该字段用 @unique 属性标记

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])
}
警告

在 MySQL 中,你可以只在引用端创建一个带索引的外键,而不是唯一约束。在 Prisma ORM 4.0.0 及更高版本中,如果你内省这种类型的关系,它会触发验证错误。要解决此问题,你需要在引用字段添加 @unique 约束。

关系型数据库中的多字段关系

仅在 **关系型数据库** 中,你还可以使用 多字段 ID/复合键来定义这种关系

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 关系

关系型数据库

以下示例演示了如何在 SQL 中创建 1-n 关系

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 记录**。这使得关系成为一对多,而不是一对一。

以下示例演示了如何使用复合键(firstNamelastName)在 SQL 中创建 1-n 关系

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")
);

比较一对一和一对多关系

在关系型数据库中,1-1 和 1-n 关系之间的主要区别在于,在 1-1 关系中,外键必须定义 UNIQUE 约束。

MongoDB

对于 MongoDB,Prisma ORM 目前使用的是 规范化数据模型设计,这意味着文档通过 ID 互相引用,类似于关系型数据库。

以下 MongoDB 文档表示一个 User

{ "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" }

以下每个 Post MongoDB 文档都有一个 authorId 字段,该字段引用了同一个用户

[
{
"_id": { "$oid": "60d5922e00581b8f0062e3a9" },
"title": "How to make sushi",
"authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
},
{
"_id": { "$oid": "60d5922e00581b8f0062e3aa" },
"title": "How to re-install Windows",
"authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
}
]

比较一对一和一对多关系

在 MongoDB 中,1-1 和 1-n 之间的唯一区别是引用数据库中另一个文档的文档数量 - 没有约束。

一对多关系中的必填和可选关系字段

1-n 关系始终有两个关系字段

1-n 关系的带注释的关系字段和关系标量可以同时为可选,也可以同时为必填。在关系的另一侧,列表始终为必填

可选一对多关系

在以下示例中,你可以创建一个 Post,而无需为其分配一个 User

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?
}

必填一对多关系

在以下示例中,你必须在创建 Post 时为其分配一个 User

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
}