Can I use one class as Entity and ViewEntity - nestjs

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?

Related

TSeD Proper way to declare Model multi type for 1 property

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

How to describe DTO with nested entity?

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

How to create index number decrease postgresql with typeorm?

i read docs of typeorm but i don't see the way to handle my problem, i tried to create index in my entity but it not sort like i want.How can i do it?
#ObjectType()
#Entity()
export class Product extends BaseEntity {
#Field()
#PrimaryGeneratedColumn()
id!: number;
#Field()
#Column()
#Index()
paidCount!: number;
...
}

Exteding base class with some default column in Sequelize with "Type support" (NestJS)

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> {
}

TypeORM getRawOne<T> not returning type T

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

Resources