@DanceMonkeyTime

Как правильно создать связи в базе данных?

Всем привет. Есть у меня таблицы users, candidate, recruiter

Когда я создаю users, то я автоматически создаю candidate или recruiter в зависимости какую роль пользователь на фронте выбрал.
Колонки ( photoURL, username ) в каждой из таблиц могут быть пустыми.

На данный момент у меня есть только такая связь ( one-to-one relation )<br />
5f812044ab32e626409848.png


Создаю я по такому типу:
Код
const credentials = {
   username: "One",
   photoURL: "http://image-way.jpg"
   email: "one@gmail.com",
   role: "recruiter"
}

user = await this.userService.create(credentials);
        const userCreationData = {
          fullName: credentials.username,
          profilePhoto: credentials.photoURL,
        };
        this.userService.createUserByRole(user, userCreationData);
        const jwtAccessToken = this.generateAccessToken(user);
        response = {
          accessToken: jwtAccessToken,
          redirectURL: `/sign-up/${user.role}`,
        };





export class CreateUserByRoleDto {
  fullName: string;
  profilePhoto: string;
}
  async createUserByRole(
    userData: User,
    createUserByRoleDto?: CreateUserByRoleDto,
  ): Promise<void> {
    const user = await this.userRepository.findOne({ email: userData.email });

    if (!user) throw new NotFoundException('User not found');

    let createdUser: Recruiter | Candidate;
    if (user.role === 'recruiter') {
      createdUser = this.recruiterRepository.create();
      createdUser = Object.assign(createdUser, createUserByRoleDto, {
        user, // вот это создает мне userId в таблице recruiter
      });
    } else {
      createdUser = this.candidateRepository.create();
      createdUser = Object.assign(createdUser, createUserByRoleDto, {
        user, // вот это создает мне userId в таблице candidate
      });
    }

    await createdUser.save();
  }


Users typeorm entity

import {
  BaseEntity,
  Entity,
  PrimaryGeneratedColumn,
  Column,
  Unique,
} from 'typeorm';
import { hash } from 'bcrypt';

@Entity()
@Unique(['email'])
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  role: string;

  @Column()
  email: string;

  @Column()
  salt: string;

  @Column()
  password: string;

  @Column({ default: false })
  agreement: boolean;

  @Column({ default: '' })
  photoURL: string;

  @Column({ default: '' })
  username: string;

  async validatePassword(password: string): Promise<boolean> {
    const hashedPassword = await hash(password, this.salt);
    return hashedPassword === this.password;
  }
}



Candidate typeorm entity

import { User } from 'src/users/user.entity';
import {
  BaseEntity,
  Column,
  Entity,
  JoinColumn,
  OneToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
export class Candidate extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @OneToOne(
    type => User,
    (user: User) => user.id,
  )
  @JoinColumn()
  user: number; // Вот тут вся магия

  @Column({ default: '' })
  primaryCategory: string;

  @Column({ default: '' })
  experience: string;

  @Column({ default: 0 })
  salary: number;

  @Column({ default: '' })
  location: string;

  @Column({ default: '' })
  fullName: string;

  /** It should be related with another table which get files from aws s3 */
  @Column({ default: '' })
  profilePhoto: string;
}



Вопрос: Делать ли мне OneToOne связь с другими похожими полями которые существуют и в users и в candidate и в recruiter (photoURL, username )?
Только тогда оно будет выглядеть вот так
5f8122e2c0948668463110.png
  • Вопрос задан
  • 64 просмотра
Пригласить эксперта
Ответы на вопрос 1
Поверьте, критерии "правильности" у каждого будут свои.

Делать ли мне OneToOne связь с другими похожими полями

Нет. Подумайте, для какой цели вообще существуют связи на уровне БД. Объясните себе, какую задачи они должны решать, что дадут предложенные вами связи?

Несколько замечаний по текущей структуре:
  1. В целом подобная структура рассчитана на то, что пользователь может быть связан с несколькими записями в отдельных таблицах. Если у вас связь 1-1, логичнее сделать так:
    • в отдельных таблицах убрать id, а в качестве первичного ключа использовать userId, связь по нему остается [предпочтительно];
    • если же вам нужны именно id в отдельных таблицах, то в user наряду с ролью можно хранить id связанной записи (relationId), тогда связь реализовывать уже на уровне приложения, а не БД. Или, на крайний случай, в user хранить recruterId и candidateId [не желательно, но как вариант].

  2. username и fullName - обычно это разные данные: username в паре с password используется для авторизации, а fullName - это ФИО.
  3. Если photoURL и profilePhoto - это одно и то же, зачем дублировать в отдельные таблицы?
  4. Лучше перенести все общие поля в user.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы