转换 MongoDB 数据

MongoDBBeginner
立即练习

介绍

在本实验中,你将学习如何使用 MongoDB 强大的聚合管道 (aggregation pipeline) 来转换数据。聚合管道允许你通过一系列阶段来处理数据,实现复杂的数据转换、分析和报告。你将从设置一个示例数据集开始,然后学习几种关键的转换技术,包括选择和重命名字段、根据现有数据计算新字段、格式化输出以及根据特定条件过滤文档。完成本实验后,你将对在 MongoDB 中操作数据打下坚实的基础。

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

设置与基础字段选择

在第一步中,你将连接到 MongoDB 服务器,创建一个数据库和集合,并插入一些示例数据。然后,你将通过选择和重命名字段来执行你的第一次数据转换。

首先,打开你的终端并启动 MongoDB Shell (mongosh)。这个交互式 shell 是与你的 MongoDB 实例交互的主要方式。在本实验的剩余部分,你将在该 shell 中执行所有数据库操作。

mongosh

进入 MongoDB Shell 后,你的提示符会发生变化。现在,创建一个名为 bookstore 的新数据库并切换到它。如果数据库不存在,此命令将创建它。

use bookstore

接下来,创建一个名为 books 的集合,并使用 insertMany 命令向其中插入三个示例文档。集合是文档的集合,类似于 SQL 数据库中的表。

db.books.insertMany([
  {
    title: "MongoDB Basics",
    author: "Jane Smith",
    price: 29.99,
    pages: 250,
    categories: ["Database", "Programming"]
  },
  {
    title: "Python Deep Dive",
    author: "John Doe",
    price: 39.99,
    pages: 450,
    categories: ["Programming", "Python"]
  },
  {
    title: "Data Science Handbook",
    author: "Alice Johnson",
    price: 49.99,
    pages: 600,
    categories: ["Data Science", "Programming"]
  }
]);

现在你有了数据,让我们使用聚合管道来转换它。aggregate 方法接受一个阶段数组,每个阶段对数据执行一个操作。我们的第一个阶段将是 $project,它会重塑文档。

运行以下命令来仅选择 titleauthor 字段,并将它们分别重命名为 bookTitlebookAuthor

db.books.aggregate([
  {
    $project: {
      _id: 0,
      bookTitle: "$title",
      bookAuthor: "$author"
    }
  }
]);

你应该会看到以下输出:

[
  { "bookTitle": "MongoDB Basics", "bookAuthor": "Jane Smith" },
  { "bookTitle": "Python Deep Dive", "bookAuthor": "John Doe" },
  { "bookTitle": "Data Science Handbook", "bookAuthor": "Alice Johnson" }
]

让我们分解一下 $project 阶段:

  • _id: 0 从输出中排除默认的 _id 字段。默认情况下,它总是包含在内。
  • bookTitle: "$title" 创建一个名为 bookTitle 的新字段,并将其值赋为原始的 title 字段。$ 前缀表示你正在引用一个字段的值。
  • bookAuthor: "$author" 类似地将 author 字段重命名为 bookAuthor

计算新字段

在上一步中,你选择了并重命了现有字段。现在,你将学习如何通过对现有数据执行计算来创建全新的字段。为此,你将使用 $addFields 阶段,它可以在不移除原始字段的情况下向文档添加新字段。

让我们添加一个名为 priceWithTax 的新字段,它计算包含 10% 税费的书籍价格。

db.books.aggregate([
  {
    $addFields: {
      priceWithTax: { $multiply: ["$price", 1.1] }
    }
  }
]);

输出将包含所有原始字段以及每个文档新增的 priceWithTax 字段:

[
  {
    _id: ObjectId("..."),
    title: 'MongoDB Basics',
    author: 'Jane Smith',
    price: 29.99,
    pages: 250,
    categories: [ 'Database', 'Programming' ],
    priceWithTax: 32.989
  },
  {
    _id: ObjectId("..."),
    title: 'Python Deep Dive',
    author: 'John Doe',
    price: 39.99,
    pages: 450,
    categories: [ 'Programming', 'Python' ],
    priceWithTax: 43.989
  },
  {
    _id: ObjectId("..."),
    title: 'Data Science Handbook',
    author: 'Alice Johnson',
    price: 49.99,
    pages: 600,
    categories: [ 'Data Science', 'Programming' ],
    priceWithTax: 54.989
  }
]

在此管道中:

  • $addFields 是用于添加新字段的阶段。
  • priceWithTax 是你正在创建的新字段的名称。
  • $multiply 是一个聚合运算符,它接受一个包含两个数字的数组并将其相乘。在这里,它将 price 字段的值乘以 1.1

格式化输出数据

数据经过适当格式化后通常更有用。在这一步中,你将学习如何在 $project 阶段中使用各种聚合运算符来格式化字符串和数字数据。这对于为应用程序或报告中的显示准备数据非常有用。

让我们通过将书名转换为大写并将价格格式化为货币字符串来创建更易读的输出。

db.books.aggregate([
  {
    $project: {
      _id: 0,
      titleUpperCase: { $toUpper: "$title" },
      formattedPrice: {
        $concat: [{ $literal: "$" }, { $toString: "$price" }]
      }
    }
  }
]);

预期的输出将显示转换后的数据:

[
  {
    "titleUpperCase": "MONGODB BASICS",
    "formattedPrice": "$29.99"
  },
  {
    "titleUpperCase": "PYTHON DEEP DIVE",
    "formattedPrice": "$39.99"
  },
  {
    "titleUpperCase": "DATA SCIENCE HANDBOOK",
    "formattedPrice": "$49.99"
  }
]

让我们检查一下此 $project 阶段中使用的运算符:

  • $toUpper: 此运算符将字符串转换为大写。我们将其应用于 title 字段。
  • $concat: 此运算符连接字符串数组。我们用它给价格添加一个美元符号 $ 前缀。
  • $literal: 此运算符用于表示那些否则会被解释为表达式的字面值。在这里,我们使用 { $literal: "$" } 来表示一个字面美元符号字符。
  • $toString: 由于 $concat 仅处理字符串,因此我们首先需要使用 $toString 运算符将数字类型的 price 字段转换为字符串。

使用 $match 过滤结果

你将学习的最后一个基本技术是过滤。$match 阶段允许你仅选择满足特定条件的文档,这类似于 SQL 中的 WHERE 子句。它是聚合管道中最常见的阶段之一。

让我们查找所有价格超过 35 美元的书籍。

db.books.aggregate([
  {
    $match: {
      price: { $gt: 35 }
    }
  }
]);

输出将仅包含两个符合过滤条件的书籍:

[
  {
    _id: ObjectId("..."),
    title: 'Python Deep Dive',
    author: 'John Doe',
    price: 39.99,
    pages: 450,
    categories: [ 'Programming', 'Python' ]
  },
  {
    _id: ObjectId("..."),
    title: 'Data Science Handbook',
    author: 'Alice Johnson',
    price: 49.99,
    pages: 600,
    categories: [ 'Data Science', 'Programming' ]
  }
]

$match 阶段使用标准的 MongoDB 查询语法。

  • price: { $gt: 35 } 指定了过滤条件。它选择 price 字段大于 ($gt) 35 的文档。

你还可以将阶段链接在一起以创建更复杂的管道。例如,你可以先过滤文档,然后从结果中投影自定义输出。

db.books.aggregate([
  {
    $match: {
      price: { $gt: 35 }
    }
  },
  {
    $project: {
      _id: 0,
      title: 1,
      price: 1
    }
  }
]);

此管道首先使用 $match 过滤出价格较高的书籍,然后,对于这些结果,使用 $project 仅显示 titleprice$project 中的 title: 1 语法是一种包含字段的简写方式。

最终输出既经过过滤又经过投影:

[
  { "title": "Python Deep Dive", "price": 39.99 },
  { "title": "Data Science Handbook", "price": 49.99 }
]

要退出 MongoDB shell,你可以输入 exit 或按 Ctrl+D

总结

在此实验中,你学习了 MongoDB 聚合管道的基本操作。你从插入数据开始,然后使用一系列阶段来转换数据。你练习了使用 $project 选择和重命名字段,使用 $addFields 创建新的计算字段,使用 $toUpper$concat 等格式化运算符更改数据外观,以及使用 $match 过滤文档。通过组合这些阶段,你可以在数据库内直接构建复杂的数据处理管道来分析和重塑你的数据,这是一种强大而高效的数据操作方法。