TypeORM查询当日记录无返回?如何正确实现带日期校验的查询
TypeORM 当日创建记录查询无匹配结果的修复方案
问题场景
开发者基于TypeORM的QueryBuilder编写联表查询逻辑,目标是拉取指定用户当日创建、标记为挑战属性的Earnings全量匹配记录,但执行后无任何结果返回,核心需要明确TypeORM框架下带日期校验的合法查询写法。
现有问题代码
all = await connection .createQueryBuilder(Earnings, 't0') .addSelect('t3.id', 't3_id') .addSelect('t3.UID', 't3_UID') .addSelect('t3.name', 't3_name') .addSelect('t3.chips', 't3_chips') .addSelect('t3.tickets', 't3_tickets') .addSelect('t3.masteredLevel', 't3_masteredLevel') .addSelect('t2.UID', 't2_UID') .addSelect('t2.name', 't2_name') .addSelect('t2.rule', 't2_rule') .addSelect('t1.id', 't1_id') .innerJoin(Questions, 't1', 't0.questionID = t1.id') .innerJoin(Lessons, 't2', 't1.lessonUID = t2.UID') .innerJoin(Topics, 't3', 't2.topicUID = t3.UID') .where('t0.challenge = 1') .andWhere('t0.createdAt = :today') .andWhere('t0.userID = :userID') .setParameters({ userID: user.id }) .setParameters({ today: moment() }) .getRawMany()
代码存在的核心问题
- 日期匹配逻辑错误:原代码使用
t0.createdAt = :today做精确等值匹配,传入的参数是moment()生成的、精确到当前执行时刻毫秒级的时间值,与数据库中存储的、带有具体时分秒信息的创建时间永远无法完全匹配,这是无返回结果的核心原因 - 参数覆盖bug:连续两次调用
setParameters()方法时,后一次的参数对象会完全覆盖前一次的设置值,原代码第二次传入today参数时,第一次设置的userID参数会被清空,导致查询条件缺失
修复后的正确实现
- 生成当日的时间边界值,把查询范围限定在自然日的完整区间内,避免毫秒级匹配的问题:
// 生成当日00:00:00到23:59:59.999的时间范围 const dayStart = moment().startOf('day').toDate() const dayEnd = moment().endOf('day').toDate() - 调整查询逻辑,使用范围匹配替代等值匹配,统一合并所有参数避免覆盖:
all = await connection .createQueryBuilder(Earnings, 't0') // 原有select、join逻辑保持不变 .addSelect('t3.id', 't3_id') .addSelect('t3.UID', 't3_UID') .addSelect('t3.name', 't3_name') .addSelect('t3.chips', 't3_chips') .addSelect('t3.tickets', 't3_tickets') .addSelect('t3.masteredLevel', 't3_masteredLevel') .addSelect('t2.UID', 't2_UID') .addSelect('t2.name', 't2_name') .addSelect('t2.rule', 't2_rule') .addSelect('t1.id', 't1_id') .innerJoin(Questions, 't1', 't0.questionID = t1.id') .innerJoin(Lessons, 't2', 't1.lessonUID = t2.UID') .innerJoin(Topics, 't3', 't2.topicUID = t3.UID') .where('t0.challenge = 1') // 替换为日期范围匹配条件 .andWhere('t0.createdAt BETWEEN :dayStart AND :dayEnd') .andWhere('t0.userID = :userID') // 统一传入所有参数,避免重复调用导致覆盖 .setParameters({ userID: user.id, dayStart: dayStart, dayEnd: dayEnd }) .getRawMany()
其他注意事项
- 不要使用字符串拼接的方式构造日期查询条件,避免SQL注入风险,始终通过参数绑定传值
- 如果数据库的时区与应用服务器时区不一致,需要确保moment生成的时间值做了对应的时区转换,避免时间范围偏移导致漏查
内容的提问来源于stack exchange,提问作者I'm not human
相关产品推荐
相关产品推荐

