Я пытаюсь найти наилучший способ (или метод наилучшей практики) для разрешения ленивых отношений в моем приложении Nestjs TypeORM postgresql.
Я определил некоторые отношения OneToMany и ManyToOne в объектахкак ленивый, и когда я запрашиваю массив одной из этих сущностей, лучшее решение, которое я нашел до сих пор, - это огромная путаница обещаний.
Моя Customer
сущность (customer.entity.ts):
import { Column, CreateDateColumn, Entity, Index, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne, OneToMany } from 'typeorm';
import { IsEmail } from 'class-validator';
import { ReservationDate } from '../reservation_date/reservation_date.entity';
@Entity()
export class Customer {
@PrimaryGeneratedColumn('uuid')
id: string;
@Index()
@Column()
@IsEmail()
email: string;
@Column()
firstName: string;
@Column()
lastName: string;
@CreateDateColumn()
createDate: Date;
@UpdateDateColumn()
updateDate: Date;
@OneToMany(type => ReservationDate, reservationDate => reservationDate.customer)
reservationDates: Promise<ReservationDate[]>;
}
и моя ReservationDate
сущность (booking_date.entity.ts):
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne } from 'typeorm';
import { Customer } from '../customer/customer.entity';
@Entity()
export class ReservationDate {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
date: Date;
@CreateDateColumn()
createDate: Date;
@UpdateDateColumn()
updateDate: Date;
@ManyToOne(type => Customer, customer => customer.reservationDates, { onDelete: 'CASCADE' })
customer: Promise<Customer>;
}
Мне нужно получить массив ReservationDate
с и отправить его куда-нибудь,но мне нужно, чтобы разрешить поле customer
(например, с нетерпением загрузить эти отношения).Вот что «работает»:
const reservationDates: ReservationDate[] = await this.reservationDateRepository
.createQueryBuilder('reservationDate')
.leftJoinAndSelect('reservationDate.customer', 'customer')
.getMany();
// Same result as query builder above
// const reservationDates: ReservationDate[] = await this.reservationDateRepository
// .find({
// relations: ['customer'],
// take: 5
// });
console.log(reservationDates[0].car); // => Promise { <pending> }
console.log(reservationDates[0].__car__); // => Car { id: string, owner... }
// this is where it gets ugly
const reservationDatesWithResolvedRelationships = await Promise.all(
reservationDates.map(async (resDate: ReservationDate) => {
const withResolved: ReservationDateRepoObject = { ...resDate };
withResolved.customer = await resDate.customer;
return withResolved;
})
);
console.log(reservationDatesWithResolvedRelationships[0].car); // => Car { id: string, owner... }
// send off the JSON-like object here
Я чувствую, что должен быть способ объединения и принудительной загрузки, но ни построитель запросов, ни методы repository.find
, похоже, не делают этого скак я это настроил.
Я также пытался добавить { lazy: true }
и { eager: true }
к отношениям в сущностях, но ничего не изменилось.
РЕДАКТИРОВАТЬ:
Пока еще немного удачи, однако мне удалось взломать псевдо-решение.
private parseRaw = name => raw => {
const parsed = new ReservationDate();
Object.entries(raw).forEach(([typeKey, value]) => {
const [type, key] = typeKey.split('_');
if (type === name) {
parsed[key] = value;
} else {
parsed[type] = parsed[type] || {};
parsed[type][key] = value;
}
});
return parsed;
};
let reservationDates: ReservationDate[] = (await this.reservationDateRepository
.createQueryBuilder('reservationDate')
.leftJoinAndSelect('reservationDate.customer', 'customer')
.limit(5)
.getRawMany()).map(this.parseRaw('reservationDate'));
Супер-уродливый взлом, но он конвертирует необработанные результаты snake_case
db в camelCase
json-объектМне нужно отправить ...