汇总 MongoDB 数据

MongoDBBeginner
立即练习

介绍

在本实验中,你将学习如何在 MongoDB 中执行基本的聚合操作。这些操作允许你处理数据记录并返回计算结果。你将学习如何计算总数、查找最小值和最大值、计数文档以及计算平均值。本实验使用一个示例 bookstore 集合来展示 MongoDB 聚合框架从数据中提取有意义的见解的能力。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 92%。获得了学习者 100% 的好评率。

连接和填充数据

在我们可以汇总数据之前,我们需要连接到 MongoDB 服务器并插入一些示例数据。在此步骤中,你将启动 MongoDB Shell,创建一个数据库,并用书籍信息填充一个集合。

首先,打开你的终端并启动 MongoDB Shell (mongosh):

mongosh

你现在已进入 MongoDB Shell,它允许你与数据库进行交互。让我们切换到一个名为 bookstore 的新数据库。如果数据库不存在,MongoDB 会在你首次存储数据时为你创建它。

use bookstore

接下来,我们将使用 insertMany() 方法将多个书籍文档插入到一个名为 books 的集合中。每个文档都是一个 JSON 对象,包含 titlepricequantity

db.books.insertMany([
  { title: "Python Basics", price: 29.99, quantity: 50 },
  { title: "MongoDB Essentials", price: 39.99, quantity: 30 },
  { title: "Data Science Guide", price: 45.5, quantity: 25 },
  { title: "Web Development", price: 34.75, quantity: 40 }
]);

你应该会看到一条输出,确认文档已成功插入。

为了验证数据是否已添加,你可以使用 find() 方法检索并显示 books 集合中的所有文档。

db.books.find();

输出将列出你刚刚插入的四个文档,每个文档都有一个由 MongoDB 分配的唯一 _id

[
  {
    _id: ObjectId("..."),
    title: 'Python Basics',
    price: 29.99,
    quantity: 50
  },
  {
    _id: ObjectId("..."),
    title: 'MongoDB Essentials',
    price: 39.99,
    quantity: 30
  },
  {
    _id: ObjectId("..."),
    title: 'Data Science Guide',
    price: 45.5,
    quantity: 25
  },
  {
    _id: ObjectId("..."),
    title: 'Web Development',
    price: 34.75,
    quantity: 40
  }
]

现在我们的集合已设置完毕,我们可以继续执行聚合操作了。

计算总数

在此步骤中,你将学习如何使用 MongoDB 的聚合框架计算总值。聚合管道通过一系列阶段处理数据。我们将使用 $group 阶段对文档进行分组,并使用 $sum 操作符执行计算。

让我们开始计算所有书名的总库存数量。我们将所有文档分组到一个单独的组中,并对它们的 quantity 字段求和。

db.books.aggregate([
  {
    $group: {
      _id: null,
      totalQuantity: { $sum: "$quantity" }
    }
  }
]);

以下是对该命令的分解说明:

  • db.books.aggregate([...]): 在 books 集合上启动一个聚合管道。
  • $group: 对输入文档进行分组的阶段。
  • _id: null: 指定集合中的所有文档都应分组到一个输出文档中。
  • totalQuantity: { $sum: "$quantity" }: 定义一个新字段 totalQuantity$sum 操作符计算组中所有文档 quantity 字段(以 $ 开头)的总和。

预期的输出是:

[{ "_id": null, "totalQuantity": 145 }]

接下来,让我们计算所有书籍的总库存价值。这需要将每本书的 price 乘以 quantity,然后将结果相加。

db.books.aggregate([
  {
    $group: {
      _id: null,
      totalBookValue: { $sum: { $multiply: ["$price", "$quantity"] } }
    }
  }
]);

在此管道中:

  • $multiply: ["$price", "$quantity"]: 此表达式将每个文档的 pricequantity 字段相乘。
  • $sum: 此操作符然后将所有文档的乘法结果相加。

预期的输出是:

[{ "_id": null, "totalBookValue": 5226.7 }]

查找最小值和最大值

查找数据集中的最小值和最大值是一项常见的分析任务。在此步骤中,你将使用 $min$max 聚合操作符来查找我们集合中最便宜和最昂贵的书籍。

$sum 类似,$min$max 操作符在 $group 阶段中使用。让我们创建一个单一的聚合管道来查找最低和最高书籍价格。

db.books.aggregate([
  {
    $group: {
      _id: null,
      lowestPrice: { $min: "$price" },
      highestPrice: { $max: "$price" }
    }
  }
]);

此管道的工作原理如下:

  • _id: null: 将所有文档分组在一起。
  • lowestPrice: { $min: "$price" }: 创建一个字段 lowestPrice,并将其值设置为所有文档中 price 字段的最小值。
  • highestPrice: { $max: "$price" }: 创建一个字段 highestPrice,并将其值设置为 price 字段的最大值。

预期的输出将显示在集合中找到的最低和最高价格:

[{ "_id": null, "lowestPrice": 29.99, "highestPrice": 45.5 }]

你可以将相同的逻辑应用于其他数值字段。例如,要查找最低和最高库存数量,你可以在 quantity 字段上使用 $min$max

db.books.aggregate([
  {
    $group: {
      _id: null,
      lowestQuantity: { $min: "$quantity" },
      highestQuantity: { $max: "$quantity" }
    }
  }
]);

此查询的预期输出是:

[{ "_id": null, "lowestQuantity": 25, "highestQuantity": 50 }]

计数文档并计算平均值

在此步骤中,你将学习另外两种有用的汇总技术:计算文档数量和计算平均值。我们将探讨一种简单的计数方法以及用于更复杂场景的聚合框架。

首先,让我们计算 books 集合中文档的总数。countDocuments() 方法是执行此操作的最简单方法。

db.books.countDocuments();

输出将是一个数字:

4

你还可以为 countDocuments() 提供查询过滤器,以仅计算符合特定条件的文档。例如,让我们计算有多少本书的价格高于 $35。

db.books.countDocuments({ price: { $gt: 35 } });

$gt 操作符代表“大于”(greater than)。输出将是:

2

接下来,让我们使用聚合框架计算平均书价。$avg 操作符在 $group 阶段中使用,用于计算数值字段的平均值。

db.books.aggregate([
  {
    $group: {
      _id: null,
      averagePrice: { $avg: "$price" }
    }
  }
]);

此管道将所有文档分组,并计算 price 字段的平均值。输出将是:

[{ "_id": null, "averagePrice": 37.56 }]

聚合框架提供了一种强大而灵活的方式来执行计数和计算平均值等计算,尤其是在与其他阶段结合使用以处理更复杂的逻辑时。

生成汇总报告

在最后一步中,你将组合多个聚合阶段来生成一个更复杂的摘要报告。这展示了如何将操作符链接在一起,以创建对数据的有见地的视图。我们将创建一个报告,将书籍分为“Budget”(预算)和“Premium”(高级)价格等级,并为每个等级计算汇总统计信息。

我们的目标是根据书籍的价格进行分组,然后计算每个组的标题数量、总数量、总价值和平均价格。

运行以下聚合管道:

db.books.aggregate([
  {
    $group: {
      _id: {
        $cond: {
          if: { $lt: ["$price", 35] },
          then: "Budget",
          else: "Premium"
        }
      },
      totalBooks: { $sum: 1 },
      totalQuantity: { $sum: "$quantity" },
      totalValue: { $sum: { $multiply: ["$price", "$quantity"] } },
      avgPrice: { $avg: "$price" }
    }
  }
]);

让我们分解一下这个强大的管道:

  • $group: 此阶段是我们报告的核心。
  • _id: { $cond: ... }: 我们不使用 null,而是使用 $cond(条件)操作符来动态确定组 ID。如果一本书的 price 小于 ($lt) 35,它将被分配到“Budget”组;否则,它就是“Premium”组。
  • totalBooks: { $sum: 1 }: 这是在组内计数文档的常用技术。对于每个文档,它会向总数加 1
  • totalQuantity, totalValue, avgPrice: 这些是你之前步骤中学到的相同累加器,但现在它们在每个价格类别内运行。

输出为每个类别提供了清晰的摘要。请注意,文档的顺序可能会有所不同。

[
  {
    "_id": "Premium",
    "totalBooks": 2,
    "totalQuantity": 55,
    "totalValue": 2212.75,
    "avgPrice": 42.745
  },
  {
    "_id": "Budget",
    "totalBooks": 2,
    "totalQuantity": 90,
    "totalValue": 2984.5,
    "avgPrice": 32.37
  }
]

这个例子展示了如何使用聚合框架将原始数据转换为结构化、有意义的报告,直接在数据库中完成。

总结

在此次实验中,你学习了 MongoDB 中数据聚合的基础知识。你首先连接到数据库并使用示例数据填充了一个集合。然后,你使用了聚合框架来执行几项常见的汇总任务。你学会了如何使用带有 $sum 等操作符的 $group 阶段来计算总数,使用 $min$max 来查找边界值,以及使用 $avg 来计算平均值。你还练习了使用 countDocuments() 进行简单计数,并了解了如何通过组合多个操作符和阶段来构建一个多方面的摘要报告。这些技能对于分析数据和从你的 MongoDB 集合中获得有价值的见解至关重要。