Sequelize v5 关联表字段参与PostgreSQL WHERE子句datetime运算求助
错误原因
- 前两种写法触发NaN的原因:
sequelize.fn、sequelize.col是数据库层面执行的标识,你把它们直接放到JS的减法运算中,JS会在SQL生成阶段就提前执行算术操作,无法识别这两个方法的返回值,最终得到NaN代入SQL。 - 第三种写法报
epoch列不存在的原因:PostgreSQL中字符串用单引号包裹,反引号是MySQL的语法,你写的epoch会被PG识别为列名而非date_part的参数。
正确实现
写法1:直接用sequelize.literal对齐原生SQL逻辑(最稳妥,不会踩Sequelize语法糖的坑)
const { Op } = require('sequelize'); const getPendingOrders = () => OrderHeader.findAll({ where: [ // 直接写和原生SQL完全一致的条件,注意PG语法用单引号包字符串,双引号包表/列名避免大小写问题 sequelize.literal(`date_part('epoch', "OrderHeader"."updated_at") + "sla_shipping_rules"."secondary_tax_timeout_hour" < date_part('epoch', now())`) ], include: { attributes: ['secondary_tax_timeout_hour'], model: SlaShippingRules, as: 'sla_shipping_rules', on: { shipping_method: { [Op.eq]: sequelize.col('OrderHeader.shipping_method') } }, required: true, }, });
写法2:纯Sequelize方法实现(尽量少用原生SQL片段)
如果不想写完整的literal语句,可以用sequelize.where来拼接数据库层面的运算和比较:
const { Op } = require('sequelize'); const getPendingOrders = () => OrderHeader.findAll({ where: sequelize.where( // 左边:order_header.updated_at的时间戳 + 超时时长 sequelize.literal(`date_part('epoch', "OrderHeader"."updated_at") + "sla_shipping_rules"."secondary_tax_timeout_hour"`), Op.lt, // 右边:当前时间戳 sequelize.fn('date_part', 'epoch', sequelize.fn('now')) ), include: { attributes: ['secondary_tax_timeout_hour'], model: SlaShippingRules, as: 'sla_shipping_rules', on: { shipping_method: { [Op.eq]: sequelize.col('OrderHeader.shipping_method') } }, required: true, }, });
注意:如果你的
secondary_tax_timeout_hour字段存的是小时单位,需要在计算时乘以3600转成秒才能和date_part('epoch')返回的秒数匹配,原生SQL可正常执行说明你的字段本身存的是秒数则无需调整。
内容的提问来源于stack exchange,提问作者RageQuitter
相关产品推荐
相关产品推荐

