Introducci贸n

1

驴Ya terminaste el Curso de NestJS: Programaci贸n Modular?

2

Platzi Store: presentaci贸n del proyecto e instalaci贸n

Database

3

C贸mo instalar Docker para este proyecto

4

Configuraci贸n de PostgresSQL en Docker

5

Explorando postgres con interfaces gr谩ficas y terminal

6

Integraci贸n de node-postgres con NestJS

7

Conexi贸n como inyectable y ejecutando un SELECT

8

Usando variables de ambiente

TypeORM

9

驴Qu茅 es un ORM? Instalando y configurando TypeORM Module

10

Creando tu primera entidad

11

TypeORM: active record vs. repositories

12

Crear, actualizar y eliminar

13

Cambiar a Mysql demo (opcional)

Migraciones

14

Sync Mode vs. Migraciones en TypeORM

15

Configurando migraciones y npm scripts

16

Corriendo migraciones

17

Modificando una entidad

Relaciones

18

Relaciones uno a uno

19

Resolviendo la relaci贸n uno a uno en el controlador

20

Relaciones uno a muchos

21

Resolviendo la relaci贸n uno a muchos en el controlador

22

Relaciones muchos a muchos

23

Resolviendo la relaci贸n muchos a muchos en el controlador

24

Manipulaci贸n de arreglos en relaciones muchos a muchos

25

Relaciones muchos a muchos personalizadas

26

Resolviendo la relaci贸n muchos a muchos personalizada en el controlador

Consultas

27

Paginaci贸n

28

Filtrando precios con operadores

29

Agregando indexadores

30

Modificando el naming

31

Serializar

Migraci贸n a NestJS 9 y TypeORM 0.3

32

Actualizando Dependencias para NestJS 9

33

Cambios en TypeORM 0.3

34

Migraciones en TypeORM 0.3

Pr贸ximos pasos

35

C贸mo solucionar una referencia circular entre m贸dulos

36

Contin煤a con el Curso de NestJS: Autenticaci贸n con Passport y JWT

No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Relaciones muchos a muchos

22/36
Recursos

Aportes 5

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Apuntes

category.entity

// src\products\entities\category.entity.ts
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class Category {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ type: 'varchar', length: 255, unique: true})
  name: string;

  @CreateDateColumn({
    type: 'timestamptz',
    default: ()=> 'CURRENT_TIMESTAMP'
  })
  createAt: Date;

  @UpdateDateColumn({
    type: 'timestamptz',
    default: ()=> 'CURRENT_TIMESTAMP'
  })
  updateAt: Date;
}

category.service

// src\products\services\categories.service.ts

import { Injectable, NotFoundException } from '@nestjs/common';

import { Category } from '../entities/category.entity';
import { CreateCategoryDto, UpdateCategoryDto } from '../dtos/category.dtos';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { merge } from 'rxjs';

@Injectable()
export class CategoriesService {
  constructor(
    @InjectRepository(Category) private categoryRepo: Repository<Category>
  ){}

  findAll() {
    return this.categoryRepo.find();
  }

  async findOne(id: number) {
    const category = await this.categoryRepo.findOne(id);
    if (!category) {
      throw new NotFoundException(`Category #${id} not found`);
    }
    return category;
  }

  create(data: CreateCategoryDto) {
    const newCategory = this.categoryRepo.create(data);
    return this.categoryRepo.save(newCategory);
  }

  async update(id: number, changes: UpdateCategoryDto) {
    const category = await this.findOne(id);
    this.categoryRepo.merge(category, changes);
    return this.categoryRepo.save(category);
  }

  remove(id: number) {
    return this.categoryRepo.delete(id);
  }
}

products module


// src\products\products.module.ts
@Module({
...
// Agregamos a category
  imports:[TypeOrmModule.forFeature([Product, Brand, Category])],
...
})

Creando la relacion

// src\products\entities\category.entity.ts
@ManyToMany(()=>Product, (product)=>product.categories)
@JoinTable() // Solo debe estar en una entidad
products: Product[]

// src\products\entities\product.entity.ts
@ManyToMany(()=>Category, (category)=>category.products)
categories: Category[];

Crear y correr la migracion

npm run migrations:generate -- create-categories
npm run migrations:run

Tal vez les sirva para nombrar las columnas de las relaciones.

@JoinColumn

Defines which side of the relation contains the join column with a foreign key and allows you to customize the join column name and referenced column name. Example:

@Entity()
export class Post {

@ManyToOne(type => Category)
@JoinColumn({
    name: "cat_id",
    referencedColumnName: "name"
})
category: Category;

}

@JoinTable

Used for many-to-many relations and describes join columns of the 鈥渏unction鈥 table. Junction table is a special, separate table created automatically by TypeORM with columns referenced to the related entities. You can change the name of the generated 鈥渏unction鈥 table and also the column names inside the junction table and their referenced columns with the joinColumn- and inverseJoinColumn attributes. Example:

@Entity()
export class Post {

@ManyToMany(type => Category)
@JoinTable({
    name: "question_categories",
    joinColumn: {
        name: "question",
        referencedColumnName: "id"
    },
    inverseJoinColumn: {
        name: "category",
        referencedColumnName: "id"
    }
})
categories: Category[];

}

Para personalizar los nombres de las tablas y llaves o referencias de la tabla

/user.entity.ts
@OneToOne(() => Customer, (customer) => customer.user, { nullable: true })
  @JoinColumn({
    name: "pk_customer",
    referencedColumnName: "id"
  })
  customer: Customer
/category.entity.ts
@ManyToMany(() => Product, (products) => products.categories, { nullable: true })
  products: Product[];
/product.entity.ts
 @ManyToOne(() => Brand, (brand) => brand.products, { nullable: true })
  brand: Brand

  @ManyToMany(() => Category, (categories) => categories.products, { nullable: true })

  @JoinTable({
    name: "product_categories",
    joinColumn: {
      name: "pk_product",
      referencedColumnName: "id"
    },
    inverseJoinColumn: {
      name: "pk_category",
      referencedColumnName: "id"
    }
  })
  categories: Category[];

Relaciones muchos a muchos

TypeORM nos permite maneja relaciones muchos a muchos, recordemos que para manejar relaciones muchos a muchos es necesario una tabla ternar铆a que nos permita manejar esta relaci贸n. Pero TypeORM ya nos abstrae este concepto de la tabla ternar铆a.

Para esto usaremos como caso de ejemplo las categor铆as y los productos, ya que un producto puede tener distintas categor铆as, y una categor铆a puede tener distintos productos.

Para esto, vamos a modificar primero la entidad de los productos:

  • **src/products/entities/product.entity.ts**:
import {
  // ...
  ManyToMany,
} from 'typeorm';

// importamos la entidad a la cual queremos hacer la relaci贸n
import { Category } from './category.entity';

@Entity()
export class Product {
  // ...

  // Este decorador especifica que la relaci贸n va a ser muchos a muchos
  // resuleve la envidad a la qu va a hacer referencia con una arrow function
  // debemos especificar en que atributo resuelve la entidad
  @ManyToMany(() => Category, (category) => category.products)
  categories: Category[];
}

Para crear la relaci贸n muchos a muchos, es obligatorio que le especifiquemos una comunicaci贸n bidireccional a la otra entidad, sin embargo, deber铆amos procurar hacer esto siempre debido a que es una buena pr谩ctica el que ambas entidades tengan una comunicaci贸n bidireccional.

  • **src/products/entities/category.entity.ts**:
import {
  // ...
  ManyToMany,
} from 'typeorm';

// importamos la entidad a la cual queremos hacer la relaci贸n
import { Product } from './product.entity';

@Entity()
export class Category {
  // ...

  // hacemos la relaci贸n bidireccional
  // resuleve la envidad a la qu va a hacer referencia con una arrow function
  // debemos especificar en que atributo resuelve la entidad
  @ManyToMany(() => Product, (products) => products.categories)
  products: Product[];
}

Ya hemos comunicado las entidades y que tipo de relaci贸n tienen, ahora, para crear la tabla donde se especificar谩 la relaci贸n muchos a muchos, debemos utilizar el decorador **@JoinTable()**, es importante aclarar que este decorador debe ir en solo una de las entidades, puede ser la que quieras, en mi caso quiero que sea en los productos:

  • **src/products/entities/product.entity.ts**:
import {
  // ...
  ManyToMany,
  JoinTable,
} from 'typeorm';

import { Category } from './category.entity';

@Entity()
export class Product {
  // ...

  @ManyToMany(() => Category, (category) => category.products)
	// este decorador crea la tabla terniaria
  @JoinTable()
  categories: Category[];
}

Y listo, ahora con crear y correr una migraci贸n nos basta para que esta.

Product Entity

@Entity()
export class Product extends BasicEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({
    type: 'varchar',
    length: 255,
    unique: true,
  })
  name: string;

  @Column({
    type: 'text',
  })
  description: string;

  @Column({ type: 'int' })
  price: number;

  @Column({ type: 'int' })
  stock: number;

  @Column({ type: 'varchar' })
  image: string;

  @ManyToOne(() => Brand, (brand) => brand.products, { nullable: true })
  // La que tiene relacion many to one, tiene la llave foranea @JoinColumn()
  brand: Brand;

  @ManyToMany(() => Category, (category) => category.products, {
    nullable: false,
  })
  // La que tiene relacion many to one, tiene la llave foranea @JoinColumn()
  categories: Category[];
}

Category entity


@Entity()
export class Category extends BasicEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ type: 'varchar', length: 255, unique: true })
  name: string;

  @ManyToMany(() => Product, (product) => product.categories)
  @JoinTable() //Este decorador solo debe ir en un lado de la migraci贸n
  products: Product[];
}