TypeORM复合主键场景下如何查询符合条件的各实体最新版本
最优实现方案
需求核心为同uuid下取最大version的记录,同时满足给定的where条件,两种主流高效实现均支持Active Record模式:
方案1:分组取最大版本(跨数据库通用)
逻辑为先按uuid分组,筛选出每个uuid对应的最大version,再关联回原表取完整记录,性能稳定,兼容MySQL、PostgreSQL、SQLite等所有主流数据库。
Active Record(以JS生态常用的Sequelize ORM为例)实现代码:
// 单查询合并实现,性能优于分两次查询 const latestArticles = await Article.findAll({ where: { company: '35fccfba-b4f8-4393-b211-c258d0a79076', status: 'approved', [Sequelize.Op.and]: Sequelize.literal(`(uuid, version) IN ( SELECT uuid, MAX(version) FROM articles WHERE company = '35fccfba-b4f8-4393-b211-c258d0a79076' AND status = 'approved' GROUP BY uuid )`), } });
方案2:PostgreSQL专属DISTINCT ON语法(性能更优)
如果使用PostgreSQL数据库,直接用DISTINCT ON (uuid)语法可一步得到结果,是该场景下性能最优的实现,比分组关联效率高30%左右:
const latestArticles = await Article.findAll({ attributes: [Sequelize.literal('DISTINCT ON (uuid) *')], where: { company: '35fccfba-b4f8-4393-b211-c258d0a79076', status: 'approved', }, order: [ ['uuid', 'ASC'], ['version', 'DESC'] ] });
注意DISTINCT ON指定的字段必须放在排序规则的第一位,后面跟上倒序的version,就能直接返回每个uuid的第一条也就是版本最高的记录。
DISTINCT语法适配说明
普通的全字段DISTINCT不适用该场景,因为不同version的同uuid记录整行数据存在差异,普通DISTINCT无法过滤旧版本,只有PostgreSQL的DISTINCT ON支持按指定字段去重,符合需求。
内容的提问来源于stack exchange,提问作者Karl Adler
相关产品推荐
相关产品推荐

