通常每当我为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
]
})
答案 0 :(得分:9)
您可以根据需要准备对象。简单易懂
var whereStatement = {};
if(searchParams.id)
whereStatement.id = searchParams.id;
if(searchParams.username)
whereStatement.username = {$like: '%' + searchParams.username + '%'};
models.user.findAll({
where: whereStatement
});
答案 1 :(得分:0)
那太棒了。谢谢。我会这样使用您的想法:
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;
}
答案 2 :(得分:-1)
它比你上面概述的要复杂得多。 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。