I am trying to save DTO with id of nested entity, but I am getting a problem:
Argument of type 'CreateSpendingDto' is not assignable to parameter of type 'DeepPartial<Spending>[]'.
How should I describe my DTO for pass it only with id?
My entity is:
#Entity('spending')
export class Spending {
#Column()
amount: number
#ManyToOne(() => Category)
#JoinColumn()
category: Category
#PrimaryGeneratedColumn()
id: number
}
My DTO is:
export class CreateSpendingDto {
readonly amount: number
readonly category: number
}
I found answer, have to add a separate column with categoryId:
#ManyToOne(() => Category)
#JoinColumn({name: 'categoryId'})
category: Category
#Column()
categoryId: number
Related
I'm working with Typeorm using MySQL database. I have a class as Entity and another class as ViewEntity. The question is why I need two separate Classes when they serve the same goal. Could I use the same Class with Entity and ViewEntity decorators?
Example Entity of Person class:
#Entity()
export class Person {
#PrimaryGeneratedColumn({ type: 'int', unsigned: true })
id: number;
#Column({length:50})
name: string;
#Column({type:'date'})
birthDate: string;
}
Another class for ViewEntity with the same properties added age property:
ViewEntity({
expression: `SELECT id, name, birthDate,
TIMESTAMPDIFF(YEAR,birthDate,CURDATE()) AS age FROM person;`
})
export class PersonView {
#ViewColumn()
id: number;
#ViewColumn()
name: string;
#ViewColumn()
birthDate: string;
#ViewColumn()
age: number;
}
To reduce redundant why I can't combine these two classes by doing this:
#Entity()
#ViewEntity({
name: 'PersonView',
expression: `SELECT id, name, birthDate,
TIMESTAMPDIFF(YEAR,birthDate,CURDATE()) AS age FROM person;`
})
export class Person{
#ViewColumn()
#PrimaryGeneratedColumn({ type: 'int', unsigned: true })
id: number;
#ViewColumn()
#Column({length:50})
name: string;
#ViewColumn()
#Column({type:'date'})
birthDate: string;
#ViewColumn()
age: number;
}
I searched in Typeorm documentation but they use a class only for ViewEntity. When I tried to test that I face a problem:
DataTypeNotSupportedError: Data type "" in "Person.age" is not supported by "mysql" database.
Also, how would I retrieve data? By doing dataSource.getRepository(Person) Person class has Entity and ViewEntity decorator then which type of entity will be retrieved? How would Typeorm distinguish between these two entities?
So i have a case that i want to save an object as a json string into database
But it kept getting error and warning everytime because the model is set as either string or object
Do i need two different models for post and get? Or there is more elegant way to deal with this sort of problem?
this is how i code right now
#Get("/")
#Summary("Return List Of blogs")
#Returns(200, Array)
async getAll(#QueryParams() blogFilter: any) {
return await this.service.findMany(blogFilter)
}
#Post("/")
#Summary("Create New Blog")
#Returns(201, BlogModel)
async create(#BodyParams() #Groups("creation") blog: BlogModel): Promise<BlogModel> {
// #ts-ignore
blog.content = JSON.stringify(await this.mediaService.contentMediaConvert(blog.content));
return await this.service.create(blog);
}
blog content should be an object from front end, but saved as JSON string for space
and this is my current model
export class BlogModel {
#ObjectID("id")
_id: string;
#Property()
#Required()
#Lowercase()
title: string;
#Property()
#Lowercase()
slug: string;
#Property()
#Any()
content: object;
#Property()
#Ref(CategoryModel)
category: Ref<CategoryModel>
#Property()
#Default(0)
views: number;
#Property()
#Required()
#Ref(UserModel)
createdBy: Ref<UserModel>;
#Property()
#Required()
#Ref(MediaModel)
thumbnail: Ref<MediaModel>;
#Property()
#Default("BLOG")
#Enum(pageType)
pageType: pageType
}
I sucks at Object oriented sorry
I have a Sequelize base class with updated_at, created_at columns etc. I want to extend the above base class in order to avoid writing repeated columns in every model. I wanted to have typing support as well (show column names).
Current Implementation.
BaseClass with typing support
export type ModelAttrs<T> = Omit<T, keyof Model>
export default class BaseModel<T> extends Model<ModelAttrs<T>, Partial<ModelAttrs<T>>> {
}
This will help to show the columns under the base class.
DefaultColumnsBaseClass
export default class DefaultValuesModel extends BaseModel<DefaultValuesModel> {
#Column({
type: DataType.DATE,
defaultValue: DataType.NOW,
})
created_at: Date;
#Column({
type: DataType.DATE,
defaultValue: DataType.NOW,
})
updated_at: Date;
#Column({
type: DataType.BOOLEAN,
defaultValue: false,
})
is_deleted: Boolean;
#Column({
type: DataType.DATE,
defaultValue: DataType.NOW,
})
deleted_at: Date;
}
What I want to do is, I want to create User class by extending DefaultValuesModel with type support from UserModel and DefaultValuesModel class. So basically the UserModel should show columns from UserModel and DefaultValuesModel.
I updated the BaseModel by referecing the DefaultValuesModel within the Type itself.
export type ModelAttrs<T> = Omit<T, keyof Model> & Omit<DefaultValuesModel, keyof Model>
export default class BaseModel<T> extends Model<ModelAttrs<T>, Partial<ModelAttrs<T>>> {
}
Now I can extend the BaseClass for type support and default column support.
export default class UserIdentityModel extends BaseModel<UserIdentityModel> {
}
I'm working on refactoring a koa api to nest and am kinda stuck on refactoring the queries from native psql to typeorm. I have the following table, view and dto.
#Entity()
export class Challenge {
#PrimaryGeneratedColumn()
id!: number;
#Column()
endDate!: Date;
#CreateDateColumn()
createdAt!: Date;
}
#ViewEntity({
expression: (connection: Connection) => connection.createQueryBuilder()
.select('SUM(cp.points)', 'score')
.addSelect('cp.challenge', 'challengeId')
.addSelect('cp.user', 'userId')
.addSelect('RANK() OVER (PARTITION BY cp."challengeId" ORDER BY SUM(cp.points) DESC) AS rank')
.from(ChallengePoint, 'cp')
.groupBy('cp.challenge')
.addGroupBy('cp.user')
})
export class ChallengeRank {
#ViewColumn()
score!: number;
#ViewColumn()
rank!: number;
#ViewColumn()
challenge!: Challenge;
#ViewColumn()
user!: User;
}
export class ChallengeResultReponseDto {
#ApiProperty()
id!: number;
#ApiProperty()
endDate!: Date;
#ApiProperty()
createdAt!: Date;
#ApiProperty()
score: number;
#ApiProperty()
rank: number;
test() {
console.log("test")
}
}
As the object I want to return is not of any entity type, I'm kinda lost on how to select it and return the correct class. I tried the following:
this.challengeRepository.createQueryBuilder('c')
.select('c.id', 'id')
.addSelect('c.endDate', 'endDate')
.addSelect('c.createdAt', 'createdAt')
.addSelect('cr.score', 'score')
.addSelect('cr.rank', 'rank')
.leftJoin(ChallengeRank, 'cr', 'c.id = cr."challengeId" AND cr."userId" = :userId', { userId })
.where('c.id = :id', { id })
.getRawOne<ChallengeResultReponseDto>();
Which returns an object that has the correct fields, but that is not of the class type "ChallengeResultReponseDto". If I try to call the function "test" the application crashes. Further it feels weird to use the challengeRepository but not return a challenge, should I use the connection or entity manager for this instead?
I'm rather certain that getRawOne<T>() returns a JSON that looks like whatever you give the generic (T), but an not instance of that class. You should try using getOne() instead to get the instance of the returned entity
let say there are different entity User, Role, Task
All these entities have createdBy, updatedBy, createdOn, updatedOn in common.
I want to know how can I create a base entity such that all entity extends base class in nest js using Typeform.
This is the place where should you use inheritance.
Basically, the idea is to have a base class/entity that gathers common logic or structure where many other classes/entities share that common logic.
For example:
Cat, Dog, Elephant are all having similar characterizations, so we might want to gather all these similar characterizations at a single place in order to avoid duplication of logic and code.
So let's see the simplest example only for basic understanding.
export class Animal {
protected numberOfLegs: number;
protected sound(): void;
}
export class Dog extends Animal {
constructor() {
super();
this.numberOfLegs = 4;
}
sound(): void {
console.log('BARK');
}
}
For your needs:
Export a base entity.
import { Entity, Column } from 'typeorm';
export class BaseEntity {
#Column()
createdBy: string;
#Column()
updatedBy: string;
#Column()
createdOn: Date;
#Column()
updatedOn: Date;
}
And then inherit it from derived entities.
import { Entity, Column } from 'typeorm';
import {BaseEntity} from './base-entity';
export class DerivedEntity extends BaseEntity {
#Column()
id: string;
...
}
Please read about inheritance which is a basic and very important principle in programming and OOP.