You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 13:54:54