Sequelize(PostgreSQL)中如何获取关联未读消息的数量?
解决方案
要在findAndCountAll查询中获取未读消息的数字计数并返回Unread_messages字段,你可以通过Sequelize的聚合函数或子查询实现,以下是两种可行的修改方式:
方式一:使用聚合函数+关联查询
这种方式通过关联Message模型并使用COUNT聚合函数计数,需要配合group子句确保分组正确:
// 先导入Sequelize的fn和col方法 import { Sequelize, fn, col } from 'sequelize'; static async fetchData(page: number, DataId: number) { const limit = 20; const offset = (page - 1) * limit; return await Data.findAndCountAll({ include: [ { model: SomeData1, as: 'someData1', required: false }, { model: Data2, as: 'data2', attributes: [ 'id', 'name', // 添加计数字段,别名Unread_messages [fn('COUNT', col('unreadMessageCount.id')), 'Unread_messages'] ], required: true, where: { is_deleted: false }, include: [ { model: Message, as: 'unreadMessageCount', where: { someDataid: DataId, status: 'UNREAD' }, attributes: [], // 不返回Message的任何属性 required: false } ], // 必须按Data2的属性分组,否则聚合函数会报错 group: ['data2.id', 'data2.name'] } ], where: { DataId: DataId }, offset, limit, distinct: true, // 若主查询count异常,可设置subQuery: false避免分组影响主计数 subQuery: false }); }
方式二:使用子查询直接计数
这种方式无需关联Message模型,通过literal写入子查询直接计算未读消息数,避免分组带来的复杂问题:
// 导入Sequelize import { Sequelize } from 'sequelize'; static async fetchData(page: number, DataId: number) { const limit = 20; const offset = (page - 1) * limit; return await Data.findAndCountAll({ include: [ { model: SomeData1, as: 'someData1', required: false }, { model: Data2, as: 'data2', attributes: [ 'id', 'name', // 子查询直接计算当前data2对应的未读消息数 [ Sequelize.literal(`( SELECT COUNT(*) FROM Message WHERE Message.someDataid = ${DataId} AND Message.status = 'UNREAD' AND Message.data2Id = data2.id )`), 'Unread_messages' ] ], required: true, where: { is_deleted: false } // 无需include Message模型 } ], where: { DataId: DataId }, offset, limit, distinct: true }); }
注意事项
- 方式一中,
group子句必须包含Data2的所有非聚合属性(即id和name),否则会触发SQL分组错误。 - 若主查询的
count结果异常,可添加subQuery: false关闭子查询模式,确保计数逻辑正确。 - 方式二中,注意替换
Message.data2Id为你实际的外键字段名(即Message表中关联Data2的字段)。
内容的提问来源于stack exchange,提问作者Devkong
相关产品推荐
相关产品推荐

