【问题标题】:TypeORM db schema Users managementTypeORM db schema 用户管理
【发布时间】:2021-12-31 21:05:34
【问题描述】:

我首先说我是 TypeORM 的初学者,但我正在开发一个 Web 应用程序 (NestJs) 只是为了更深入地研究这个 ORM。 我无法“想到”一个有效的解决方案(在架构级别),它允许我在这种情况下管理用户以及与他们关联的数据:

我有三种类型的用户:“代理”、“用户管理员”和“主管”。代理必须只能看到他的数据,“用户管理员”必须能够看到他的数据和他下属的用户的数据。 在级联中,主管用户必须能够看到他的数据、经理和他下属的用户的数据。

-实例: 一个用户“X”被分配了任务,如果用户“X”有一个经理“R”,这个经理必须看到他的任务和“X”的任务。在级联中,如果经理有主管,主管必须能够看到他的任务,即“R”和“X”的任务。所有这些“关联”都应该有一个 dateStart 和 dateStart。 我已经看到有闭表模式,但是有了这个,我无法处理 dateStart 和 dateStart 字段。

有什么建议或例子吗? 非常感谢

【问题讨论】:

    标签: database database-design nestjs typeorm


    【解决方案1】:

    要实现这一点,您需要确保您的实体文件具有正确的关系装饰器。做出一些假设,但是:

    主管实体/模式:

    // imports typeorm
    import {Entity, Column, OneToMany} from 'typeorm';
    import {Manager} from '../../manager/entities/manager.entity';
    
    @Entity()
    export class Supervisor{
      // relationship column assuming supervisor has many managers
      @OneToMany(() => Manager, (manager) => manager.supervisor))
      managers: Manager[];
    }
    

    现在和经理一样:

    // imports typeorm
    import {Entity, Column, OneToMany, ManyToOne} from 'typeorm';
    import {Agent} from '../../agent/entities/agent.entity';
    import {Supervisor} from '../../supervisor/entities/supervisor.entity';
    
    @Entity()
    export class Manager{
    
      // reverse supervisor relationship
      @ManyToOne(() => Supervisor, (supervisor) => supervisor.managers)
      supervisor: Supervisor;
    
      // relationship column
      @OneToMany(() => Agent, (agent) => agent.manager))
      agents: Agent[];
    }
    

    现在介绍代理:

    // imports typeorm
    import {Entity, Column, ManyToOne} from 'typeorm';
    import {Manager} from '../../manager/entities/manager.entity';
    
    @Entity()
    export class Agent{
    
      // reverse manager relationship
      @ManyToOne(() => Manager, (manager) => manager.agents)
      manager: Manager;
    }
    

    如果您在实体中没有 {eager:true} 用于关系选项,您的查询将看起来不太漂亮,从主管的角度来看,它会是这样的:

     //import typeorm and other imports needed
    import {EntityRepository, Repository} from 'typeorm';
    import {Supervisor} from '../../supervisor/entities/supervisor.entity';
    
    @EntityRepository(Supervisor)
    export class SupervisorRepository extends Repository<Supervisor>{
      
      async getManagerAndAgents(supervisorId: string){
        let from = new Date().toISOString();
        let to = new Date().toISOString(); //pretend this is different than to
    
        return await this.createQueryBuilder('supervisor')
            .leftJoinAndSelect(
               'supervisor.managers', // relationship declared in entity
               'manager', // the name of the left join, think of it like 'AS' in sql
            )
            .leftJoinAndSelect(
              'manager.tasks', // relationship in manager entity to tasks
              'task',
              `task.date BETWEEN '${from}' AND '${to}'` // where condition
            )
            .leftJoinAndSelect(
              'manager.agents',
              'agent'
            )
            .leftJoinAndSelect(
              'agent.tasks',
              'agentTasks',
              `agentTasks.date BETWEEN '${from}' AND '${to}'` // or whatever you need (<, >)
            )
            .where('supervisor.id = :id', {id: supervisorId})
            .getOne();
      }
    
    }
    

    写完之后——亲爱的耶稣让我们有更好的方法,我不介意犯错。另外,请正确编写此代码。

    我从来没有找到不使用 createQueryBuilder 来使用日期的好方法。

    【讨论】:

    • 是的可能是一个解决方案,但这样我们需要为每个角色创建一个实体,无论如何感谢您的解决方案和您的时间
    • 如果这些只是角色,您可以拥有 supervisorId 和 mangerId 的字段,并适当地查询这些字段。对于角色,它实际上取决于您采用哪种方法来实现角色,例如声明或角色表。我的印象是那些是独立的实体。祝你好运找到解决方案。
    猜你喜欢
    • 2019-08-22
    • 2018-03-27
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多