How to perform a search with conditional where parameters using Sequelize

旧巷老猫 提交于 2020-01-14 09:33:03

问题


Usually whenever I write a search query for SQL, I do something similar to this:

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

Basically this simulates a conditional WHERE clause. We only want to compare @searchParam to the column if @searchParam was provided.

Is there a way to replicate this using Sequelize?

EDIT: Here is my best attempt which fails:

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

UPDATE: I found a way to do it, but it feels like a workaround. I'm certain there has to be a more elegant way. This works, but is ugly:

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

回答1:


You can just prepare object with needed conditions. Simple and easy to understand

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



回答2:


that's pretty awesome. thank you. i use your ideas like that:

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:


It'd be a little more complicated than you've outlined above. Sequelize has to have pretty explicit statements on ands and ors, and that means you have to use the $and and $or options to replicate what you're looking for. What you've done above is merely create the values in JavaScript and pass them to the database. Try the following:

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

For more on this, and some good examples, see their documentation.



来源:https://stackoverflow.com/questions/42236837/how-to-perform-a-search-with-conditional-where-parameters-using-sequelize

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!