08-27-周三_17-09-29
This commit is contained in:
167
数据库/MongoDB_2025/MongoDB进阶查询.md
Normal file
167
数据库/MongoDB_2025/MongoDB进阶查询.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# 查询进阶
|
||||
|
||||
本章节将带大家深入了解 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`。
|
||||
|
||||
```javascript
|
||||
// 只返回 name 和 price 字段,_id 默认返回
|
||||
db.products.find({}, { name: 1, price: 1 })
|
||||
```
|
||||
|
||||
- **排除字段**: 将不需要返回的字段设置为 `0`。
|
||||
|
||||
```javascript
|
||||
// 返回除 description 之外的所有字段
|
||||
db.products.find({}, { description: 0 })
|
||||
```
|
||||
|
||||
- **排除 `_id` 字段**:
|
||||
|
||||
```javascript
|
||||
db.products.find({}, { name: 1, price: 1, _id: 0 })
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 排序(Sorting)
|
||||
|
||||
使用 `sort()` 方法对查询结果进行排序。
|
||||
|
||||
- **升序 (Ascending)**: 将字段值设置为 `1`。
|
||||
- **降序 (Descending)**: 将字段值设置为 `-1`。
|
||||
|
||||
```javascript
|
||||
// 按价格升序排序
|
||||
db.products.find().sort({ price: 1 })
|
||||
|
||||
// 按库存降序、名称升序排序
|
||||
db.products.find().sort({ stock: -1, name: 1 })
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 分页(Pagination)
|
||||
|
||||
通过组合使用 `limit()` 和 `skip()` 方法,可以实现对查询结果的分页。
|
||||
|
||||
- **`limit()`**: 限制返回的文档数量。
|
||||
- **`skip()`**: 跳过指定数量的文档。
|
||||
|
||||
```javascript
|
||||
// 获取第 2 页数据,每页 10 条 (跳过前 10 条,返回 10 条)
|
||||
db.products.find().skip(10).limit(10)
|
||||
```
|
||||
|
||||
**注意**: 对于大数据量的集合,使用 `skip()` 进行深度分页可能会有性能问题。在这种情况下,建议使用基于范围的查询(如使用 `_id` 或时间戳)。
|
||||
|
||||
---
|
||||
|
||||
## 正则表达式查询
|
||||
|
||||
MongoDB 支持使用 PCRE (Perl Compatible Regular Expression) 语法的正则表达式进行字符串匹配。
|
||||
|
||||
```javascript
|
||||
// 查询 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' 的学生。
|
||||
|
||||
### 实践细节和结果验证
|
||||
|
||||
```javascript
|
||||
// 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/ });
|
||||
```
|
Reference in New Issue
Block a user