过滤 MongoDB 集合

MongoDBBeginner
立即练习

介绍

在本实验中,你将学习如何使用各种查询技术有效地过滤 MongoDB 集合。本实验涵盖了应用多个条件、使用比较运算符、使用正则表达式进行匹配、检查字段是否存在以及查找 null 值。这些技能对于在 MongoDB 中进行精确的数据检索至关重要。分步说明提供了实践示例,帮助你掌握 MongoDB 查询的基础知识。

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

应用多个条件

在本步骤中,你将学习如何应用多个条件来过滤 MongoDB 集合中的文档。通过组合多个标准,可以实现更精确的查询。

首先,打开你的终端并启动 MongoDB Shell。这个交互式 shell 是你执行所有数据库命令的地方。

mongosh

进入 mongosh shell 后,你将看到一个 > 提示符。接下来,我们将切换到一个名为 school_database 的新数据库,并创建一个包含一些示例数据的 students 集合。

use school_database
db.students.insertMany([
  { name: "Alice", age: 22, grade: "A", major: "Computer Science" },
  { name: "Bob", age: 20, grade: "B", major: "Mathematics" },
  { name: "Charlie", age: 25, grade: "A", major: "Physics" },
  { name: "David", age: 19, grade: "C", major: "Computer Science" }
]);

此命令将向 students 集合插入四个文档。现在,让我们查找满足多个条件的学生。我们将使用 $and 操作符来查找年龄大于或等于 20 岁 并且 成绩为 "A" 的学生。

db.students.find({
  $and: [{ age: { $gte: 20 } }, { grade: "A" }]
});

此查询使用了 $gte(大于或等于)和 $and,以确保同时满足这两个条件。输出将显示 Alice 和 Charlie:

[
  {
    _id: ObjectId("..."),
    name: 'Alice',
    age: 22,
    grade: 'A',
    major: 'Computer Science'
  },
  {
    _id: ObjectId("..."),
    name: 'Charlie',
    age: 25,
    grade: 'A',
    major: 'Physics'
  }
]

接下来,我们将使用 $or 操作符来查找至少满足多个条件中任一条件的文档。此查询将查找专业为 "Computer Science" 年龄小于 21 岁的学生。

db.students.find({
  $or: [{ major: "Computer Science" }, { age: { $lt: 21 } }]
});

此查询使用了 $lt(小于)。结果将包括 Alice 和 David(计算机科学专业)以及 Bob 和 David(年龄小于 21 岁)。由于 David 同时满足两个条件,他只出现一次。

[
  {
    _id: ObjectId("..."),
    name: 'Alice',
    age: 22,
    grade: 'A',
    major: 'Computer Science'
  },
  {
    _id: ObjectId("..."),
    name: 'Bob',
    age: 20,
    grade: 'B',
    major: 'Mathematics'
  },
  {
    _id: ObjectId("..."),
    name: 'David',
    age: 19,
    grade: 'C',
    major: 'Computer Science'
  }
]

在下一步中,你将探索更多的比较操作符。现在,你可以继续留在 mongosh shell 中。

使用比较操作符

在本步骤中,你将使用 MongoDB 的比较操作符来构建更复杂的查询。这些操作符允许你根据值比较来过滤数据。

你应该仍然处于上一步的 mongosh shell 中。首先,让我们清空现有集合并插入带有 credits 字段的新数据以供使用。

db.students.drop();
db.students.insertMany([
  {
    name: "Alice",
    age: 22,
    grade: "A",
    major: "Computer Science",
    credits: 45
  },
  { name: "Bob", age: 20, grade: "B", major: "Mathematics", credits: 35 },
  { name: "Charlie", age: 25, grade: "A", major: "Physics", credits: 50 },
  { name: "David", age: 19, grade: "C", major: "Computer Science", credits: 25 }
]);

现在,让我们使用 "大于" ($gt) 和 "小于" ($lt) 操作符来查找年龄大于 20 岁但小于 25 岁的学生。

db.students.find({ age: { $gt: 20, $lt: 25 } });

此查询将只返回 Alice 的文档,因为她 22 岁。

接下来,使用 "大于或等于" ($gte) 和 "小于或等于" ($lte) 来查找 credits 在 40 到 50 之间(包含边界)的学生。

db.students.find({ credits: { $gte: 40, $lte: 50 } });

此查询将返回 Alice(45 credits)和 Charlie(50 credits)。

最后,让我们使用 "不等于" ($ne) 操作符来查找所有 grade 不是 "C" 的学生。

db.students.find({ grade: { $ne: "C" } });

这将返回 Alice、Bob 和 Charlie,排除 grade 为 "C" 的 David。这些操作符是创建详细且特定查询的基础。

使用正则表达式匹配

正则表达式(regex)提供了一种灵活的方式来执行强大的文本搜索。在本步骤中,你将学习如何在 MongoDB 查询中使用正则表达式。

首先,让我们为本步骤准备数据。清空集合并插入包含更多详细字符串字段的新文档。

db.students.drop();
db.students.insertMany([
  {
    name: "Alice Johnson",
    age: 22,
    major: "Computer Science",
    email: "alice.j@example.com"
  },
  {
    name: "Bob Smith",
    age: 20,
    major: "Mathematics",
    email: "bob.smith@university.edu"
  },
  {
    name: "Charlie Brown",
    age: 25,
    major: "Physics",
    email: "charlie.brown@school.org"
  },
  {
    name: "David Lee",
    age: 19,
    major: "Computer Engineering",
    email: "david.lee@tech.net"
  }
]);

要查找所有名字以 "Alice" 开头的学生,你可以使用带有 ^ 锚点的 $regex 操作符。

db.students.find({ name: { $regex: "^Alice" } });

此查询将返回 "Alice Johnson" 的文档。^ 字符表示字符串的开头。

要查找来自特定域(如 example.com)的电子邮件地址的学生,请使用 $ 锚点匹配字符串的结尾。

db.students.find({ email: { $regex: "@example.com$" } });

这将找到 "Alice Johnson",因为她的电子邮件以 @example.com 结尾。

你还可以执行不区分大小写的搜索。以下查询通过使用 i 选项,查找名字中包含 "smith" 的任何学生,而不考虑大小写。

db.students.find({ name: { $regex: "smith", $options: "i" } });

此查询将匹配 "Bob Smith"。

最后,要查找包含 "Computer" 一词的任何专业,你可以使用简单的正则表达式模式,而无需任何锚点。

db.students.find({ major: { $regex: "Computer" } });

这将返回 "Alice Johnson"(Computer Science)和 "David Lee"(Computer Engineering)。

检查字段是否存在

有时,集合中的文档结构不同。本步骤将教你如何根据特定字段是否存在来查询文档。

让我们开始插入一组新文档,其中一些字段缺失。

db.students.drop();
db.students.insertMany([
  { name: "Alice", age: 22, major: "Computer Science", scholarship: 1000 },
  { name: "Bob", age: 20, major: "Mathematics" },
  { name: "Charlie", age: 25, major: "Physics", internship: "Research Lab" },
  { name: "David", age: 19, contact: { phone: "555-1234" } }
]);

要查找所有具有 scholarship 字段的学生,请使用值为 true$exists 操作符。

db.students.find({ scholarship: { $exists: true } });

此查询将只返回 Alice 的文档,因为她是唯一拥有 scholarship 字段的学生。

相反,要查找没有 internship 字段的学生,请将 $exists 设置为 false

db.students.find({ internship: { $exists: false } });

这将返回 Alice、Bob 和 David 的文档,因为他们都没有 internship 字段。

$exists 操作符也适用于嵌套字段。要查找拥有包含 phone 字段的 contact 对象的学生,你可以使用点表示法(dot notation)。

db.students.find({ "contact.phone": { $exists: true } });

此查询专门查找 contact 对象内的 phone 字段,并将返回 David 的文档。

查找 Null 值

在本步骤的最后,你将学习如何查询包含 null 值的文档。null 值代表有意缺失一个值。

首先,我们来设置一个包含 null 值和缺失字段的文档集合。

db.students.drop();
db.students.insertMany([
  { name: "Alice", age: 22, email: null },
  { name: "Bob", age: 20, major: "Mathematics" },
  { name: "Charlie", age: null, major: "Physics" },
  { name: "David", contact: { email: null } }
]);

要查找字段具有 null 值的文档,你可以直接查询 null。以下查询会查找 email 字段为 nullemail 字段不存在的所有文档。

db.students.find({ email: null });

此查询将返回所有四个文档:Alice(email 显式为 null),Bob(email 字段缺失),Charlie(email 字段缺失),以及 David(email 字段缺失)。

要仅查找字段显式设置为 null 的文档,你必须将 null 检查与 $exists 检查结合起来。

db.students.find({ email: { $type: "null" } });

或者,你也可以使用 $type 操作符。null 的 BSON 类型是 10。此查询将仅返回 Alice 的文档。

db.students.find({ email: { $type: 10 } });

你也可以查询嵌套文档中的 null 值。以下查询会查找 contact 对象中 email 字段为 nullcontact 字段不存在的文档。

db.students.find({ "contact.email": null });

这将返回所有四个文档:Alice、Bob 和 Charlie(contact 字段缺失),以及 David(contact.email 显式为 null)。理解如何查询 null 对于处理不完整或稀疏的数据至关重要。

完成后,你可以通过输入 exit 或按 Ctrl+D 来退出 mongosh shell。

总结

在本实验中,你学习了 MongoDB 中过滤集合的几种基本技术。你练习了使用 $and$or 操作符应用多个条件,这使得创建复杂且精确的查询成为可能。你还探索了一系列比较操作符,如 $gt$lt$ne,用于优化搜索条件。此外,你还获得了使用正则表达式匹配文本、使用 $exists 检查字段是否存在以及查询 null 值的经验。这些技能为你有效地检索和操作 MongoDB 数据奠定了坚实的基础。