Prisma ORM 第四章 表之间关系的建立和删除

1. content

在 Prisma 中,connect 是一个用于建立关系的选项,主要用于在创建或更新记录时将现有记录关联起来。connect 允许你在不重新创建相关记录的情况下,将它们链接到当前记录。这在处理多对多关系或多对一关系时特别有用。

1. connect 的作用

connect 通常用于以下几种情况:

  • 创建记录时建立关系:在创建新记录时,将其与已存在的记录关联。
  • 更新记录时建立关系:在更新现有记录时,将其与已存在的记录关联。

2. 一对多关系中的content

假设你有一个 User 模型和一个 Post 模型,其中 User 可以有多篇 Post。

  • 模型定义
prisma 复制代码
model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
  age   Int
  posts Post[]
}

model Post {
  id      Int     @id @default(autoincrement())
  title   String
  content String
  author  User    @relation(fields: [authorId], references: [id])
  authorId Int
}
  1. 创建用户并关联帖子
typescript 复制代码
const user = await prisma.user.create({
  data: {
    name: 'John Doe',
    email: 'john.doe@example.com',
    age: 25,
    posts: {
      connect: [{ id: 1 }, { id: 2 }], // 关联已存在的帖子
    },
  },
});

console.log(user);
  1. 更新记录时使用 connect
    假设你已经有一个用户,现在想为该用户添加新的帖子。
  • 更新用户并关联帖子
typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
  	email: "newEmail@"
    posts: {
      connect: [{ id: 3 }], // 关联新的帖子
    },
  },
});

console.log(user);

3. 多对多关系中的 connect

假设你有一个 User 模型和一个 Role 模型,其中 User 可以有多个 Role,Role 也可以属于多个 User。

  • 模型定义
prisma 复制代码
model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
  age   Int
  roles Role[]  @relation("UserRoles")
}

model Role {
  id    Int     @id @default(autoincrement())
  name  String
  users User[]  @relation("UserRoles")
}
  1. 创建用户并关联角色
typescript 复制代码
const user = await prisma.user.create({
  data: {
    name: 'John Doe',
    email: 'john.doe@example.com',
    age: 25,
    roles: {
      connect: [{ id: 1 }, { id: 2 }], // 关联已存在的角色
    },
  },
});

console.log(user);
  1. 更新用户并关联角色
typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    roles: {
      connect: [{ id: 3 },{ id: 4 }], // 关联新的角色
    },
  },
});

console.log(user);

2. connectOrCreate

作用: 用于在创建或更新记录时,将现有记录关联起来,或者在关联记录不存在时创建它。

1. 基本概念

connectOrCreate 选项允许你在关联记录不存在时创建它,并将其与当前记录关联。它接受一个数组,每个元素都是一个对象,包含 where 和 create 两个属性:

  • where:用于查找现有记录的条件。如果找到匹配的记录,则将其关联。
  • create:如果 where 条件没有找到匹配的记录,则使用 create 中提供的数据创建新记录,并将其关联。

2. 示例

假设你有一个 User 模型和一个 Role 模型,其中 User 可以有多个 Role,Role 也可以属于多个 User。

  • 模型定义
prisma 复制代码
model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
  age   Int
  roles Role[]  @relation("UserRoles")
}

model Role {
  id    Int     @id @default(autoincrement())
  name  String  @unique
  users User[]  @relation("UserRoles")
}

3. 创建用户并连接或创建角色

typescript 复制代码
const user = await prisma.user.create({
  data: {
    name: 'John Doe',
    email: 'john.doe@example.com',
    age: 25,
    roles: {
      connectOrCreate: [
        {
          where: { name: 'Admin' },
          create: { name: 'Admin' },
        },
        {
          where: { name: 'Editor' },
          create: { name: 'Editor' },
        },
      ],
    },
  },
});

console.log(user);
  • 在这个示例中:

    • 如果 Role 表中已经存在 name 为 Admin 的记录,则将其与新创建的用户关联。
    • 如果 Role 表中不存在 name 为 Admin 的记录,则创建一个新的 Role 记录,并将其与新创建的用户关联。
    • 同样的逻辑适用于 Editor 角色。

4. 更新用户并连接或创建角色

typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    roles: {
      connectOrCreate: [
        {
          where: { name: 'Moderator' },
          create: { name: 'Moderator' },
        },
      ],
    },
  },
});

console.log(user);
  • 在这个示例中:

    • 如果 Role 表中已经存在 name 为 Moderator 的记录,则将其与用户 ID 为 1 的用户关联。
    • 如果 Role 表中不存在 name 为 Moderator 的记录,则创建一个新的 Role 记录,并将其与用户 ID 为 1 的用户关联。

5. 处理唯一约束

connectOrCreate 特别适合处理具有唯一约束的字段。例如,Role 模型中的 name 字段被标记为 @unique,这意味着每个角色名称必须是唯一的。connectOrCreate 确保不会创建重复的角色记录。

6. 错误处理

如果 where 条件不唯一,connectOrCreate 会抛出错误。因此,确保 where 条件能够唯一标识记录。

  • 示例:处理错误
typescript 复制代码
try {
  const user = await prisma.user.create({
    data: {
      name: 'John Doe',
      email: 'john.doe@example.com',
      age: 25,
      roles: {
        connectOrCreate: [
          {
            where: { name: 'Admin' },
            create: { name: 'Admin' },
          },
          {
            where: { name: 'Admin' }, // 重复的 where 条件
            create: { name: 'Admin' },
          },
        ],
      },
    },
  });

  console.log(user);
} catch (error) {
  console.error('Error:', error.message);
}

在这个示例中,由于 where 条件重复,connectOrCreate 会抛出错误。

3. disconnect

作用: 用于断开现有记录之间的关系。

1. 基本概念

disconnect 选项允许你在更新记录时断开与现有记录的关联。它接受一个数组,每个元素都是一个对象,包含用于查找要断开关联的记录的条件。

2. 示例

假设你有一个 User 模型和一个 Role 模型,其中 User 可以有多个 Role,Role 也可以属于多个 User。

  • 模型定义
prisma 复制代码
model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
  age   Int
  roles Role[]  @relation("UserRoles")
}

model Role {
  id    Int     @id @default(autoincrement())
  name  String  @unique
  users User[]  @relation("UserRoles")
}

3. 断开用户与角色的关联

typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    roles: {
      disconnect: [{ id: 2 }], // 断开与角色 ID 为 2 的关联
    },
  },
});

console.log(user);

在这个示例中:

  • where 条件指定了要更新的用户(ID 为 1)。
  • data 对象中的 roles 字段使用了 disconnect 选项,传入了一个数组,数组中的每个对象都包含一个 id 属性,用于指定要断开关联的角色。

4. 断开多个关联

你可以在 disconnect 数组中指定多个对象,以断开多个关联。

typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    roles: {
      disconnect: [{ id: 2 }, { id: 3 }], // 断开与角色 ID 为 2 和 3 的关联
    },
  },
});

console.log(user);

在这个示例中:

  • disconnect 数组中包含了两个对象,分别指定了要断开关联的角色 ID 为 2 和 3。

5. 使用其他条件断开关联

除了使用 id,你还可以使用其他唯一字段来断开关联。

typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    roles: {
      disconnect: [{ name: 'Editor' }], // 断开与角色名称为 'Editor' 的关联
    },
  },
});

console.log(user);

在这个示例中:

  • disconnect 数组中的对象使用了 name 字段来指定要断开关联的角色。

6. 断开所有关联

如果你想断开用户与所有角色的关联,可以使用 set 选项并将值设置为空数组。

typescript 复制代码
const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    roles: {
      set: [], // 断开与所有角色的关联
    },
  },
});

console.log(user);

在这个示例中:

  • set 选项将 roles 设置为空数组,从而断开用户与所有角色的关联。

7. 错误处理

如果 disconnect 中的条件不匹配任何记录,Prisma 不会抛出错误,而是简单地忽略该条件。因此,你需要确保条件是正确的,以避免意外的行为。

typescript 复制代码
try {
  const user = await prisma.user.update({
    where: {
      id: 1,
    },
    data: {
      roles: {
        disconnect: [{ id: 999 }], // 不存在的角色 ID
      },
    },
  });

  console.log(user);
} catch (error) {
  console.error('Error:', error.message);
}

在这个示例中:

  • disconnect 中的 id: 999 不存在,Prisma 会忽略该条件,不会抛出错误。
相关推荐
YUELEI1182 个月前
Prisma ORM 第一章 安装与使用
prisma
白雾茫茫丶2 个月前
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
postgresql·vue3·vite·pinia·nest.js·prisma
stonefisher5 个月前
推荐Nodejs下高效存储树到数据库工具库-FlexTree
javascript·数据库·nodejs·tree·prisma
逐星ing7 个月前
Prisma是什么:现代数据库工具和ORM
数据库·prisma
亮子AI1 年前
【PostgreSQL】Ubuntu 下使用 Prisma 的初始化流程
数据库·ubuntu·postgresql·prisma
愧怍121 年前
有了 Prisma,就别用 TypeORM 了
typescript·orm·prisma
超级架构师1 年前
【全栈开发】使用NestJS、Angular和Prisma 打造全栈Typescript开发
前端·typescript·nestjs·angular·angular.js·graphql·prisma
芝士思维1 年前
NextJS开发:Prisma开启SQL日志输出
数据库·sql·nextjs·prisma
昆吾kw1 年前
Koa + Prisma 快速入门
mysql·node.js·prisma·koa.js