How to make a certain SQL instruction in sequelize? - node.js

I want to make the next SQL instruction, but I don't know how. I tried many ways, but I can't make it work in sequelize. This is the SQL instruction:
SELECT interes_revision.nombre FROM interes_revision
LEFT JOIN asociar ON interes_revision.id = asociar.id_interes_revision
WHERE asociar.id_par_evaluador = <req.params>
And tbe models asociated with that instruction:
InteresRevision.ts
#Table({
timestamps:false,
tableName: "interes_revision"
})
export class InteresRevision extends Model {
#Column({
type: DataType.INTEGER,
primaryKey:true,
allowNull:false,
autoIncrement:true
})
id!:number;
#Column({
type: DataType.STRING,
allowNull:true,
unique: true
})
nombre!:string;
#HasMany(() => Asociar)
asociar!: Asociar[];
ParEvaluador.ts
#Table({
timestamps:false,
tableName: "par_evaluador"
})
export class ParEvaluador extends Model {
#Column({
type: DataType.INTEGER,
primaryKey:true,
allowNull:false,
autoIncrement:true
})
id!:number;
#HasMany(() => Asociar)
asociar!: Asociar[];
}
Asociar.ts
#Table({
timestamps:false,
tableName: "asociar"
})
export class Asociar extends Model {
#ForeignKey(() => ParEvaluador)
#Column({
allowNull: false
})
id_par_evaluador!: number;
#ForeignKey(() => InteresRevision)
#Column({
allowNull: false
})
id_interes_revision!: number;
#BelongsTo(() => InteresRevision)
interesRevision!: InteresRevision;
#BelongsTo(() => ParEvaluador)
parEvaluador!: ParEvaluador;
}
The instruction in particular would show only a column from one table, and would return a list of "interes_revision" where the "id_par_evaluador" on "asociar" matches the req.params' id you want to match. Any help is welcome.

Related

Why am I getting a validation error? Nestjs, Sequelize , PostgressQL

I want to create a dependency where one User can have many InvestorCase, but one InvestorCase belongs to only one User. I need to have user_id field in InvestorCase.
User entity:
import { InvestorCase } from 'src/investor-case/entities/investor-case.entity';
import { ApiProperty } from '#nestjs/swagger';
import { Exclude } from 'class-transformer';
import {
AllowNull,
Column,
DataType,
Default,
HasMany,
IsIn,
Model,
Table,
} from 'sequelize-typescript';
import { UserRole, UserStatus } from 'src/shared/enums';
import { IUser } from 'src/shared/interfaces';
const userRoleValues = Object.values(UserRole);
const userStatusValues = Object.values(UserStatus);
#Table({ tableName: 'user' })
export class User extends Model<User, IUser> {
#ApiProperty({ example: '1', description: 'User`s Id' })
#Column({
type: DataType.INTEGER,
unique: true,
autoIncrement: true,
primaryKey: true,
})
public id: number;
#ApiProperty({ example: 'test#gmail.com', description: 'User`s Email' })
#Column({
type: DataType.STRING,
allowNull: false,
})
public email: string;
#ApiProperty({ example: 'password', description: 'User``s password' })
#Column({
type: DataType.STRING,
allowNull: true,
})
#Exclude()
public password: string;
#ApiProperty({ example: 'Barak', description: 'User`s name' })
#Column({
type: DataType.STRING,
allowNull: false,
})
public firstName: string;
#ApiProperty({ example: 'Obama', description: 'User`s surname' })
#Column({
type: DataType.STRING,
allowNull: false,
})
public lastName: string;
#ApiProperty({ example: '3806799599432', description: 'User`s phone number' })
#Column({
type: DataType.STRING,
})
public phoneNumber: string;
#ApiProperty({ example: 'verified', description: 'Account status' })
#IsIn({
args: [userStatusValues],
msg: `User status must one of the following:
${userStatusValues.join(', ')}`,
})
#Default(UserStatus.UNVERIFIED)
#Column
public status: UserStatus;
#ApiProperty({
example: 'developer',
description: 'User`s role',
enum: UserRole,
})
#IsIn({
args: [userRoleValues],
msg: `User role must one of the following:
${userRoleValues.join(', ')}`,
})
#Default(UserRole.INVESTOR)
#AllowNull(false)
#Column
public role: UserRole;
#HasMany(() => InvestorCase)
investorCases: InvestorCase[];
}
InvestorCare entity:
import { ApiProperty } from "#nestjs/swagger";
import { BelongsTo, Column, DataType, ForeignKey, IsIn, Model, PrimaryKey, Table } from "sequelize-typescript";
import { PaymentMethods } from 'src/shared/enums'
import { IInvestorCase } from 'src/shared/interfaces';
import { User } from "src/user/entities/user.entity";
const paymentMethods = Object.values(PaymentMethods);
#Table({ tableName: 'investor-case' })
export class InvestorCase extends Model<InvestorCase, IInvestorCase> {
#ApiProperty({ example: '1', description: 'Unique ID' })
#PrimaryKey
#Column({ type: DataType.INTEGER, unique: true, autoIncrement: true })
public id: number;
#ApiProperty({ example: '10000', description: 'The amount the investor will deposit initially.' })
#Column({ type: DataType.INTEGER, unique: true, allowNull: false, validate: { min: 1000 } })
public initialPayment: number;
#ApiProperty({ example: '1000', description: 'The amount that the investor will contribute monthly.' })
#Column({ type: DataType.INTEGER, allowNull: true, validate: { min: 500 } })
public monthlyPayment: number;
#ApiProperty({
example: 'true',
description: 'The payment method by which the investments will be made.',
enum: paymentMethods
})
#IsIn({
args: [paymentMethods],
msg: `The payment method must one of the following: ${paymentMethods.join(',')}`
})
#Column({ type: DataType.STRING, allowNull: false, defaultValue: PaymentMethods.Manually })
public paymentMethod: string;
#BelongsTo(() => User, {
foreignKey: 'userId',
as: 'UserId',
})
#ApiProperty({
example: '1',
description: 'Company representative user id',
})
#ForeignKey(() => User)
#Column({ type: DataType.INTEGER })
userId: number;
}
I try to create InvestorCase using this:
{
"initialPayment": 5000,
"monthlyPayment": 1000,
"paymentMethod": "Link a bank account",
"userId": 2
}
[Nest] 244 - 05/10/2022, 10:30:26 AM ERROR [ExceptionsHandler] Validation error
Error:
at Query.run (/app/node_modules/sequelize/src/dialects/postgres/query.js:76:25)
at /app/node_modules/sequelize/src/sequelize.js:643:28
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at PostgresQueryInterface.insert (/app/node_modules/sequelize/src/dialects/abstract/query-interface.js:773:21)
at InvestorCase.save (/app/node_modules/sequelize/src/model.js:4046:35)
at Function.create (/app/node_modules/sequelize/src/model.js:2253:12)
at InvestorCaseService.create (/app/src/investor-case/investor-case.service.ts:18:16)
at InvestorCaseController.create (/app/src/investor-case/investor-case.controller.ts:18:16)
at /app/node_modules/#nestjs/core/router/router-execution-context.js:46:28
at /app/node_modules/#nestjs/core/router/router-proxy.js:9:17
But alwways got error:
[Nest] 244 - 05/10/2022, 10:30:26 AM ERROR [ExceptionsHandler] Validation error
Error:
at Query.run (/app/node_modules/sequelize/src/dialects/postgres/query.js:76:25)
at /app/node_modules/sequelize/src/sequelize.js:643:28
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at PostgresQueryInterface.insert (/app/node_modules/sequelize/src/dialects/abstract/query-interface.js:773:21)
at InvestorCase.save (/app/node_modules/sequelize/src/model.js:4046:35)
at Function.create (/app/node_modules/sequelize/src/model.js:2253:12)
at InvestorCaseService.create (/app/src/investor-case/investor-case.service.ts:18:16)
at InvestorCaseController.create (/app/src/investor-case/investor-case.controller.ts:18:16)
at /app/node_modules/#nestjs/core/router/router-execution-context.js:46:28
at /app/node_modules/#nestjs/core/router/router-proxy.js:9:17

How to Select Some Fields From Relations in Typeorm Relations

I need to Select Some fields from relations in Nest.js TypeOrm .
For Example My Entity is :
#Entity()
export class Chat {
#PrimaryGeneratedColumn()
public id: number;
#Column()
public orderId: number;
#Column({ default: ChatStatus.Active })
public status: ChatStatus;
#Column()
public userId: number;
#ManyToOne(() => User, (user) => user.chats, { nullable: true })
#JoinColumn({ name: 'userId' })
public user: User;
}
Any In My Service :
async findAll(dataSearch) {
return await this.chatRepository.find({
relations: ['user'],
});
}
I Want Just Select "name" , "avatar" from user relation but This select all Columns.
Thanks
#Column({ type: "timestamp", default: () => 'CURRENT_TIMESTAMP',
select: false
})
updated_at: Timestamp;
Example
#Column({ type: "timestamp", default: () => 'CURRENT_TIMESTAMP', select: false })

TS2345 sequelize create function

I am creating a sequelize repository and I have an object which extends sequelize model.
I was able to do the following to save the model to the db.
repository.create(myModel) // myModel being an instance of MyModel which extends sequelize model
Now I am getting the following error in typescript:
Argument of type 'MyModel' is not assignable to parameter of type 'CreationAttributes<MyModel>'.
Type 'MyModel' is not assignable to type 'Omit<any, string>'.
Index signature for type 'number' is missing in type 'MyModel'.ts(2345)
I was doing some searching and a suggestion was to add to MyModel:
[key: number]: number;
When I do that the error is changed to the following:
Argument of type 'MyModel' is not assignable to parameter of type 'CreationAttributes<MyModel>'.
Type 'MyModel' is not assignable to type 'Omit<any, string>'.
Index signature for type 'symbol' is missing in type 'MyModel'.ts(2345)
I can get around the error by changing the call to create:
repository.create({...myModel})
Can anyone point me to documentation about ts(2345) what it is, perhaps how to ignore it. Or even solve the issue the correct way?
Using the spread operator, to me seems a bit messy, but if that is the correct solution that is fine.
Model definition:
import {
Column, DataType, ForeignKey, Model, Sequelize, Table,
} from 'sequelize-typescript';
import MediaResource from './media_resource';
import User from './users';
#Table({
tableName: 'videos',
timestamps: true,
version: true,
})
export default class Video extends Model {
#Column({
primaryKey: true,
autoIncrement: true,
type: DataType.INTEGER,
defaultValue: Sequelize.literal("nextval('videos_id_seq'::regclass)"),
})
id?: number;
#ForeignKey(() => MediaResource)
#Column({
field: 'media_resource_id',
allowNull: false,
type: DataType.INTEGER,
})
mediaResourceId?: number;
#Column({
allowNull: false,
type: DataType.STRING(191),
})
title?: string;
#Column({
allowNull: false,
type: DataType.STRING(2000),
})
url?: string;
#Column({
allowNull: true,
type: DataType.STRING(512),
})
description?: string;
#Column({
allowNull: false,
type: DataType.BOOLEAN,
})
is_3d?: boolean;
#Column({
allowNull: false,
type: DataType.BOOLEAN,
})
is_360?: boolean;
#ForeignKey(() => User)
#Column({
field: 'user_id',
allowNull: false,
type: DataType.INTEGER,
})
userId?: number;
#Column({
field: 'created_at',
allowNull: false,
type: DataType.DATE,
})
createdAt?: Date;
#Column({
field: 'updated_at',
allowNull: false,
type: DataType.DATE,
})
updatedAt?: Date;
}
Repository create signiture:
const db = DB.getInstance();
const videosRepository = db.getRepository(Video);
const transaction = await db.transaction();
try {
const saved = await videosRepository.create({ ...video }, { transaction });
await transaction.commit();
return saved;
} catch (err) {
await transaction.rollback();
if (err instanceof Error) logger.error(err.message);
throw new InternalServerError();
}
We have a sequelize singleton which is what db is, the video object is created from an express request body.
Also this used to work, I could add a ts-ignore comment and it will work.
sequelize: 6.15.1
sequelize-typescript: 2.1.2
typescript: 4.5.5
So I've come across 2 solutions to this problem, the first is as outlined above:
repository.create({ ...myModel })
And the second is:
repository.create(myModel as any)
This was my solution ...
export default class Video extends Model<InferAttributes<Video>, InferCreationAttributes<Video>> {
https://sequelize.org/master/manual/typescript.html

Nestjs TypeORM syntax error at or near "AND"

I am building a UserService class in my system, and declaring which should be a simple 'find' method, but I'm receiving the error as shown in the image bellow:
This is my service method:
#Injectable()
export class UsersService {
...
async findByRA(academicRegister: string) {
return await this.userRepository.findOne({
where: { academicRegister: academicRegister },
});
}
...
}
This is my controller:
#Controller('users')
export class UsersController {
...
#Get('ra/:ra')
findByRa(#Param('ra') ra: string) {
return this.usersService.findByRA(ra);
}
...
}
This is my User entity, and if I change eager to false, the error does not happen, however I don't get the data from the child entities, which I need
#Entity()
export class User {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
#ApiProperty({ enum: UserRole, enumName: 'UserRole' })
userRole: UserRole;
#Column()
academicRegister: string;
#Column()
password: string;
#OneToOne(() => Coordinator, (coordinator) => coordinator.user, {
eager: true,
nullable: true,
cascade: ['insert', 'update', 'soft-remove', 'recover'],
})
coordinator?: Coordinator;
#OneToOne(() => Monitor, (monitor) => monitor.user, {
eager: true,
nullable: true,
cascade: ['insert', 'update', 'soft-remove', 'recover'],
})
monitor?: Monitor;
#CreateDateColumn()
creationDate: Date;
#DeleteDateColumn()
deletionDate?: Date;
#Column({ nullable: true })
deletedBy?: string;
}
These are the related columns in the child entities:
export class Coordinator {
...
#Column({ nullable: true, unique: true })
userId: string;
#OneToOne(() => User, (user) => user.coordinator, {
orphanedRowAction: 'nullify',
cascade: ['insert', 'update', 'soft-remove', 'recover'],
})
user: User;
...
}
export class Monitor {
...
#Column({ nullable: true, unique: true })
userId: string;
#OneToOne(() => User, (user) => user.monitor, {
orphanedRowAction: 'nullify',
cascade: ['insert', 'update', 'soft-remove', 'recover'],
})
user: User;
...
}
Eager relations are loaded automatically each time you load entities
from the database.
When You will be loading your Coordinator or Monitor entity you don't need to have manually call for your relations it will be done automatically.
You must be accessing your entities in wrong way.

how to create association instance from source instance with sequelize-typescript

I have 1:n association Company -> CompanySettings,
what I want is, I find Company by Id then create companySettings by that instance and automatically fill the foreign key attribute
using sequelize-typescript
I have tried $get, $add, $count from association function and its works
but when I try $create function it gives me the errors
Company Class
#Table({
tableName: 'company',
})
export class Company extends Model<Company> {
#Column({ allowNull: false, type: DataType.STRING(50) })
name: string
#CreatedAt
#Column({ field: 'created_at' })
createdAt: Date
#UpdatedAt
#Column({ field: 'updated_at' })
updatedAt: Date
#Column({ field: 'is_deleted', defaultValue: 'f', type: DataType.BOOLEAN })
isDeleted: boolean
#HasMany(() => CompanySettings)
settings: CompanySettings[]
CompanySettings class
#Table({
tableName: 'company_settings',
})
export class CompanySettings extends Model<CompanySettings> {
#ForeignKey(() => Company)
#Column
idCompany: number
#BelongsTo(() => Company)
company: Company
#Column({ type: DataType.ENUM('default', 'alwaysApprove', 'alwaysAsking') })
defaultBookingApproval: defaultBookingOptions
#Column({ type: DataType.SMALLINT })
budgetPeriod: number
#Column({ type: DataType.CHAR(2) })
startDate: string
#CreatedAt
#Column
createdAt: Date
#UpdatedAt
#Column
updatedAt: Date
#Column({ defaultValue: 'f', type: DataType.BOOLEAN })
isDeleted: boolean
controller
const companies = await Company.findOne()
return await companies.$create('settings', { startDate: '22' })
After finding the source instance, I want to create new instance related to the source instance
But the errors I got is shown below
TypeError: this[("create" + string_1.capitalize(...))] is not a function
tell me where am i wrong ?
if you want create one setting, you should write code like below
companies.$create('setting', { startDate: '22 })
instead of
companies.$create('settings', { startDate: '22' })
if you want create bulk, you should like below
companies.$create('settings', [{ startDate: '22', { startDate: '23'}] })
fuzes solutions should work nicely,
If you want to attach this newly created instance to source instance then:
const setting = await companies.$create('setting', { startDate: '22' });
companies.set('settings', [...companies.settings, setting]);

Resources