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

MongoDB聚合查询:按书籍作者统计文档数量的问题排查

MongoDB聚合统计指定作者书籍数量

集合数据

bookSchema集合中的数据如下:

[
  {
    _id: ObjectId("637d05dc32428ed75ea08d09"),
    book_details: {
      book_name: "random123",
      book_auth: "Amber"
    }
  },
  {
    _id: ObjectId("637d0673ce0f17f6c473dee2"),
    book_details: {
      book_name: "random321",
      book_auth: "Amber"
    }
  },
  {
    _id: ObjectId("637d069a3d597c8458ebe4ec"),
    book_details: {
      book_name: "random676",
      book_auth: "Amber"
    }
  },
  {
    _id: ObjectId("637d06c05b32d503007bcb54"),
    book_details: {
      book_name: "random999",
      book_auth: "Saurav"
    }
  }
]

期望输出

需要得到如下格式的统计结果:

{
  score_ambr: 3,
  score_saurabh: 1
}

尝试的错误查询及问题

使用以下聚合语句时,结果不符合预期:

db.bookSchema.aggregate([
  {
    "$group": {
      "_id": {
        "$eq": [
          "$book_details.book_auth",
          "Amber"
        ]
      },
      "score_ambr": {
        "$sum": 1
      }
    },
  },
  {
    "$group": {
      "_id": {
        "$eq": [
          "$book_details.book_auth",
          "Saurav"
        ]
      },
      "score_saurabh": {
        "$sum": 1
      }
    },
  }
])

错误原因:

  • 连续的$group阶段会丢弃前一阶段的非_id字段,第二个$group无法访问原始的book_details.book_auth字段,导致分组逻辑失效。
  • 分组依据使用$eq返回布尔值,无法精准区分目标作者,统计逻辑错误。

正确实现方法

方法一:单分组阶段条件统计(推荐)

直接在一次$group中通过$cond条件判断,分别累加指定作者的书籍数量:

db.bookSchema.aggregate([
  {
    "$group": {
      "_id": null,
      "score_ambr": {
        "$sum": {
          "$cond": [{ "$eq": ["$book_details.book_auth", "Amber"] }, 1, 0]
        }
      },
      "score_saurabh": {
        "$sum": {
          "$cond": [{ "$eq": ["$book_details.book_auth", "Saurav"] }, 1, 0]
        }
      }
    }
  },
  { "$project": { "_id": 0 } }
])

逻辑说明:

  • $group按null分组,将所有文档聚合为一组。
  • 每个$sum中用$cond判断作者是否匹配,匹配则加1,否则加0,最终得到对应作者的书籍总数。
  • $project移除多余的_id字段,得到期望格式。

方法二:分组后转键值对

先按作者分组统计数量,再将结果转换为指定键名的对象:

db.bookSchema.aggregate([
  // 按作者分组统计数量
  {
    "$group": {
      "_id": "$book_details.book_auth",
      "count": { "$sum": 1 }
    }
  },
  // 将分组结果转为键值对数组
  {
    "$group": {
      "_id": null,
      "scores": {
        "$push": {
          "k": {
            "$cond": {
              if: { "$eq": ["$_id", "Amber"] },
              then: "score_ambr",
              else: "score_saurabh"
            }
          },
          "v": "$count"
        }
      }
    }
  },
  // 将键值对数组转为对象并作为根文档
  {
    "$replaceRoot": {
      "newRoot": { "$arrayToObject": "$scores" }
    }
  }
])

逻辑说明:

  • 第一个$group统计每个作者的书籍数量。
  • 第二个$group将所有分组结果聚合,用$push生成包含指定键名(k)和数量(v)的数组。
  • $replaceRoot结合$arrayToObject将键值对数组转换为目标格式的对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:41:15