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

如何让Sequelize findAll内连接后返回重复的表A行JSON结果?

问题描述

需要通过Sequelize的findAll方法实现:返回的JSON结果中,根据表B(Message)的匹配项,重复返回表A(Conversation)的行,每行仅包含一个关联的Message。

当前代码:

await this._conversation.findAll({
        include: [
            {
                required: true,
                model: Message,
                as: 'messages',
                where: message_query,
            },
        ],
    })

当前返回结果:

[
  { // Conversation [ table A ]
    ....
    "messages": [
      { // message 1 [ table B ]
        ....
      }, 
      { // message 2 [ table B ]
        ....
      }, 
      { // message 3 [ table B ]
        ....
      }, 
    ]
  }
]

期望返回结果:

[
  { // Conversation [ table A ]
    ....
    "messages": [
      { // message 1 [ table B ]
        ....
      }, 
    ]
  },
  { // Conversation [ table A ]
    ....
    "messages": [
      { // message 2 [ table B ]
        ....
      }, 
    ]
  },
  { // Conversation [ table A ]
    ....
    "messages": [
      { // message 3 [ table B ]
        ....
      }, 
    ]
  },
]

原生SQL查询能得到目标结果:

SELECT 
  * 
FROM 
  `conversations` 
  INNER JOIN `messages` 
ON 
  `conversations`.`id` = `messages`.`conversation_id`
解决方案

Sequelize默认会将同一父模型(Conversation)的关联子模型(Message)聚合到数组中,要实现原生SQL的效果,需要手动调整查询或转换结果结构。

方法一:使用raw+nest查询后手动转换

通过raw: true获取原生SQL返回的平级数据,再将结构转换为期望的格式:

// 执行查询,获取平级的关联数据
const rawResults = await this._conversation.findAll({
  include: [
    {
      required: true,
      model: Message,
      as: 'messages',
      where: message_query,
    },
  ],
  raw: true,
  nest: true // 嵌套关联字段,避免字段名冲突
});

// 转换为期望的结构
const formattedResults = rawResults.map(item => {
  const conversation = {};
  const singleMessage = {};
  // 拆分Conversation和Message的字段
  Object.keys(item).forEach(key => {
    if (key.startsWith('messages.')) {
      singleMessage[key.replace('messages.', '')] = item[key];
    } else {
      conversation[key] = item[key];
    }
  });
  return {
    ...conversation,
    messages: [singleMessage]
  };
});

方法二:从Message模型反向查询并转换结构

如果Message和Conversation已建立反向关联(Message属于Conversation),可以直接查询Message,再将结构反转:

// 假设Message模型中关联Conversation的别名为`conversation`
const messages = await Message.findAll({
  include: [
    {
      required: true,
      model: Conversation,
      as: 'conversation'
    }
  ],
  where: message_query
});

// 转换为目标结构
const formattedResults = messages.map(msg => {
  // 转换为JSON对象(如果是Sequelize实例的话)
  const convData = msg.conversation.toJSON ? msg.conversation.toJSON() : msg.conversation;
  const msgData = msg.toJSON ? msg.toJSON() : msg;
  // 删除Message中的conversation字段,避免冗余
  delete msgData.conversation;
  return {
    ...convData,
    messages: [msgData]
  };
});

内容的提问来源于stack exchange,提问作者yeln

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:34:52