首页 > 解决方案 > 有没有办法使用 Sequelize 模型方法来表达以下 SQL 查询?

问题描述

我整个下午都在尝试使用诸如 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

wherebody.startDatebody.endDate由 HTTP post 提供 -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.colwhere()调用中定义列名,但该方法似乎不想将它们解释为列名。

谁能建议一个更好的方法来做到这一点,还是我只需要坚持运行原始查询?

编辑 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
    } 
}]

标签: javascriptsqlnode.jssequelize.js

解决方案


你可以尝试这样的事情:

[Op.or]: [{
  startDate: {
   [Op.lte]: body.startDate
  },
  endDate: {
   [Op.gte]: body.startDate
  }
}, {
  startDate: {
   [Op.lte]: body.endDate
  },
  endDate: {
   [Op.gte]: body.endDate
  }
}]

推荐阅读