Amazon DocumentDB 基础查询 #
一、查询方法概述 #
1.1 查询方法 #
text
查询方法:
├── find - 查询多个文档
├── findOne - 查询单个文档
├── countDocuments - 计数
├── distinct - 去重
└── aggregate - 聚合查询
1.2 查询结构 #
javascript
// 基本查询结构
db.collection.find(
{ /* 查询条件 */ },
{ /* 投影 */ }
)
// 完整查询链
db.users.find({ status: "active" })
.projection({ name: 1, email: 1 })
.sort({ createdAt: -1 })
.skip(0)
.limit(10)
二、find - 基本查询 #
2.1 查询所有文档 #
javascript
// 查询所有文档
db.users.find({})
// 格式化输出
db.users.find({}).pretty()
// 统计数量
db.users.find({}).count()
2.2 等值查询 #
javascript
// 单字段等值查询
db.users.find({ name: "张三" })
// 多字段等值查询(AND关系)
db.users.find({
name: "张三",
status: "active"
})
// 嵌套字段查询
db.users.find({ "address.city": "北京" })
// 数组元素查询
db.users.find({ tags: "编程" })
2.3 查询字段存在性 #
javascript
// 检查字段是否存在
db.users.find({ email: { $exists: true } })
// 检查字段不存在
db.users.find({ phone: { $exists: false } })
// 检查字段类型
db.users.find({ age: { $type: "int" } })
三、查询操作符 #
3.1 比较操作符 #
javascript
// 等于
db.products.find({ price: { $eq: 100 } })
// 不等于
db.products.find({ status: { $ne: "deleted" } })
// 大于
db.products.find({ price: { $gt: 100 } })
// 大于等于
db.products.find({ price: { $gte: 100 } })
// 小于
db.products.find({ price: { $lt: 100 } })
// 小于等于
db.products.find({ price: { $lte: 100 } })
// 在列表中
db.users.find({ role: { $in: ["admin", "editor"] } })
// 不在列表中
db.users.find({ status: { $nin: ["deleted", "banned"] } })
3.2 逻辑操作符 #
javascript
// AND操作
db.users.find({
$and: [
{ age: { $gte: 18 } },
{ status: "active" }
]
})
// 简写形式(逗号分隔)
db.users.find({
age: { $gte: 18 },
status: "active"
})
// OR操作
db.users.find({
$or: [
{ role: "admin" },
{ role: "superuser" }
]
})
// NOT操作
db.users.find({
age: { $not: { $lt: 18 } }
})
// NOR操作(都不满足)
db.users.find({
$nor: [
{ status: "deleted" },
{ status: "banned" }
]
})
3.3 元素操作符 #
javascript
// 字段存在
db.users.find({ email: { $exists: true } })
// 字段类型
db.users.find({
age: { $type: ["int", "long"] }
})
3.4 数组操作符 #
javascript
// 数组包含元素
db.users.find({ tags: "编程" })
// 数组包含所有元素
db.users.find({
tags: { $all: ["编程", "阅读"] }
})
// 数组长度
db.users.find({
tags: { $size: 3 }
})
// 数组元素匹配
db.users.find({
scores: { $elemMatch: { $gte: 80, $lt: 90 } }
})
// 嵌套数组查询
db.users.find({
education: {
$elemMatch: {
school: "清华大学",
degree: "本科"
}
}
})
3.5 正则表达式 #
javascript
// 正则匹配
db.users.find({
email: { $regex: /@example\.com$/ }
})
// 不区分大小写
db.users.find({
name: { $regex: /张/i }
})
// 使用$options
db.users.find({
name: { $regex: "张", $options: "i" }
})
// 复杂正则
db.users.find({
phone: { $regex: /^1[3-9]\d{9}$/ }
})
四、投影 #
4.1 包含字段 #
javascript
// 只返回指定字段
db.users.find(
{},
{ name: 1, email: 1 }
)
// 输出
{
"_id": ObjectId("..."),
"name": "张三",
"email": "zhangsan@example.com"
}
4.2 排除字段 #
javascript
// 排除指定字段
db.users.find(
{},
{ password: 0, createdAt: 0 }
)
4.3 嵌套字段投影 #
javascript
// 投影嵌套字段
db.users.find(
{},
{ "address.city": 1, "address.province": 1 }
)
// 投影数组元素
db.users.find(
{},
{ "education.0": 1 } // 只返回第一个教育经历
)
4.4 数组切片 #
javascript
// 返回数组前N个元素
db.posts.find(
{},
{ comments: { $slice: 5 } }
)
// 跳过前M个,返回后N个
db.posts.find(
{},
{ comments: { $slice: [10, 5] } }
)
// 返回数组最后N个元素
db.posts.find(
{},
{ comments: { $slice: -5 } }
)
4.5 元素匹配投影 #
javascript
// 返回匹配条件的数组元素
db.students.find(
{ name: "张三" },
{
grades: {
$elemMatch: { subject: "数学" }
}
}
)
4.6 条件投影 #
javascript
// 使用$条件投影
db.users.find(
{ "grades.subject": "数学" },
{ "grades.$": 1 }
)
五、排序 #
5.1 单字段排序 #
javascript
// 升序
db.users.find({}).sort({ name: 1 })
// 降序
db.users.find({}).sort({ createdAt: -1 })
5.2 多字段排序 #
javascript
// 多字段排序(先按status升序,再按createdAt降序)
db.users.find({}).sort({
status: 1,
createdAt: -1
})
5.3 嵌套字段排序 #
javascript
// 排序嵌套字段
db.users.find({}).sort({ "address.city": 1 })
5.4 排序限制 #
text
排序注意事项:
├── 排序字段应有索引
├── 大数据量排序可能超时
├── 内存排序限制100MB
└── 超过限制需要使用allowDiskUse
六、分页 #
6.1 skip/limit分页 #
javascript
// 基本分页
const page = 1;
const pageSize = 10;
db.users.find({})
.skip((page - 1) * pageSize)
.limit(pageSize)
// 第1页
db.users.find({}).skip(0).limit(10)
// 第2页
db.users.find({}).skip(10).limit(10)
// 第3页
db.users.find({}).skip(20).limit(10)
6.2 游标分页(推荐) #
javascript
// 使用最后一条记录的ID作为游标
function findWithCursor(collection, filter, lastId, limit = 10) {
const query = lastId
? { ...filter, _id: { $gt: lastId } }
: filter;
return collection.find(query)
.sort({ _id: 1 })
.limit(limit)
.toArray();
}
// 使用示例
let lastId = null;
const pageSize = 10;
// 第一页
const page1 = await findWithCursor(db.users, {}, lastId, pageSize);
lastId = page1[page1.length - 1]._id;
// 第二页
const page2 = await findWithCursor(db.users, {}, lastId, pageSize);
lastId = page2[page2.length - 1]._id;
6.3 范围分页 #
javascript
// 使用时间戳范围分页
function findByTimeRange(collection, startTime, endTime, limit = 100) {
return collection.find({
createdAt: {
$gte: startTime,
$lt: endTime
}
})
.sort({ createdAt: 1 })
.limit(limit)
.toArray();
}
6.4 分页性能对比 #
text
分页方式对比:
├── skip/limit
│ ├── 简单易用
│ ├── 深度分页性能差
│ └── 适合小数据量
│
└── 游标分页
├── 性能稳定
├── 不适合随机跳页
└── 适合大数据量
七、计数 #
7.1 countDocuments #
javascript
// 精确计数
db.users.countDocuments({})
// 条件计数
db.users.countDocuments({ status: "active" })
// 复杂条件计数
db.users.countDocuments({
createdAt: { $gte: new Date("2024-01-01") },
status: { $in: ["active", "pending"] }
})
7.2 estimatedDocumentCount #
javascript
// 估算计数(更快但不精确)
db.users.estimatedDocumentCount()
八、去重 #
8.1 基本去重 #
javascript
// 获取字段唯一值
db.users.distinct("city")
// 输出
["北京", "上海", "广州", "深圳"]
8.2 条件去重 #
javascript
// 条件去重
db.users.distinct("role", { status: "active" })
8.3 嵌套字段去重 #
javascript
// 嵌套字段去重
db.users.distinct("address.city")
九、查询优化 #
9.1 使用explain #
javascript
// 查看查询计划
db.users.find({ email: "test@example.com" }).explain()
// 查看执行统计
db.users.find({ email: "test@example.com" }).explain("executionStats")
// 关键指标
{
"executionStats": {
"totalDocsExamined": 1, // 扫描文档数
"totalKeysExamined": 1, // 扫描索引键数
"executionTimeMillis": 0, // 执行时间
"indexUsed": "email_1" // 使用的索引
}
}
9.2 索引使用检查 #
javascript
// 检查是否使用索引
const explain = db.users.find({ email: "test@example.com" }).explain();
const winningPlan = explain.queryPlanner.winningPlan;
if (winningPlan.stage === "COLLSCAN") {
print("警告:使用了全表扫描");
} else if (winningPlan.stage === "IXSCAN") {
print("使用了索引: " + winningPlan.indexName);
}
9.3 查询优化建议 #
text
优化建议:
├── 为常用查询字段创建索引
├── 使用索引覆盖查询
├── 避免使用$or(考虑$in)
├── 限制返回字段数量
├── 使用游标分页代替skip
├── 避免大数组查询
└── 使用explain分析查询
十、查询模式 #
10.1 模糊搜索 #
javascript
// 前缀匹配
db.users.find({ name: { $regex: /^张/ } })
// 后缀匹配
db.users.find({ email: { $regex: /@example\.com$/ } })
// 包含匹配
db.users.find({ name: { $regex: /三/ } })
// 多字段搜索
db.users.find({
$or: [
{ name: { $regex: /张/ } },
{ email: { $regex: /张/ } }
]
})
10.2 范围查询 #
javascript
// 日期范围
db.orders.find({
createdAt: {
$gte: new Date("2024-01-01"),
$lt: new Date("2024-02-01")
}
})
// 数值范围
db.products.find({
price: {
$gte: 100,
$lte: 500
}
})
10.3 空值处理 #
javascript
// 查找null或不存在
db.users.find({ phone: null })
// 只查找null值
db.users.find({ phone: { $type: "null" } })
// 查找不存在或null
db.users.find({
$or: [
{ phone: null },
{ phone: { $exists: false } }
]
})
十一、实际应用示例 #
11.1 用户搜索 #
javascript
// 综合用户搜索
function searchUsers(options) {
const query = {};
// 关键词搜索
if (options.keyword) {
query.$or = [
{ name: { $regex: options.keyword, $options: "i" } },
{ email: { $regex: options.keyword, $options: "i" } }
];
}
// 状态筛选
if (options.status) {
query.status = options.status;
}
// 角色筛选
if (options.role) {
query.role = options.role;
}
// 日期范围
if (options.startDate || options.endDate) {
query.createdAt = {};
if (options.startDate) {
query.createdAt.$gte = new Date(options.startDate);
}
if (options.endDate) {
query.createdAt.$lte = new Date(options.endDate);
}
}
return db.users.find(query)
.sort({ createdAt: -1 })
.skip((options.page - 1) * options.pageSize)
.limit(options.pageSize)
.toArray();
}
11.2 产品筛选 #
javascript
// 产品筛选查询
function filterProducts(filters) {
const query = {};
// 分类
if (filters.category) {
query.category = filters.category;
}
// 价格范围
if (filters.minPrice || filters.maxPrice) {
query.price = {};
if (filters.minPrice) query.price.$gte = filters.minPrice;
if (filters.maxPrice) query.price.$lte = filters.maxPrice;
}
// 标签
if (filters.tags && filters.tags.length > 0) {
query.tags = { $all: filters.tags };
}
// 库存
if (filters.inStock) {
query.stock = { $gt: 0 };
}
return db.products.find(query)
.sort({ sales: -1, createdAt: -1 })
.toArray();
}
十二、总结 #
12.1 查询操作符速查 #
| 操作符 | 用途 |
|---|---|
| $eq, $ne | 等于/不等于 |
| $gt, $gte, $lt, $lte | 比较 |
| $in, $nin | 包含/不包含 |
| $and, $or, $not | 逻辑 |
| $exists | 字段存在 |
| $regex | 正则匹配 |
| $all, $elemMatch, $size | 数组 |
12.2 最佳实践总结 #
text
查询最佳实践:
├── 使用索引优化查询
├── 使用explain分析性能
├── 合理使用投影减少数据传输
├── 使用游标分页处理大数据
├── 避免深度嵌套查询
└── 监控慢查询
下一步,让我们学习高级查询!
最后更新:2026-03-27