【发布时间】:2020-08-28 19:53:42
【问题描述】:
我整个下午都在尝试使用诸如 findOne() 之类的 Sequelize 模型方法来表达以下 SQL 查询 -
SELECT * FROM "Tariffs" WHERE "tariffType" = 'DateRange' AND (('${body.startDate}' BETWEEN "startDate" AND "endDate") OR ('${body.endDate}' BETWEEN "startDate" AND "endDate")) LIMIT 1
body.startDate 和 body.endDate 由 HTTP 帖子提供 - startDate 和 endDate 是 PostgreSQL 后端中保存的日期列。
显然我可以使用query() 直接执行此操作,但这首先违背了使用 ORM 的目的。
提供给findOne() 的对象的标准似乎没有提供一种明显的方法来提供要匹配的文字值,并且总是需要列名和然后一个值。有一个 sequelize.where() 方法,但是它确实可以让你在某种程度上解决这个问题,我能想到的最好的就是这个怪物 -
Tariffs.findOne({
where: {
[Op.and]: [{
tariffType: "DateRange"
},
{
[Op.or]: [sequelize.where(sequelize.literal(`'${body.startDate}'`), Op.between, sequelize.literal('"startDate" AND "endDate"')),
sequelize.where(sequelize.literal(`'${body.endDate}'`), Op.between, sequelize.literal('"startDate" AND "endDate"'))
]
}
]
}
});
这会大量使用sequelize.literal,这可能也是不可取的——我尝试sequelize.col 在where() 调用中定义列名,但该方法似乎不想将它们解释为列名。
谁能建议一个更好的方法来做到这一点,还是我只能坚持运行原始查询?
编辑 13/05/20
Anatoly 的答案是正确的 - 谢谢。
但是,我最初的逻辑是错误的 - 我实际上想匹配具有提供的开始和结束日期内的开始和结束日期的记录,以及提供的开始日期在其范围内或提供的结束日期在其范围内的记录范围。因此,[Op.or] 运算符之后需要一个额外的对象 -
[Op.or]: [{
startDate: {
[Op.lte]: body.startDate
},
endDate: {
[Op.gte]: body.startDate
} }, {
startDate: {
[Op.lte]: body.endDate
},
endDate: {
[Op.gte]: body.endDate
} }, {
startDate: {
[Op.gte]: body.startDate
},
endDate: {
[Op.lte]: body.endDate
}
}]
【问题讨论】:
标签: javascript sql node.js sequelize.js