在 MongoDB 中插入数据

MongoDBBeginner
立即练习

介绍

在本实验中,你将学习将数据插入 MongoDB 数据库的基本技术。你将练习插入单个和多个文档,处理潜在的错误,并使用 MongoDB shell (mongosh) 验证数据完整性。

本实验专注于 CRUD (Create, Read, Update, Delete) 中的“创建”操作。你将从头开始构建一个简单的书店数据库,在 NoSQL 环境中获得数据管理基本任务的实践经验。到最后,你将对如何在 MongoDB 中有效添加和管理数据有扎实的理解。

插入单个文档

在第一步中,你将连接到 MongoDB 服务器,创建一个数据库和一个集合,并插入你的第一个文档。MongoDB 以灵活的、类似 JSON 的文档形式存储数据,这使得表示复杂的数据结构变得容易。

首先,使用 MongoDB Shell 连接到你的本地 MongoDB 实例。打开终端并运行以下命令:

mongosh

你将看到一个 > 提示符,表明你已进入 MongoDB Shell 并连接到数据库。

接下来,切换到一个名为 bookstore 的新数据库。如果数据库不存在,MongoDB 会在你首次存储数据时为你创建它。

use bookstore

输出将确认你已切换到 bookstore 数据库。

switched to db bookstore

现在,将单个文档插入一个名为 books 的新集合中。集合是 MongoDB 文档的集合,大致相当于关系数据库中的表。insertOne() 方法将单个文档添加到集合中。

db.books.insertOne({
  title: "The Great Gatsby",
  author: "F. Scott Fitzgerald",
  year: 1925,
  genres: ["Classic", "Fiction"],
  stock: 10
});

成功插入后,MongoDB 会返回一个文档,确认操作并提供新插入文档的唯一 _id

{
  acknowledged: true,
  insertedId: ObjectId("652f8d3e111a2b3c4d5e6f78")
}

_id 是 MongoDB 为每个文档自动生成的唯一标识符,确保集合中的每个文档都可以被唯一识别。

插入多个文档

逐个插入文档可能效率低下。要一次性添加多个文档,MongoDB 提供了 insertMany() 方法。这是一种批量插入操作,可以减少与数据库的网络往返次数。

在这一步中,你将使用一个命令向 books 集合添加另外三本书。请确保你仍在 mongosh shell 中,并且已切换到 bookstore 数据库。

使用 insertMany() 方法,传入一个文档对象数组。

db.books.insertMany([
  {
    title: "1984",
    author: "George Orwell",
    year: 1949,
    genres: ["Dystopian", "Science Fiction"],
    stock: 15
  },
  {
    title: "To Kill a Mockingbird",
    author: "Harper Lee",
    year: 1960,
    genres: ["Classic", "Fiction"],
    stock: 5
  },
  {
    title: "Pride and Prejudice",
    author: "Jane Austen",
    year: 1813,
    genres: ["Romance", "Classic"],
    stock: 12
  }
]);

输出将确认操作已被确认,并列出你插入的三个文档的 _id 值。

{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("652f8e3e111a2b3c4d5e6f79"),
    '1': ObjectId("652f8e3e111a2b3c4d5e6f7a"),
    '2': ObjectId("652f8e3e111a2b3c4d5e6f7b")
  }
}

为了验证文档是否已添加,你可以计算集合中文档的总数。

db.books.countDocuments();

结果应为 4,代表上一步中的一个文档和你刚刚添加的三个文档。

4

查询并验证已插入数据

插入数据后,下一步是检索和检查数据。这对于验证你的数据是否已正确存储以及构建从数据库读取数据的应用程序至关重要。MongoDB 为此提供了强大的 find() 方法。

要检索 books 集合中的所有文档,请在不带任何参数的情况下使用 find() 方法。

db.books.find();

此命令将列出当前集合中的所有四个文档。输出可能很长,但这是查看所有内容的好方法。

通常,你希望查找符合特定条件的文档。要查找所有在 1950 年之前出版的书籍,你可以使用带有 $lt(小于)运算符的查询过滤器。

db.books.find({ year: { $lt: 1950 } });

此查询将返回“The Great Gatsby”、“1984”和“Pride and Prejudice”的文档。

有时,你只需要文档中的特定字段,而不是整个文档。这称为投影(projection)。要仅检索“Classic”类别中所有书籍的 titleauthor,你可以将投影文档作为第二个参数添加到 find() 中。

db.books.find({ genres: "Classic" }, { title: 1, author: 1, _id: 0 });

在投影文档中,1 表示“包含此字段”,0 表示“排除此字段”。默认情况下,_id 字段始终包含在内,因此我们使用 _id: 0 显式排除它。

输出将是一个整洁的标题和作者列表:

[
  { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" },
  { "title": "To Kill a Mockingbird", "author": "Harper Lee" },
  { "title": "Pride and Prejudice", "author": "Jane Austen" }
]

使用唯一索引处理插入错误

数据完整性对任何数据库都至关重要。强制执行此操作的一种方法是防止重复条目。在这一步中,你将学习如何创建唯一索引,并观察 MongoDB 如何处理违反此约束的尝试。

让我们确保我们的集合中没有两本书具有相同的标题。为此,请在 title 字段上创建唯一索引。

db.books.createIndex({ title: 1 }, { unique: true });

输出确认了已创建索引的名称。

title_1

现在唯一索引已设置好,让我们尝试插入一个标题已存在于集合中的文档,例如“1984”。

db.books.insertOne({
  title: "1984",
  author: "George Orwell",
  year: 1949,
  genres: ["Dystopian", "Science Fiction"],
  stock: 20
});

此操作将失败。MongoDB 将抛出 MongoBulkWriteException,错误代码为 E11000,表示重复键冲突。这是预期行为,并确认我们的唯一索引正在正常工作。

MongoBulkWriteException: E11000 duplicate key error collection: bookstore.books index: title_1 dup key: { title: "1984" }

在应用程序中,你会将此类数据库操作包装在 try...catch 块中,以优雅地处理这些错误,而不是导致程序崩溃。你也可以在 mongosh shell 中模拟这一点。

try {
  db.books.insertOne({
    title: "1984",
    author: "George Orwell"
  });
} catch (e) {
  print("Error inserting document:", e.message);
}

此命令将捕获异常并打印用户友好的错误消息,演示了一种处理潜在插入失败的健壮方法。

通过 Schema Validation 强制执行数据完整性

虽然 MongoDB 以其灵活的 Schema 而闻名,但你可以使用 Schema Validation 来强制执行文档的特定结构。这可以确保集合中的所有文档都遵循一组定义的规则,从而提高数据质量和一致性。

在最后一步中,你将向 books 集合添加一个验证器(validator)。此验证器将要求每个文档都包含 titleauthoryear,并对这些字段强制执行特定的数据类型和范围。

使用 collMod(修改集合)命令添加验证器。

db.runCommand({
  collMod: "books",
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["title", "author", "year"],
      properties: {
        title: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        author: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        year: {
          bsonType: "int",
          minimum: 1000,
          maximum: 2024,
          description: "must be an integer between 1000 and 2024"
        }
      }
    }
  }
});

输出 { ok: 1 } 确认验证器已成功应用。

现在,让我们通过尝试插入一个违反规则的文档来测试验证器。此文档的 year 超出了允许的范围。

db.books.insertOne({
  title: "The Hobbit",
  author: "J.R.R. Tolkien",
  year: 999
});

插入将失败,MongoDB 将返回一条错误消息,解释文档未能通过验证。

MongoBulkWriteException: Document failed validation

这证实了你的 Schema Validation 规则已激活,并有效地保护了你的数据完整性。此强大功能将 NoSQL 数据库的灵活性与数据验证的可靠性相结合。

总结

在本实验中,你已成功掌握了向 MongoDB 集合插入数据的核心技术。你首先使用 insertOne() 插入单个文档,然后使用 insertMany() 批量操作高效地添加了多个文档。

你还练习了如何使用 find()countDocuments() 查询和验证你的数据。最重要的是,你探索了确保数据完整性的两种关键方法:创建唯一索引以防止重复,以及实施 Schema Validation 以强制执行一致的文档结构。这些技能对于使用 MongoDB 构建健壮可靠的应用程序至关重要。