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

如何获取每个聊天室的最新单条消息?聚合与循环查询对比

问题

我希望获取每个聊天室的最新用户消息数组,但当前实现的Go语言MongoDB查询代码返回的是所有聊天室的全部消息。现有代码如下:

func (r *Mongo) findLastMessages(ctx context.Context, chatIds []string) ([]*Message, error) {

    if len(chatIds) == 0 {
        return nil, nil
    }

    query := bson.M{"chat_id": bson.M{"$in": chatIds}}
    cursor, err := r.colMessage.Find(ctx, query, nil)
    if err != nil {
        return nil, err
    }

    var messages []*Message
    if err = cursor.All(ctx, &messages); err != nil {
        return nil, err
    }

    err = cursor.Close(ctx)
    if err != nil {
        return nil, ErrInternal
    }

    return messages, err
}

请问如何过滤以得到每个聊天室的最后一条消息?另外,是否应使用聚合查询?若使用聚合,相比循环Find哪种方式更优?


解决方案

1. 用聚合查询获取每个聊天室的最新消息

推荐使用MongoDB聚合框架,直接在数据库层面完成筛选、排序和分组,得到每个聊天室的最新消息。修改后的代码如下:

func (r *Mongo) findLastMessages(ctx context.Context, chatIds []string) ([]*Message, error) {
    if len(chatIds) == 0 {
        return nil, nil
    }

    pipeline := []bson.M{
        // 筛选指定聊天室的所有消息
        {"$match": bson.M{"chat_id": bson.M{"$in": chatIds}}},
        // 按消息创建时间倒序排序,确保最新消息排在首位
        {"$sort": bson.M{"created_at": -1}},
        // 按chat_id分组,取每组第一条(最新)消息
        {"$group": bson.M{
            "_id": "$chat_id",
            "lastMessage": bson.M{"$first": "$$ROOT"},
        }},
        // 将分组后的消息内容作为根文档,匹配原Message结构
        {"$replaceRoot": bson.M{"newRoot": "$lastMessage"}},
    }

    cursor, err := r.colMessage.Aggregate(ctx, pipeline)
    if err != nil {
        return nil, err
    }
    defer cursor.Close(ctx)

    var messages []*Message
    if err = cursor.All(ctx, &messages); err != nil {
        return nil, err
    }

    return messages, nil
}

2. 聚合查询 vs 循环Find的优劣对比

聚合查询是更优的选择,理由如下:

  • 减少网络开销:聚合仅需一次数据库请求,直接返回最终结果;循环Find需要为每个chatId发起一次请求,chatIds数量越多,网络延迟和开销越大。
  • 降低应用层压力:聚合在数据库端完成数据筛选和分组,应用层无需处理大量冗余数据,节省内存和CPU资源。
  • 保证一致性:聚合是单次原子操作,避免循环查询过程中数据更新导致的结果不一致问题。

仅当chatIds数量极少(比如个位数)时,循环Find的性能差异可忽略,但从扩展性和长期性能来看,聚合查询是更合理的方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:50:36