Typeorm querybuilder присоединиться к последней строке - PullRequest
0 голосов
/ 08 января 2020

Я использую Nest JS с TypeORM

У меня есть два объекта с отношением:

export class Device {
    @PrimaryGeneratedColumn()
    id: number;

    @Column("macaddr")
    mac: string;

    @OneToMany(type => DeviceStatus, deviceStatus => deviceStatus.mac)
    @JoinColumn()
    status: DeviceStatus[]

    @Column()
    created: Date;
}

export class DeviceStatus {
    @PrimaryGeneratedColumn()
    id: number;

    @ManyToOne(type => Device, device => device.mac)
    @JoinColumn({ name: "mac", referencedColumnName: "mac" })
    mac: Device;

    @Column()
    deviceState: number;

    @Column()
    created: Date;
}

Я хочу получить Device, но только его последний DeviceStatus на его status свойство.

Теперь я делаю это так:

const deviceQuery: Device = await this.deviceRepository
                        .createQueryBuilder("device")
                        .where('device.id = :id AND "device"."userId" = :user', {id: id, user: user.id})
                        .getOne();


const statusQuery: DeviceStatus = await this.deviceStatusRepository.createQueryBuilder("status")
                        .where('status.mac = :mac', { mac: deviceQuery.mac })
                        .orderBy('created', "DESC")
                        .limit(1)
                        .getOne();

deviceQuery.status = [statusQuery];

Как я могу сделать это, используя только один запрос typeBormBuilder?

Я уже пробовал это, но это не отображает свойство status на устройство, .execute() получает все свойства DeviceStatus, но не отображает объекты.

const deviceQuery: Device = await this.deviceRepository
                    .createQueryBuilder("device")
                    .leftJoinAndSelect(subquery => {
                        return subquery
                            .from(DeviceStatus, "status")
                            .innerJoin(subquery => {
                                return subquery
                                    .select(["status2.mac"])
                                    .addSelect("MAX(created)", "lastdate")
                                    .from(DeviceStatus, "status2")
                                    .groupBy("status2.mac")
                            }, "status3", 'status.created = "status3"."lastdate"')
                    }, "status", 'device.mac = "status"."mac"')
                    .where('device.id = :id AND "device"."userId" = :user', {id: id, user: user.id})
                    .getOne();

1 Ответ

1 голос
/ 09 января 2020

Вы можете достичь этого, присоединившись к статусу 2 раза. Условие второго присоединения к статусу (next_status) должно сравнивать дату created и находиться после первого присоединенного статуса. Затем просто проверьте, является ли next_status нулевым, это означает, что нет статуса моложе, чем первое присоединение

Код, вероятно, является лучшим объяснением:

const device: Device = await this.deviceRepository
                    .createQueryBuilder("device")
                    .leftJoinAndSelect("device.status", "status")
                    .leftJoin("device.status", "next_status", "status.created < next_status.created")
                    .where("next_status.id IS NULL")

// device.status is the latest status
...