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

