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 uno a muchos

20/36
Recursos

Aportes 6

Preguntas 4

Ordenar por:

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

o inicia sesi贸n.

He creado dos snippets de VS Code para crear un Servicio y un Controller b谩sico mucho m谩s r谩pido. (para hacer lo que el profe hace en c谩mara r谩pida).

Para crearlos van a:

  • File
  • Preferences
  • User Snippets
  • Buscan typescript

En el archivo JSON que se les abri贸 copian este c贸digo dentro de las llaves:

  • Servicio
	"Create NestJS Service": {
		"prefix": "nest:s",
		"body": [
			"import { Injectable, NotFoundException } from '@nestjs/common';",
			"import { InjectRepository } from '@nestjs/typeorm';",
			"import { Repository } from 'typeorm';",
			"",
			"import { $2 } from '${1:entity-route}';",
			"import { ${4:createDto}, ${5:updateDto} } from '${3:dto-route}';",
			"",
			"@Injectable()",
			"export class ${6:serviceName}Service {",
			"  constructor(",
			"    @InjectRepository($2)",
			"    private ${7:repo}: Repository<$2>,",
			"  ) {}",
			"${0}",
			"  async findAll() {",
			"    return await this.$7.find();",
			"  }",
			"",
			"  async findOne(id: number) {",
			"    const ${8:object} = await this.$7.findOne(id);",
			"    if (!$8) throw new NotFoundException(`${9:object} not found.`);",
			"    return $8;",
			"  }",
			"",
			"  async create(data: $4) {",
			"    const ${10:newObject} = this.$7.create(data);",
			"    return await this.$7.save($10);",
			"  }",
			"",
			"  async update(id: number, changes: $5) {",
			"    const $8 = await this.findOne(id);",
			"    this.$7.merge($8, changes);",
			"    return await this.$7.save($8);",
			"  }",
			"",
			"  async remove(id: number) {",
			"    return await this.$7.delete(id);",
			"  }",
			"}",
		],
		"description": "This service has a basic CRUD implemented"
	},
  • Controller
"Create NestJS Controller": {
		"prefix": "nest:co",
		"body": [
			"import {",
			"  Controller,",
			"  Get,",
			"  Post,",
			"  Put,",
			"  Body,",
			"  Param,",
			"  Delete,",
			"  ParseIntPipe,",
			"} from '@nestjs/common';",
			"import { ApiTags } from '@nestjs/swagger';",
			"",
			"import { ${2:serviceName} } from '${1:service-route}';",
			"import { ${4:createDto}, ${5:updateDto} } from '${3:dto-route}';",
			"",
			"@ApiTags('${6:controllerName}')",
			"@Controller('$6')",
			"export class ${7:controllerNameInUppercase}Controller {",
			"  constructor(private ${8:serviceName}: $2) {}",
			"",
			"  @Get()",
			"  async findAll() {",
			"    return await this.$8.findAll();",
			"  }",
			"",
			"  @Get('/:id')",
			"  async getCategory(@Param('id') id: number) {",
			"    return await this.$8.findOne(id);",
			"  }",
			"",
			"  @Post()",
			"  async create(@Body() payload: $4) {",
			"    return await this.$8.create(payload);",
			"  }",
			"",
			"  @Put('/:id')",
			"  async update(",
			"    @Param('id', ParseIntPipe) id: number,",
			"    @Body() payload: $5,",
			"  ) {",
			"    return await this.$8.update(id, payload);",
			"  }",
			"",
			"  @Delete('/:id')",
			"  async remove(@Param('id', ParseIntPipe) id: number) {",
			"    return await this.$8.remove(id);",
			"  }",
			"}",
		],
		"description": "This controller has a basic CRUD implemented"
	}

Para usarlos simplemente tienen que crear su servicio/controlador normalmente y borrar lo que hay ah铆.
Luego simplemente ponen nest:s o nest:co y empiezan a llenar todos los datos que se pide.
Para avanzar solo precionen la tecla tab

Espero les sirva! 馃槂

Lo que vimos:

brand.entity.ts

import {
  PrimaryGeneratedColumn,
  Column,
  Entity,
  CreateDateColumn,
  UpdateDateColumn,
  OneToMany,
} from 'typeorm';
import { Product } from './product.entity';

@Entity()
export class Brand {
  @PrimaryGeneratedColumn()
  id: number;
  @Column({ type: 'varchar', length: 255, unique: true })
  name: string;

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

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

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

  @OneToMany(() => Product, (product) => product.brand)
  products: Product;
}


brands.service.ts

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

import { Brand } from '../entities/brand.entity';
import { CreateBrandDto, UpdateBrandDto } from '../dtos/brand.dtos';

@Injectable()
export class BrandsService {
  constructor(@InjectRepository(Brand) private brandRepo: Repository<Brand>) {}
  findAll() {
    return this.brandRepo.find();
  }

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

  create(data: CreateBrandDto) {
    const newBrand = this.brandRepo.create(data);
    return this.brandRepo.save(newBrand);
  }

  async update(id: number, changes: UpdateBrandDto) {
    const brand = await this.brandRepo.findOne(id);
    this.brandRepo.merge(brand, changes);
    return this.brandRepo.save(brand);
  }

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

product.entity.ts

import {
  PrimaryGeneratedColumn,
  Column,
  Entity,
  CreateDateColumn,
  UpdateDateColumn,
  ManyToOne,
} from 'typeorm';
import { Brand } from './brand.entity';

@Entity()
export class Product {
  @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;

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

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

  @ManyToOne(() => Brand, (brand) => brand.products)
  brand: Brand;
}

Relaciones uno a muchos

Vamos a trabajar ahora en relaciones uno a muchos (1: n), para esto vamos a tomar como caso de ejemplo la relaci贸n de productos a marcas, ya que una marca puede tener muchos productos, pero un producto solo puede tener una marca.

En las relaciones uno a muchos, la entidad d茅bil (1), es la que por defecto debe tener la relaci贸n, en este caso la entidad d茅bil el nuestro Product:

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

// importamos la entidad que vamos a referenciar
import { Brand } from './brand.entity';

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

  // el decorador "ManyToOne" indica la relac铆on muchos a uno
  // muchos productos, una marca
  // indicamos que resuelva la entidad "Brand" con una arrow function
  // indicamos el atributo que maneja la relaci贸n "brand.products"
  @ManyToOne(() => Brand, (brand) => brand.products)
  brand: Brand;
}

Recordemos que TypeORM nos permite manejar relaciones bidireccionales, as铆 que vamos a la entidad de las Brands e indiquemos esta relaci贸n bidireccional.

  • src/products/entities/brand.entity.ts:
import {
  // ...
  OneToMany,
} from 'typeorm';
import { Product } from './product.entity';

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

  // el decorador "OneToMany" indica la  relaci贸n uno a muchos
  // una marca, muchos productos
  // indicamos que resuelva la entidad "Product" con una arrow function,
  // indicamos el atributo que maneja la relaci贸n "product.brand"
  @OneToMany(() => Product, (product) => product.brand)
  products: Product[];
}

En este caso no debemos a帽adir un decorador extra que sea el que maneje la clave for谩nea como lo es **@JoinColumn()**, debido a que TypeORM sabe que en las relaciones uno a muchos es la entidad d茅bil la que maneja la relaci贸n 鈥@ManyToOne()" es la que tiene que tener la clave for谩nea.

Ahora solo debemos crear una migraci贸n y ya habremos definido nuestra relaci贸n uno a muchos.

Si les sale el error "Cannot find a module Brand.entity, es porque nest al realizar la autoimportacion del archivo los hace utilizando rutas absolutas. Para solucionarlo deben modificar las importaciones utilizando rutas relativas.

Al final la entidad debil es la que tiene la relaci贸n, esto es 'Product' porque un producto solo puede tener una marca pero una marca puede tener muchos productos

super chistoso escuchar la musica en 1.5x ademas de tener el volumen alto, llegu茅 a saltar jajaja

Excelente clase, cada d铆a aprendiendo mas sobre Manejo de bases de datos con nextjs lml