Three dimensional relations in NestJS

24 Views Asked by At

I have three entities: User, Meal, Date.
Date:

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToMany,
  JoinTable,
} from 'typeorm';
import { User } from '../../users/entities/user.entity';
import { Meal } from '../../meals/entities/meal.entity';
import { Field, ID, ObjectType } from '@nestjs/graphql';

@Entity()
@ObjectType()
export class DateEntity {
  @PrimaryGeneratedColumn()
  @Field(() => ID, { description: 'a unique identifier' })
  id: number;

  @Column()
  date: string;

  @ManyToMany(() => User, (user) => user.dates)
  user: User[];

  @ManyToMany(() => Meal, (meal) => meal.dates)
  @JoinTable()
  meals: Meal[];
}

Meal:

import { ObjectType, Field, ID } from '@nestjs/graphql';
import { DateEntity } from 'src/date/entities/date.entity';
import {
  Column,
  Entity,
  JoinTable,
  ManyToMany,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
@ObjectType()
export class Meal {
  @PrimaryGeneratedColumn()
  @Field(() => ID, { description: 'a unique identifier' })
  id: number;

  @Column()
  title: string;

  @Column()
  price: number;

  @Column()
  type: string;

  @Column()
  description: string;

  @Column()
  imageSource: string;

  @ManyToMany(() => DateEntity, (date) => date.meals)
  @JoinTable()
  dates: DateEntity[];
}

User:

import { ObjectType, Field, ID } from '@nestjs/graphql';
import {
  Column,
  Entity,
  JoinTable,
  ManyToMany,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { Role } from '../enums/role.enum';
import { Payment } from 'src/payments/entities/payment.entity';
import { DateEntity } from 'src/date/entities/date.entity';

@Entity()
@ObjectType()
export class User {
  @PrimaryGeneratedColumn()
  @Field(() => ID, { description: 'a unique identifier' })
  id: number;

  @Column()
  username: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @Column({ enum: Role, default: Role.Regular })
  @Field(() => Role)
  role: Role;

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

  @ManyToMany(() => Payment, (payment) => payment.user)
  payments: Payment[];

  @ManyToMany(() => DateEntity, (date) => date.user)
  @JoinTable()
  dates: DateEntity[];
}

I created simple service in order to check behavior of the relations:
Service:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Meal } from 'src/meals/entities/meal.entity';
import { Repository } from 'typeorm';
import { DateEntity } from './entities/date.entity';
import { CreateMealDateUserInput } from './dto/create-meal-date-user.dto';
import { User } from 'src/users/entities/user.entity';

@Injectable()
export class DateService {
  constructor(
    @InjectRepository(Meal)
    private readonly mealRepository: Repository<Meal>,
    @InjectRepository(DateEntity)
    private readonly dateRepository: Repository<DateEntity>,
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  async create(createMealDateUserInput: CreateMealDateUserInput) {
    const dateEntity = await this.dateRepository.findOneOrFail({
      where: { date: createMealDateUserInput.date },
    });

    const mealEntity = await this.mealRepository.findOneOrFail({
      where: { id: createMealDateUserInput.mealId },
    });

    const userEntity = await this.userRepository.findOneOrFail({
      where: { id: createMealDateUserInput.userId },
    });

    if (!dateEntity.meals) {
      const newDateEntity = {
        ...dateEntity,
        user: [userEntity],
        meals: [mealEntity],
      };
      return this.dateRepository.save(newDateEntity);
    }

    const meals = [...dateEntity.meals, mealEntity];

    const newDateEntity = {
      ...dateEntity,
      user: [userEntity],
      meals,
    };
    return this.dateRepository.save(newDateEntity);
  }
}

Resolver (Controller):

import { Body, Controller, Post } from '@nestjs/common';
import { Auth } from 'src/iam/authentication/decorators/auth.decorator';
import { AuthType } from 'src/iam/authentication/enums/auth-type.enum';
import { CreateMealDateUserInput } from './dto/create-meal-date-user.dto';
import { DateService } from './date.service';

@Controller('date')
@Auth(AuthType.None)
export class DateResolver {
  constructor(private dateService: DateService) {}

  @Post('createMealDateUser')
  async checkout(@Body() createMealDateUserInput: CreateMealDateUserInput) {
    return this.dateService.create(createMealDateUserInput);
  }
}

After I added Meal in User in Date I can see that one date is connected with one meal.
Example:
date <-> meals table
user <-> date table

The problem is that I would like to connect One user with Many dates that are connected with Many Meals, but for each user separately.

How can I achieve it in NestJS typeorm?
I can image in as follow:
Table DatesMealsUsers consists with 3 columns: Date, Meal, User.
Each row has separate ids, i.e. dateId: 1, mealId: 1, userId: 1,
dateId: 1, mealId:2, userId:1,
etc.

0

There are 0 best solutions below