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

如何用Scala+ReactiveMongo单次查询分组统计MongoDB文件类型数量

解决MongoDB Scala聚合查询统计文件类型数量的问题

你的代码存在两个核心问题导致结果异常:

  1. Group阶段写法错误:原代码用Group(BSONDocument("_id" -> "$contentType"))的方式不符合Scala驱动的API规范,无法正确生成分组的_id字段
  2. 只获取单个聚合结果:聚合查询会返回每个文件类型对应的统计文档,你只取了第一个结果,导致所有类型的数量都相同

修正后的代码

def contentTypeStats(implicit ec: ExecutionContext): Future[ContentTypesDTO] = {
  collectionFactory.collection().flatMap(collection => {
    import collection.AggregationFramework._
    
    // 构建正确的聚合管道
    val pipeline = List(
      Match(BSONDocument("metadata.s" -> BSONDocument("$ne" -> "thumbnail"))),
      Group(Field("contentType"))("count" -> Sum(1)) // 修正Group和Sum的写法
    )
    
    // 获取所有聚合结果,而非单个文档
    val result: Future[List[BSONDocument]] = 
      collection.aggregatorContext[BSONDocument](pipeline)
        .prepared.cursor.collect[List]()

    result.map { statsDocs =>
      // 初始化各类型数量为0
      var pngCount = 0L
      var jpgCount = 0L
      var pdfCount = 0L
      
      // 遍历所有统计文档,匹配类型赋值
      statsDocs.foreach { doc =>
        doc.getAsOpt[String]("_id").foreach { contentType =>
          val count = doc.getAsOpt[Long]("count").getOrElse(0L)
          contentType match {
            case "image/png" => pngCount = count
            case "image/jpeg" => jpgCount = count
            case "application/pdf" => pdfCount = count
            case _ => // 忽略其他未知类型
          }
        }
      }
      
      ContentTypesDTO(pngCount, jpgCount, pdfCount)
    }
  })
}

关键修正说明

  • Group阶段:使用Group(Field("contentType"))对应MongoDB聚合中的_id: "$contentType",这是Scala驱动中按字段分组的标准写法
  • Sum操作:用Sum(1)替代SumAll,对应MongoDB的$sum: 1,实现对每组文档的计数
  • 结果收集:用cursor.collect[List]()获取所有聚合结果文档,而不是只取第一个
  • 结果映射:遍历所有统计文档,根据_id(即contentType的值)来分别填充DTO的各个字段,确保每个类型的数量正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:20:13