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

如何优化Mongo聚合管道,避免OOM并获取各事件类型最近5条文本?

聚合管道OOM问题优化方案:获取各event_type最近5条text样本

原管道在处理百万级文档时,$group阶段会将每个event_type下的所有text存入数组,导致内存占用过高引发OOM。以下是针对性优化方案:

方案1:先排序再分组,仅保留最新5条text

先按event_type分组前,将同类型文档按时间倒序排序,分组时只保留最新的5条text,避免积累大量无效数据:

Events.aggregate([
    { $match: { event_type: { $in: [1,5,10,12] } } },
    // 同event_type内按time倒序排列,确保最新文档在前
    { $sort: { event_type: 1, time: -1 } },
    {
        $group: {
            _id: "$event_type",
            avgTime: { $avg: "$time" },
            avgCost: { $avg: "$cost" },
            maxCost: { $max: "$cost" },
            maxTime: { $max: "$time" },
            // 每次push后立即截取前5条,避免数组无限膨胀
            texts: { $slice: [{ $push: "$text" }, 5] }
        }
    }
])

方案2:创建复合索引加速查询与排序

针对$match和$sort阶段创建复合索引,减少磁盘IO与内存排序开销:

// 创建复合索引
Events.createIndex({ event_type: 1, time: -1 })

该索引可直接用于$match过滤指定event_type,同时让$sort阶段无需在内存中排序,大幅降低内存占用。

方案3:拆分任务,单event_type单独处理

如果聚合统计与样本获取可以拆分,可对每个event_type单独执行查询,避免一次性处理所有数据:

// 遍历每个event_type,分别查询统计与最新text
const eventTypes = [1,5,10,12];
const results = await Promise.all(eventTypes.map(async (type) => {
    // 获取最新5条text
    const latestTexts = await Events.find({ event_type: type })
        .sort({ time: -1 })
        .limit(5)
        .map(doc => doc.text)
        .toArray();
    // 计算聚合统计
    const stats = await Events.aggregate([
        { $match: { event_type: type } },
        {
            $group: {
                _id: null,
                avgTime: { $avg: "$time" },
                avgCost: { $avg: "$cost" },
                maxCost: { $max: "$cost" },
                maxTime: { $max: "$time" }
            }
        }
    ]).next();
    return {
        event_type: type,
        avgTime: stats.avgTime,
        avgCost: stats.avgCost,
        maxCost: stats.maxCost,
        maxTime: stats.maxTime,
        texts: latestTexts
    };
}));

方案4:使用窗口函数(MongoDB 5.0+)

利用$setWindowFields窗口函数,在计算聚合统计的同时高效获取最新N条数据,避免$group阶段的大数组:

Events.aggregate([
    { $match: { event_type: { $in: [1,5,10,12] } } },
    { $sort: { event_type: 1, time: -1 } },
    {
        $setWindowFields: {
            partitionBy: "$event_type",
            sortBy: { time: -1 },
            output: {
                avgTime: { $avg: "$time", window: { documents: ["unbounded", "current"] } },
                avgCost: { $avg: "$cost", window: { documents: ["unbounded", "current"] } },
                maxCost: { $max: "$cost", window: { documents: ["unbounded", "current"] } },
                maxTime: { $max: "$time", window: { documents: ["unbounded", "current"] } },
                // 标记同组内的文档排名
                rank: { $rank: {} }
            }
        }
    },
    // 仅保留每个event_type的前5条文档
    { $match: { rank: { $lte: 5 } } },
    {
        $group: {
            _id: "$event_type",
            avgTime: { $first: "$avgTime" },
            avgCost: { $first: "$avgCost" },
            maxCost: { $first: "$maxCost" },
            maxTime: { $first: "$maxTime" },
            texts: { $push: "$text" }
        }
    }
])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:15:39