【问题标题】:How to perform a search with conditional where parameters using Sequelize如何使用 Sequelize 执行带有条件 where 参数的搜索
【发布时间】:2020-12-07 11:02:40
【问题描述】:

通常每当我为 SQL 编写搜索查询时,我都会做类似的事情:

SELECT * FROM users u
WHERE (@username IS NULL OR u.username like '%' + @username + '%')
AND (@id IS NULL OR u.id = @id)

这基本上模拟了一个条件 WHERE 子句。如果提供了@searchParam,我们只想将@searchParam 与列进行比较。

有没有办法使用 Sequelize 复制它?

编辑:这是我失败的最佳尝试:

models.user.findAll({
  where: {
    username: searchParams.username || models.sequelize.col('user.username'),
    id: searchParams.id || models.sequelize.col('user.id')
  }
})

更新:我找到了一种方法,但感觉像是一种解决方法。我敢肯定必须有一种更优雅的方式。这可行,但很难看:

models.user.findAll({
  where: [
    '(? IS NULL OR "user"."username" LIKE ?) AND (? IS NULL OR "user"."id" = ?)',
    searchParams.username,
    `%${searchParams.username}%`,
    searchParams.id,
    searchParams.id
  ]
})

【问题讨论】:

    标签: sql node.js sequelize.js


    【解决方案1】:

    您可以只准备具有所需条件的对象。简单易懂

    var whereStatement = {};
    if(searchParams.id)
        whereStatement.id = searchParams.id;
    if(searchParams.username)
        whereStatement.username = {$like: '%' + searchParams.username + '%'};
    models.user.findAll({
      where: whereStatement
    });
    

    【讨论】:

    • 是的,这似乎确实是最好的方法。我希望避免创建一长串 if 检查,但在这一点上似乎是不可避免的。
    • 当我的 whereStatement 对象仍然为空时,我得到一个错误。那该怎么办?续集 5.18。
    【解决方案2】:

    真是太棒了。谢谢你。我会这样使用你的想法:

    app.get('/', function (req, res) {
        ..
        let foo = await Foo.findAll(
        {
            offset: parseInt(req.query.offset | 0),
            limit: parseInt(req.query.limit | 10),
            where: getFooConditions(req),
        ...
    }
    
    function getFooConditions(req) {
      fooConditions = {};
      // Query param date
      if (req.query.date) {
        fooCondtions.start = {
          [Op.gte]: moment(parseInt(req.query.date)).utc().startOf('day'),
          [Op.lte]: moment(parseInt(req.query.date)).utc().endOf('day')
        }
      }
      // Query param name
      if (req.query.name) {
        fooCondtions.name = {
          [Op.like]: '%' + (req.query.name) + '%'
        }
      }
      // Query param id
      if (req.query.id) {
        fooCondtions.id = {
          [Op.equals]: '%' + (req.query.id) + '%'
        }
      }
      return fooConditions;
    }
    

    【讨论】:

      【解决方案3】:

      它会比您上面概述的要复杂一些。 Sequelize 必须对 ands 和 ors 有非常明确的声明,这意味着您必须使用 $and$or 选项来复制您正在寻找的内容。您在上面所做的只是在 JavaScript 中创建值并将它们传递给数据库。请尝试以下操作:

      models.user.findAll({
                      where: {
                          $and: [{
                              $or: [{
                                  username: {
                                      $like: '%' + searchParams.username '%'
                                  }
                              }, {
                                  username: null
                              }]
                          }, {
                              $or: [{
                                      id: searchParams.id
                              }, {
                                 id: null
                              }]
                          }]
                      }
                  })
      

      有关这方面的更多信息和一些很好的例子,请参阅他们的documentation

      【讨论】:

      • 这不是一回事。您的示例将返回等于 searchParams.id 或等于 null 的所有内容。如果searchParams.id 为null,或者等于searchParams.id 的所有内容,我想返回所有内容。看出区别了吗?
      • 基本上,我不知道如何检查 searchParams.id 是否为空。您可以在原始查询中轻松执行此操作,但我看不到使用 Sequelize 运算符执行此操作的方法。
      猜你喜欢
      • 1970-01-01
      • 2019-07-15
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 2018-06-22
      相关资源
      最近更新 更多