Files
Cloud-book/数据库/MongoDB_2025/MongoDB进阶查询.md
2025-08-27 17:10:05 +08:00

5.6 KiB
Raw Permalink Blame History

查询进阶

本章节将带大家深入了解 MongoDB 强大的查询功能,包括使用查询操作符、投影、排序、分页以及正则表达式查询,可以更精确、更高效地从数据库中检索数据。


查询操作符

查询操作符是 MongoDB 查询语言的核心,它们可以帮助大家构建更复杂的查询条件。

比较操作符

操作符 描述 示例
$eq 等于 (Equal) db.inventory.find({ qty: { $eq: 20 } })
$ne 不等于 (Not Equal) db.inventory.find({ qty: { $ne: 20 } })
$gt 大于 (Greater Than) db.inventory.find({ qty: { $gt: 20 } })
$gte 大于等于 (Greater Than or Equal) db.inventory.find({ qty: { $gte: 20 } })
$lt 小于 (Less Than) db.inventory.find({ qty: { $lt: 20 } })
$lte 小于等于 (Less Than or Equal) db.inventory.find({ qty: { $lte: 20 } })
$in 在指定数组内 (In) db.inventory.find({ qty: { $in: [5, 15] } })
$nin 不在指定数组内 (Not In) db.inventory.find({ qty: { $nin: [5, 15] } })

逻辑操作符

操作符 描述 示例
$and 逻辑与,连接多个查询条件 db.inventory.find({ $and: [{ qty: { $lt: 20 } }, { price: { $gt: 10 } }] })
$or 逻辑或,满足任一查询条件 db.inventory.find({ $or: [{ qty: { $lt: 20 } }, { price: { $gt: 50 } }] })
$nor 逻辑非或,所有条件都不满足 db.inventory.find({ $nor: [{ price: 1.99 }, { sale: true }] })
$not 逻辑非,对指定条件取反 db.inventory.find({ price: { $not: { $gt: 1.99 } } })

元素操作符

操作符 描述 示例
$exists 判断字段是否存在 db.inventory.find({ qty: { $exists: true } })
$type 判断字段的数据类型 db.inventory.find({ qty: { $type: "number" } })

数组操作符

操作符 描述 示例
$all 匹配包含所有指定元素的数组 db.inventory.find({ tags: { $all: ["appliance", "school"] } })
$elemMatch 数组中至少有一个元素满足所有指定条件 db.inventory.find({ results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } })
$size 匹配指定大小的数组 db.inventory.find({ tags: { $size: 3 } })

投影Projection

投影用于限制查询结果中返回的字段,可以减少网络传输的数据量,并保护敏感字段。

  • 包含字段: 在 find() 方法的第二个参数中,将需要返回的字段设置为 1

    // 只返回 name 和 price 字段_id 默认返回
    db.products.find({}, { name: 1, price: 1 })
    
  • 排除字段: 将不需要返回的字段设置为 0

    // 返回除 description 之外的所有字段
    db.products.find({}, { description: 0 })
    
  • 排除 _id 字段:

    db.products.find({}, { name: 1, price: 1, _id: 0 })
    

排序Sorting

使用 sort() 方法对查询结果进行排序。

  • 升序 (Ascending): 将字段值设置为 1
  • 降序 (Descending): 将字段值设置为 -1
// 按价格升序排序
db.products.find().sort({ price: 1 })

// 按库存降序、名称升序排序
db.products.find().sort({ stock: -1, name: 1 })

分页Pagination

通过组合使用 limit()skip() 方法,可以实现对查询结果的分页。

  • limit(): 限制返回的文档数量。
  • skip(): 跳过指定数量的文档。
// 获取第 2 页数据,每页 10 条 (跳过前 10 条,返回 10 条)
db.products.find().skip(10).limit(10)

注意: 对于大数据量的集合,使用 skip() 进行深度分页可能会有性能问题。在这种情况下,建议使用基于范围的查询(如使用 _id 或时间戳)。


正则表达式查询

MongoDB 支持使用 PCRE (Perl Compatible Regular Expression) 语法的正则表达式进行字符串匹配。

// 查询 name 字段以 'A' 开头的文档 (不区分大小写)
db.products.find({ name: { $regex: '^A', $options: 'i' } })

// 查询 name 字段包含 'pro' 的文档
db.products.find({ name: /pro/ })

实践操作

假设有一个 students 集合,包含以下字段:name, age, major, gpa, courses (数组)。

需求描述

  1. 查询练习:

    • 查询所有主修 'Computer Science' 且 GPA 大于 3.5 的学生。
    • 查询年龄在 20 到 22 岁之间(含)的学生。
    • 查询选修了 'Database Systems' 和 'Data Structures' 两门课的学生。
  2. 投影练习:

    • 只返回学生的姓名和专业。
  3. 排序和分页练习:

    • 按 GPA 降序显示前 10 名学生。
  4. 正则表达式练习:

    • 查询所有姓 'Li' 的学生。

实践细节和结果验证

// 1. 查询练习
// 查询所有主修 'Computer Science' 且 GPA 大于 3.5 的学生
db.students.find({ major: 'Computer Science', gpa: { $gt: 3.5 } });

// 查询年龄在 20 到 22 岁之间(含)的学生
db.students.find({ age: { $gte: 20, $lte: 22 } });

// 查询选修了 'Database Systems' 和 'Data Structures' 两门课的学生
db.students.find({ courses: { $all: ['Database Systems', 'Data Structures'] } });

// 2. 投影练习
// 只返回学生的姓名和专业
db.students.find({}, { name: 1, major: 1, _id: 0 });

// 3. 排序和分页练习
// 按 GPA 降序显示前 10 名学生
db.students.find().sort({ gpa: -1 }).limit(10);

// 4. 正则表达式练习
// 查询所有姓 'Li' 的学生
db.students.find({ name: /^Li/ });