NestJS+TypeORM:如何实现广告租赁状态自动回退?
问题解决:TypeORM查询无有效租赁请求的广告
问题分析
你当前的Not操作符用法逻辑错误:rentRequests: Not({...})会匹配存在至少一个不符合条件的租赁请求的广告,但实际需求是不存在任何已批准且当前处于租期内的租赁请求的广告,两者逻辑完全不同。
解决方案
需要用Not(Exists(...))来表达“没有符合条件的关联租赁请求”,或者用QueryBuilder构建更直观的查询,以下是两种可行写法:
方案1:使用FindOptions结合Not与Exists
import { Not, Exists, LessThan, MoreThan } from 'typeorm'; async activateAllRentingCar(): Promise<AdvertEntity[]> { const currentDate = new Date(); // 查询状态为IN_RENTING且无有效租赁请求的广告 const adverts = await this.advertsRepository.find({ where: { advertStatus: AdvertStatus.IN_RENTING, rentRequests: Not(Exists({ status: RentRequestStatus.APPROVED, from: LessThan(currentDate), to: MoreThan(currentDate), })), }, }); // 更新状态为ACTIVE并保存 adverts.forEach(advert => { advert.advertStatus = AdvertStatus.ACTIVE; }); await this.advertsRepository.save(adverts); return adverts; }
方案2:使用QueryBuilder(更直观,适合复杂查询)
async activateAllRentingCar(): Promise<AdvertEntity[]> { const currentDate = new Date(); const adverts = await this.advertsRepository .createQueryBuilder('advert') // 左连接租赁请求表 .leftJoin('advert.rentRequests', 'rentRequest') // 筛选当前状态为IN_RENTING的广告 .where('advert.advertStatus = :rentingStatus', { rentingStatus: AdvertStatus.IN_RENTING }) // 核心条件:不存在任何已批准且当前在租期内的租赁请求 .andWhere('NOT EXISTS (SELECT 1 FROM rent_request rr WHERE rr.advertId = advert.id AND rr.status = :approvedStatus AND rr.from < :currentDate AND rr.to > :currentDate)', { approvedStatus: RentRequestStatus.APPROVED, currentDate, }) .getMany(); adverts.forEach(advert => { advert.advertStatus = AdvertStatus.ACTIVE; }); await this.advertsRepository.save(adverts); return adverts; }
关键说明
Exists子查询会检查是否存在符合条件的关联记录,Not(Exists(...))正好对应“无任何符合条件的记录”的需求- QueryBuilder写法更灵活,适合调试复杂关联查询,PostgreSQL对
NOT EXISTS的查询优化也更高效
内容的提问来源于stack exchange,提问作者Hrechko Dmytro
相关产品推荐
相关产品推荐

