TypeORM一对多关系下如何用QueryBuilder按日期排序获取共享设备最新Data数据
实现方案
首先先修正你实体中的一处关联配置错误:当前Devices实体的@OneToMany关联参数填写错误,第二个参数需要指向Data实体中关联Devices的devices属性,否则关联查询会异常,修正后代码如下:
// Devices实体中修正后的OneToMany配置 @OneToMany(() => Data, data => data.devices) Data: Data[];
以下是两种符合需求的QueryBuilder实现方式:
方案1:返回映射好的实体对象(更易用)
通过leftJoinAndMapOne直接将每个设备的最新Data映射到Devices实体的额外属性中,返回结果为标准实体数组:
- 先给Devices实体新增可选的最新数据属性:
// 在Devices类中添加 latestData?: Data;
- 查询代码:
import { getRepository } from 'typeorm'; const devicesWithLatestData = await getRepository(Devices) .createQueryBuilder('device') // 过滤所有共享状态为true的设备 .where('device.shared = :isShared', { isShared: true }) // 关联映射每个设备的最新Data记录 .leftJoinAndMapOne( 'device.latestData', Data, 'data', 'data.id_data = (SELECT MAX(subData.id_data) FROM data subData WHERE subData.id_device = device.id_device)' ) .getMany();
这里用自增主键id_data的最大值判断最新记录,如果你需要严格按创建时间匹配,可以将子查询中的MAX(subData.id_data)替换为subData.time = (SELECT MAX(subData2.time) FROM data subData2 WHERE subData2.id_device = device.id_device)即可。
方案2:返回原始查询结果
如果只需要原始字段数据,可以用子查询关联的方式实现:
import { getConnection } from 'typeorm'; const result = await getConnection() .createQueryBuilder() .select('device.id_device', 'deviceId') .addSelect('device.name', 'deviceName') .addSelect('data.*') .from(Devices, 'device') .where('device.shared = :isShared', { isShared: true }) // 子查询获取每个设备的最新Data ID .leftJoin( qb => qb.select('MAX(subData.id_data)', 'maxDataId') .addSelect('subData.id_device') .from(Data, 'subData') .groupBy('subData.id_device'), 'latestData', 'latestData.id_device = device.id_device' ) // 关联拿到最新Data的完整字段 .leftJoin(Data, 'data', 'data.id_data = latestData.maxDataId') .getRawMany();
内容的提问来源于stack exchange,提问作者Bartłomiej Pachel
相关产品推荐
相关产品推荐

