nestjs结合prisma关系模型,多对多及多对多对多

prisma关系模型

多对多

注意:id不能使用bigint!!!!!
官网的例子

model Post {
  id         Int                 @id @default(autoincrement())
  title      String
  categories CategoriesOnPosts[]
}

model Category {
  id    Int                 @id @default(autoincrement())
  name  String
  posts CategoriesOnPosts[]
}

model CategoriesOnPosts {
  post       Post     @relation(fields: [postId], references: [id])
  postId     Int // relation scalar field (used in the `@relation` attribute above)
  category   Category @relation(fields: [categoryId], references: [id])
  categoryId Int // relation scalar field (used in the `@relation` attribute above)
  assignedAt DateTime @default(now())
  assignedBy String

  @@id([postId, categoryId])
}

本人项目

model Menu {
  id          Int            @id @default(autoincrement())
  // 父菜单ID
  parentId    Int            @default(0) @map("parent_id")
  // 父节点ID路径
  treePath    String?        @map("tree_path")
  // 菜单名称
  name        String
  // 菜单类型(1:菜单 2:目录 3:外链 4:按钮)
  type        Int
  // 路由路径(浏览器地址栏路径)
  path        String?
  // 组件路径(vue页面完整路径,省略.vue后缀)
  component   String?
  // 权限标识
  perm        String?
  // 显示状态(1-显示;0-隐藏)
  visible     Int?           @default(1)
  // 排序
  sort        Int?           @default(0)
  // 菜单图标
  icon        String?
  // 跳转路径
  redirect    String?
  createTime  DateTime?      @default(now()) @map("create_time")
  updateTime  DateTime?      @default(now()) @map("update_time")
  // 【目录】只有一个子路由是否始终显示(1:是 0:否)
  always_show Int?
  // 【菜单】是否开启页面缓存(1:是 0:否)
  keep_alive  Int?
  roles       RolesOnMenus[]
}

model User {
  id         Int            @id @default(autoincrement())
  //用户名
  username   String?
  //昵称
  nickname   String?
  //性别((1:男;2:女))
  gender     Int            @default(1)
  //密码
  password   String?
  //部门ID
  deptId     Int?           @map("dept_id")
  //用户头像
  avatar     String?
  //联系方式
  mobile     String?
  // 用户状态((1:正常;0:禁用))
  status     Int            @default(1)
  // 用户邮箱
  email      String?
  // 逻辑删除标识(0:未删除;1:已删除)
  deleted    Int?           @default(0)
  createTime DateTime?      @default(now()) @map("create_time")
  updateTime DateTime?      @default(now()) @map("update_time")
  roles      UsersOnRoles[]
}

model Role {
  id         Int            @id @default(autoincrement())
  // 角色名称
  name       String
  // 角色编码
  code       String?
  // 排序
  sort       Int?           @default(0)
  // 角色状态(1-正常;0-停用)
  status     Int?           @default(1)
  // 数据权限(0-所有数据;1-部门及子部门数据;2-本部门数据;3-本人数据)
  dataScope  Int            @map("data_scope")
  // 逻辑删除标识(0:未删除;1:已删除)
  deleted    Int?           @default(0)
  createTime DateTime?      @default(now()) @map("create_time")
  updateTime DateTime?      @default(now()) @map("update_time")
  menus      RolesOnMenus[]
  users      UsersOnRoles[]
}

model UsersOnRoles {
  user   User @relation(fields: [userId], references: [id])
  userId Int // relation scalar field (used in the `@relation` attribute above)
  role   Role @relation(fields: [roleId], references: [id])
  roleId Int // relation scalar field (used in the `@relation` attribute above)

  @@id([userId, roleId])
  @@map("user_role")
}

model RolesOnMenus {
  role   Role @relation(fields: [roleId], references: [id])
  roleId Int // relation scalar field (used in the `@relation` attribute above)
  menu   Menu @relation(fields: [menuId], references: [id])
  menuId Int // relation scalar field (used in the `@relation` attribute above)

  @@id([roleId, menuId])
  @@map("role_menu")
}

查询多对多 用户和角色

async findOne(id: number) {
    const result = await this.prisma.user.findUnique({
      where: {
        id,
      },
      include: {
        roles: {
          select: {
            role: {
              select: {
                code: true,
              },
            },
          },
        },
      },
    });
    return result;
}
{
        "id": 2,
        "username": "admin",
        "nickname": "系统管理员",
        "gender": 1,
        "deptId": 1,
        "avatar": "https://oss.youlai.tech/youlai-boot/2023/05/16/811270ef31f548af9cffc026dfc3777b.gif",
        "mobile": "17621210366",
        "status": 1,
        "email": "",
        "deleted": 0,
        "createTime": "2019-10-10T13:41:22.000Z",
        "updateTime": "2022-07-31T12:39:30.000Z",
        "roles": [
            {
                "role": {
                    "code": "ADMIN"
                }
            }
        ]
    },

扁平化

async findOne(id: number) {  
	const result = await this.prisma.user.findUnique({
      where: {
        id,
      },
      include: {
        roles: {
          select: {
            role: true,
          },
        },
      },
    });

    const roles = result.roles.map((item) => item.role.code);

    const newUser = {
      ...result,
      roles,
    };

    return newUser;
}
{
        "id": 2,
        "username": "admin",
        "nickname": "系统管理员",
        "gender": 1,
        "deptId": 1,
        "avatar": "https://oss.youlai.tech/youlai-boot/2023/05/16/811270ef31f548af9cffc026dfc3777b.gif",
        "mobile": "17621210366",
        "status": 1,
        "email": "",
        "deleted": 0,
        "createTime": "2019-10-10T13:41:22.000Z",
        "updateTime": "2022-07-31T12:39:30.000Z",
        "roles": [
            "ADMIN"
        ]
    },

多对多对多

用户和角色多对多,角色又和菜单多对多,一次查询出来

async findOne(id: number) {
    const result = await this.prisma.user.findUnique({
      where: {
        id,
      },
      include: {
        roles: {
          select: {
            role: {
              select: {
                code: true,
                menus: {
                  select: {
                    menu: {
                      select: {
                        perm: true, // 选择你想包含的菜单字段
                      },
                    },
                  },
                },
              },
            },
          },
        },
      },
    });

    // 获取用户对应的角色数组
    const rolesCodes = result.roles.map((item) => item.role.code);

    // 获取角色对应的菜单权限数组
    const rolesMenusPerm = result.roles
      .map((item) => {
        return item.role.menus
          .filter((item2) => item2.menu.perm) // 过滤出 perm 有值的元素
          .map((item2) => item2.menu.perm);
      })
      .flat();
    // console.log(rolesMenusPerm);

    const newUser = {
      ...result,
      roles: rolesCodes,
      perm: rolesMenusPerm,
    };

    return newUser;
  }

最终结果

{
    "data": {
        "id": 2,
        "username": "admin",
        "nickname": "系统管理员",
        "gender": 1,
        "deptId": 1,
        "avatar": "https://oss.youlai.tech/youlai-boot/2023/05/16/811270ef31f548af9cffc026dfc3777b.gif",
        "mobile": "17621210366",
        "status": 1,
        "email": "",
        "deleted": 0,
        "createTime": "2019-10-10T13:41:22.000Z",
        "updateTime": "2022-07-31T12:39:30.000Z",
        "roles": [
            "ADMIN"
        ],
        "perm": [
            "sys:user:add",
            "sys:user:edit",
            "sys:user:delete",
            "sys:role:add",
            "sys:role:edit",
            "sys:role:delete",
            "sys:menu:add",
            "sys:menu:edit",
            "sys:menu:delete",
            "sys:dept:add",
            "sys:dept:edit",
            "sys:dept:delete",
            "sys:dict_type:add",
            "sys:dict_type:edit",
            "sys:dict_type:delete",
            "sys:dict:add",
            "sys:dict:edit",
            "sys:dict:delete",
            "sys:user:password_reset"
        ]
    },
    "code": "00000",
    "msg": "一切ok"
}
  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@icapps/nestjs-prisma是一个基于Prisma ORM的NestJS模块,它可以帮助我们快速地集成Prisma ORM到NestJS应用程序中。如果你需要集成多个数据库,可以按照以下步骤进行: 1. 首先,在项目中安装Prisma ORM,并为每个数据库创建一个Prisma schema。 2. 创建一个新的Prisma client实例,该实例将连接到特定的数据库。你可以在NestJS的providers中创建多个Prisma服务,每个服务都使用不同的Prisma client实例。 3. 在使用@icapps/nestjs-prisma模块时,你可以将不同的Prisma服务注入到不同的模块或控制器中,以便在应用程序中访问多个数据库。 下面是一个简单的示例,展示了如何在NestJS应用程序中集成多个Prisma服务: ```typescript import { Module } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; import { PrismaService } from '@icapps/nestjs-prisma'; @Module({ providers: [ { provide: 'DB_ONE', useFactory: () => new PrismaClient({ datasources: { db: { url: 'XXXXXXXX' } } }), }, { provide: 'DB_TWO', useFactory: () => new PrismaClient({ datasources: { db: { url: 'XXXXXXXX' } } }), }, { provide: 'DB_THREE', useFactory: () => new PrismaClient({ datasources: { db: { url: 'XXXXXXXX' } } }), }, { provide: 'DB_FOUR', useFactory: () => new PrismaClient({ datasources: { db: { url: 'XXXXXXXX' } } }), }, PrismaService, ], }) export class AppModule {} ``` 在上面的示例中,我们创建了四个不同的Prisma服务,每个服务使用不同的Prisma client实例,并将它们的provider名称分别设置为`'DB_ONE'`、`'DB_TWO'`、`'DB_THREE'`和`'DB_FOUR'`。然后,我们将这些服务注入到应用程序的providers列表中,并为每个服务指定相应的Prisma client实例。最后,我们还将@icapps/nestjs-prisma的PrismaService也添加到providers中,以便在整个应用程序中访问Prisma服务。 当我们需要在控制器或模块中使用Prisma时,可以通过注入相应的Prisma服务来访问不同的数据库,例如: ```typescript import { Controller, Get, Inject } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Controller('users') export class UsersController { constructor( @Inject('DB_ONE') private readonly dbOne: PrismaClient, @Inject('DB_TWO') private readonly dbTwo: PrismaClient, @Inject('DB_THREE') private readonly dbThree: PrismaClient, @Inject('DB_FOUR') private readonly dbFour: PrismaClient, ) {} @Get() async getUsers() { const users1 = await this.dbOne.user.findMany(); const users2 = await this.dbTwo.user.findMany(); const users3 = await this.dbThree.user.findMany(); const users4 = await this.dbFour.user.findMany(); return { users1, users2, users3, users4 }; } } ``` 在上面的示例中,我们在控制器中注入了四个不同的Prisma服务,每个服务使用不同的Prisma client实例。然后,我们可以使用这些服务来查询不同的数据库,并将结果返回给客户端。 希望这个示例能够帮助你实现NestJS集成多个数据库。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值