Sequelize 的“嵌套模型查询”最终会生成SQL“连接查询”语句,即生成'inner join'
、'left join'
等。在连接查询时,我们在可以连接阶段通过'on ... and'
(如:ON A.id = B.user_id AND B.name = 'itbilu.com'
)来对连接表进行筛选,可以在where
条件中(如:WHERE B.name = 'itbilu.com'
)进行筛选。除数据筛选外,结果排序也会经常用到。在SQL语句中,对连接表排序比较简单,直接把连接表的排序字段放到order by
子语句中即可(如:'ORDER BY B.name ASC'
)。在Sequelize中,同样也可以支持连接模型的筛选和排序。以下是Sequelize中连接模型的筛选与排序的使用小技巧。
1. Sequelize 与连接模型的筛选
Sequelize 通过'include'
属性来生成连接查询语句,对连接模型(连接表)数据进行筛选时,我们可以将筛选条件放在'include'
连接模型的'where'
属性中,也可以放在顶级'where'
属性中。
连接模型'where'
我们有如下两个模型,并在连接模型中使用'where'
属性:
const User = sequelize.define('user', { id: Sequelize.INT, account: Sequelize.STRING, password: Sequelize.STRING }); const Player = sequelize.define('player', { id: Sequelize.INT, userId: Sequelize.INT, name: Sequelize.STRING }); User.hasOne(Player); let include = [{ model: Player, where: {name:'itbilu.com'} }]; User.findAll({ include: include }).then((users) => { console.log(JSON.stringify(users)) })
以上查询会生成类似如下SQL语句:
SELECT * FROM user INNER JOIN player ON user.id = player.userId AND player.name = 'itbilu.com';
顶级'where'
我们也可以将'on'
中筛选条件放到顶级'where'
属性中。在顶级'where'
中,使用'$nested.column$'
语法格式进行连接模型(连接表)的数据筛选。
同样是
let include = [{ model: Player, where: {name:'itbilu.com'} }]; User.findAll({ where: {'$player.name$':'itbilu.com'}, include: include }).then((users) => { console.log(JSON.stringify(users)) })
以上查询会生成类似如下SQL语句:
SELECT * FROM user INNER JOIN player user.id = player.userId where player.name = 'itbilu.com';
由上可见,在连接模型的'where'
属性中进行筛选时,最终生成的SQL语句会在'ON'
条件中进行筛选。也就是说,数据筛选是在表连接之前;而在顶级'where'
属性中进行筛选时,最终生成的SQL语句会在'WHERE'
条件中进行筛选,也就是说,的筛选在表连接之后。一般来说,前者的执行效率要高于后者。
2. Sequelize 与连接模型的排序
在Sequelize中,通过'order'
属性生成'ORDER BY'
排序SQL。'order'
属性支持字符串格式:
User.findAll({order:'id DESC'});
也支持数组(二维数组)格式:
User.findAll({order:[['id', DESC]]});
如果使用连接模型字段排序,就要向排序数组中传入3个值:
User.findAll({ include:[ Player ], order:[[Player, 'id', DESC]]});
如果有更多级的嵌套,就要向排序数组中传入更多的值:
const PlayerLevel = sequelize.define('playerLevel', { id: Sequelize.INT, playerId: Sequelize.INT, level: Sequelize.INT }) Player.hasOne(PlayerLevel); let include = [{ model: Player, include: [PlayerLevel] }]; User.findAll({ include:include, order:[[Player, PlayerLevel, 'level', DESC]]});
以上生成的排序语句类似如下:
ORDER BY player.playerLevel.level DESC
或者,使用sequelize.col()
函数来处理多级嵌套。以上查询等价于:
User.findAll({ include:include, order:[[sequelize.col('player.playerLevel.level'), DESC]]});
更多参考: