在nodejs项目中,接口会接收从前台传来的查询参数,接口里面根据请求参数动态查询数据库,例如分页参数等等;sequelize官方文档中并没有提及如何做,不过可以利用sequelize的特性去巧妙实现。下面介绍两种方式:
先来看第一种方式:由于sequelize的where查询条件本身就是一个对象object,所以我们可以利用这种特性,提前根据请求参数以及各种条件判断来构造这个对象,构造完以后,放进对应的查询位置就好,代码如下:
// 这是一个在前台展示用户列表的接口
static async list(req, resp) { // 前台可能会传来nickname、account来模糊查询,以及分页参数 const {page, pageSize, nickname, account} = req.query; // where条件接受一个对象传入,先定义一个对象,用{}符号 let criteria = {}; const start = (page - 1) * pageSize; let total = 0; let list = null; // 检查前台传来的参数是否为空,从而构造各种查询条件
if (nickname) { criteria['nickname'] = nickname; if (account) { // 这里用的就是纯粹的=符号,代表精确查找,下面例举了like符号,更多符号自己探索 criteria['account'] = account; } } else if (account) { // 这里后面赋值的是like操作符,代表模糊查询,后面account用``反引号字符串替换模板将account代入进去 criteria['account'] = {$like: `%${account}%`}; }await UserModel.findAndCountAll({ where: criteria, // 将前面构造的对象传入 offset: start, limit: Number(pageSize)}).then( // 由于前端使用了element-ui,传过来的pageSize是string型,要转一下 result => { total = result.count; list = result.rows; }); resp.json(new result(200, {total, list})); }
如果你都是根据前台传来的请求参数进行精确查找的话,那么上面的代码完全可以写成下面这种形式:
这是因为where: {nickname , account }这句代码,还记得我们说过where参数可以是一个对象吗,在sequelize中那句代码就代表where: {nickname: nickname , account: account },传进的参数即是参数名,本身也是参数值。如下所示:
static async list(req, resp) {
const {page, pageSize, nickname, account} = req.query;
let criteria = {};
const start = (page - 1) * pageSize;
let total = 0;
let list = null;
await UserModel.findAndCountAll({
where: {nickname , account },
offset: start,
limit: Number(pageSize)}).then(
result => {
total = result.count;
list = result.rows;
});
resp.json(new result(200, {total, list}));
}
第二种方式如下所示:它将判断条件都放到了where中,用的是三目运算符,假如条件为真,中括号里面像是在拼装原生sql语句,并且还用到了?号占位符,两个参数外面用了一个sequelize.and包裹,这个符号等同于$and,当然如果你需要其他查询方式,可以换成其他符号,例如or等等。我的项目使用了TypeScript,在我的项目中下面这种方式代码下面一直冒红
await UserModel.findAndCountAll({
where: sequelize.and(
nickname ? ['nickname = ?', nickname] : null,
account ? ['account = ?', account] : null
),
offset: start,
limit: Number(pageSize)}).then(
result => {
total = result.count;
list = result.rows;
});
如果上面代码不冒红能正常编译的话,where条件的sql语句打印出来为 where (nickname='xxxx' and account='xxxxx' ),假如account为空null的话,打印出来的sql语句为where (nickname='xxxx' and 1=1 );假如两个参数都为空,那就是where (1=1 and 1=1 );奇妙吧,对你的查询结果丝毫没有影响,因为你本来就是想要查询全部结果。总之使用了typescript的话,这种方式用不了,原始的javascript可以试一下
随后我就改良了一下,将中括号里面的语句改成反引号字符串替换模板形式,where关键词又冒红
await UserModel.findAndCountAll({
where: sequelize.and(
nickname ? `nickname = ${nickname}` : null,
account ? `account = ${account}` : null),
offset: start,
limit: Number(pageSize)}).then(
result => {
total = result.count;
list = result.rows;
});
因为sequelize和typescript语法经常冲突,所以我就想先运行试一下,运行时,调用接口,报下面的错误:Error: Support for `{where: 'raw query'}` has been removed.
我用的sequelize版本为4.41.2,可能raw 查询不支持了,或者默认关闭了,我看到有个参数为raw,可以将它设置true,我没试。
参考链接:https://github.com/sequelize/sequelize/issues/1955
https://stackoverflow.com/questions/26106165/sequelize-dynamic-query-params
https://stackoverflow.com/questions/36466395/sequelize-optional-where-clause-parameters