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

如何将聊天消息文档数组按连续用户分组拆分为多个数组?

解决方案:将连续相同用户的聊天消息分组

场景说明

你已经通过Messages.find().sort({ timestamp: 1 })获取到按时间升序排序的消息列表,现在需要将**连续相同userId**的消息归为独立数组(而非全局按userId合并)。


方法一:应用层(JavaScript)处理排序后的数组

拿到排序后的消息数组后,通过遍历对比当前与前一条消息的userId即可完成分组:

// 假设sortedMessages是你通过find().sort()获取的数组
const sortedMessages = await Messages.find().sort({ timestamp: 1 }).lean();

const groupedMessages = [];
if (sortedMessages.length === 0) return groupedMessages;

// 初始化第一个分组
let currentGroup = [sortedMessages[0]];
let currentUserId = sortedMessages[0].userId;

for (let i = 1; i < sortedMessages.length; i++) {
  const message = sortedMessages[i];
  if (message.userId === currentUserId) {
    // 同用户消息,加入当前分组
    currentGroup.push(message);
  } else {
    // 用户切换,存入当前分组并初始化新分组
    groupedMessages.push(currentGroup);
    currentGroup = [message];
    currentUserId = message.userId;
  }
}
// 加入最后一个分组
groupedMessages.push(currentGroup);

console.log(groupedMessages);

执行后会得到你期望的结构:连续相同用户的消息被打包为子数组,顺序与时间排序完全一致。


方法二:MongoDB聚合管道实现(大数据量推荐)

如果数据量较大,直接在数据库层面完成分组能减少传输开销、提升效率。利用$setWindowFields标记连续用户的分组ID,再按ID聚合:

const groupedMessages = await Messages.aggregate([
  // 1. 按时间升序排序
  { $sort: { timestamp: 1 } },
  // 2. 用窗口函数标记连续用户的分组ID
  {
    $setWindowFields: {
      sortBy: { timestamp: 1 },
      output: {
        groupId: {
          $sum: {
            $cond: [
              { $ne: ["$userId", { $lag: "$userId" }] },
              1,
              0
            ]
          }
        }
      }
    }
  },
  // 3. 按分组ID聚合消息
  {
    $group: {
      _id: "$groupId",
      messages: { $push: "$$ROOT" }
    }
  },
  // 4. 按分组ID排序,保证顺序正确
  { $sort: { _id: 1 } },
  // 5. 整理输出格式
  { $project: { _id: 0, messages: 1 } },
  { $group: { _id: null, result: { $push: "$messages" } } },
  { $project: { _id: 0, result: 1 } }
]);

// 最终结果在groupedMessages[0].result中
console.log(groupedMessages[0].result);

管道逻辑说明:

  • $setWindowFields:通过$lag获取前一条消息的userId,若与当前不同则groupId加1,实现连续用户的分组标记。
  • 后续的$group与$sort负责将标记后的消息整理为目标结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:05:29