MongoDB基础查询 #

一、查询概述 #

1.1 查询方法 #

MongoDB提供多种查询方法:

方法 说明
find 查询多个文档
findOne 查询单个文档
countDocuments 统计文档数量
distinct 去重查询

1.2 查询结构 #

javascript
// 基本查询结构
db.collection.find(
    { query },      // 查询条件
    { projection }  // 投影
).sort({ sort }).limit(limit).skip(skip)

二、find方法 #

2.1 基本查询 #

javascript
// 查询所有文档
db.users.find()

// 格式化输出
db.users.find().pretty()

// 查询单个文档
db.users.findOne()

2.2 条件查询 #

javascript
// 等值查询
db.users.find({ name: "John" })

// 多条件查询(AND)
db.users.find({ name: "John", age: 25 })

// 嵌套字段查询
db.users.find({ "address.city": "Beijing" })

// 数组元素查询
db.users.find({ hobbies: "reading" })

2.3 查询结果处理 #

javascript
// 限制结果数量
db.users.find().limit(10)

// 跳过结果
db.users.find().skip(10)

// 排序
db.users.find().sort({ age: -1 })  // 降序
db.users.find().sort({ age: 1 })   // 升序

// 组合使用
db.users.find()
    .sort({ age: -1 })
    .skip(10)
    .limit(10)

三、查询操作符 #

3.1 比较操作符 #

$eq - 等于

javascript
// 等于
db.users.find({ age: { $eq: 25 } })
// 等同于
db.users.find({ age: 25 })

$ne - 不等于

javascript
// 不等于
db.users.find({ age: { $ne: 25 } })

$gt - 大于

javascript
// 大于
db.users.find({ age: { $gt: 20 } })

$gte - 大于等于

javascript
// 大于等于
db.users.find({ age: { $gte: 20 } })

$lt - 小于

javascript
// 小于
db.users.find({ age: { $lt: 30 } })

$lte - 小于等于

javascript
// 小于等于
db.users.find({ age: { $lte: 30 } })

$in - 在列表中

javascript
// 在列表中
db.users.find({ age: { $in: [20, 25, 30] } })

// 多个值
db.users.find({ city: { $in: ["Beijing", "Shanghai"] } })

$nin - 不在列表中

javascript
// 不在列表中
db.users.find({ age: { $nin: [20, 25, 30] } })

组合比较

javascript
// 范围查询
db.users.find({ age: { $gt: 20, $lt: 30 } })

// 多条件组合
db.users.find({
    age: { $gte: 20, $lte: 30 },
    city: { $in: ["Beijing", "Shanghai"] }
})

3.2 逻辑操作符 #

$and - 逻辑与

javascript
// 逻辑与
db.users.find({
    $and: [
        { age: { $gt: 20 } },
        { city: "Beijing" }
    ]
})

// 简化写法
db.users.find({
    age: { $gt: 20 },
    city: "Beijing"
})

$or - 逻辑或

javascript
// 逻辑或
db.users.find({
    $or: [
        { age: { $lt: 20 } },
        { age: { $gt: 60 } }
    ]
})

// 多条件或
db.users.find({
    $or: [
        { city: "Beijing" },
        { city: "Shanghai" }
    ]
})

$not - 逻辑非

javascript
// 逻辑非
db.users.find({
    age: { $not: { $gt: 30 } }
})
// 等同于 age <= 30

$nor - 逻辑或非

javascript
// 逻辑或非
db.users.find({
    $nor: [
        { age: { $lt: 20 } },
        { city: "Beijing" }
    ]
})
// 既不满足age < 20,也不满足city = Beijing

组合逻辑

javascript
// 复杂逻辑组合
db.users.find({
    $and: [
        {
            $or: [
                { status: "active" },
                { status: "pending" }
            ]
        },
        { age: { $gte: 18 } }
    ]
})

3.3 元素操作符 #

$exists - 字段存在

javascript
// 字段存在
db.users.find({ email: { $exists: true } })

// 字段不存在
db.users.find({ email: { $exists: false } })

$type - 类型检查

javascript
// 类型检查
db.users.find({ age: { $type: "number" } })

// 多种类型
db.users.find({ age: { $type: ["number", "string"] } })

// 使用类型编号
db.users.find({ age: { $type: 16 } })  // 32位整数

3.4 数组操作符 #

$all - 包含所有元素

javascript
// 包含所有元素
db.users.find({ hobbies: { $all: ["reading", "swimming"] } })

$size - 数组长度

javascript
// 数组长度
db.users.find({ hobbies: { $size: 3 } })

$elemMatch - 元素匹配

javascript
// 元素匹配
db.users.find({
    scores: {
        $elemMatch: {
            subject: "math",
            score: { $gt: 80 }
        }
    }
})

// 数组嵌套对象查询
db.orders.find({
    items: {
        $elemMatch: {
            productId: ObjectId("..."),
            quantity: { $gt: 1 }
        }
    }
})

3.5 正则表达式 #

javascript
// 正则表达式查询
db.users.find({ name: /^John/ })

// $regex操作符
db.users.find({
    name: { $regex: /^john/i }
})

// 复杂正则
db.users.find({
    email: {
        $regex: /^[a-zA-Z0-9._%+-]+@example\.com$/,
        $options: "i"
    }
})

四、投影 #

4.1 基本投影 #

javascript
// 包含字段
db.users.find({}, { name: 1, email: 1 })

// 排除字段
db.users.find({}, { password: 0, _id: 0 })

// 混合使用(不能同时使用包含和排除)
db.users.find({}, { name: 1, email: 1, _id: 0 })

4.2 嵌套字段投影 #

javascript
// 嵌套字段投影
db.users.find({}, { "address.city": 1, "address.street": 1 })

// 数组元素投影
db.users.find({}, { "hobbies.$": 1 })

// 数组元素过滤
db.users.find(
    { hobbies: "reading" },
    { "hobbies.$": 1 }
)

4.3 数组投影 #

javascript
// 数组切片
db.users.find({}, { hobbies: { $slice: 3 } })
db.users.find({}, { hobbies: { $slice: -3 } })
db.users.find({}, { hobbies: { $slice: [2, 3] } })

// 数组元素匹配
db.users.find(
    {},
    { scores: { $elemMatch: { score: { $gt: 80 } } } }
)

4.4 聚合投影 #

javascript
// 使用聚合表达式
db.users.find({}, {
    name: 1,
    email: 1,
    age: { $add: ["$age", 1] },
    fullName: { $concat: ["$firstName", " ", "$lastName"] }
})

五、排序 #

5.1 基本排序 #

javascript
// 升序
db.users.find().sort({ age: 1 })

// 降序
db.users.find().sort({ age: -1 })

// 多字段排序
db.users.find().sort({ city: 1, age: -1 })

5.2 嵌套字段排序 #

javascript
// 嵌套字段排序
db.users.find().sort({ "address.city": 1 })

5.3 排序规则 #

javascript
// 排序规则
db.users.find().sort({ name: 1 }).collation({
    locale: "zh",
    strength: 2
})

六、分页 #

6.1 skip/limit分页 #

javascript
// 基本分页
const page = 1
const pageSize = 10
db.users.find()
    .skip((page - 1) * pageSize)
    .limit(pageSize)

// 排序分页
db.users.find()
    .sort({ createdAt: -1 })
    .skip((page - 1) * pageSize)
    .limit(pageSize)

6.2 游标分页 #

javascript
// 游标分页(更高效)
const lastId = ObjectId("...")
db.users.find({ _id: { $gt: lastId } })
    .sort({ _id: 1 })
    .limit(10)

// 复合游标分页
const lastCreatedAt = ISODate("...")
const lastId = ObjectId("...")
db.users.find({
    $or: [
        { createdAt: { $lt: lastCreatedAt } },
        { createdAt: lastCreatedAt, _id: { $gt: lastId } }
    ]
})
    .sort({ createdAt: -1, _id: 1 })
    .limit(10)

七、统计 #

7.1 countDocuments #

javascript
// 统计文档数量
db.users.countDocuments({})

// 条件统计
db.users.countDocuments({ age: { $gt: 20 } })

// 复杂条件统计
db.users.countDocuments({
    city: "Beijing",
    age: { $gte: 18, $lte: 60 }
})

7.2 estimatedDocumentCount #

javascript
// 估算文档数量(更快)
db.users.estimatedDocumentCount()

7.3 distinct #

javascript
// 去重查询
db.users.distinct("city")

// 条件去重
db.users.distinct("city", { age: { $gt: 20 } })

// 嵌套字段去重
db.users.distinct("address.city")

八、查询优化 #

8.1 使用索引 #

javascript
// 创建索引
db.users.createIndex({ name: 1 })

// 使用索引查询
db.users.find({ name: "John" })

// 强制使用索引
db.users.find({ name: "John" }).hint({ name: 1 })

// 查看执行计划
db.users.find({ name: "John" }).explain("executionStats")

8.2 查询分析 #

javascript
// 查看执行计划
db.users.find({ age: { $gt: 20 } }).explain()

// 详细执行计划
db.users.find({ age: { $gt: 20 } }).explain("executionStats")

// 所有执行计划
db.users.find({ age: { $gt: 20 } }).explain("allPlansExecution")

8.3 查询优化建议 #

javascript
// 1. 使用投影减少返回字段
db.users.find({}, { name: 1, email: 1 })

// 2. 使用limit限制结果
db.users.find().limit(100)

// 3. 避免使用$where
// 不推荐
db.users.find({ $where: "this.age > 20" })
// 推荐
db.users.find({ age: { $gt: 20 } })

// 4. 使用索引
db.users.createIndex({ age: 1 })
db.users.find({ age: { $gt: 20 } })

九、查询游标 #

9.1 游标方法 #

javascript
// 遍历游标
const cursor = db.users.find()
while (cursor.hasNext()) {
    printjson(cursor.next())
}

// 使用forEach
db.users.find().forEach(user => {
    print(user.name)
})

// 转换为数组
const users = db.users.find().toArray()

// 获取单个文档
const user = db.users.find().next()

9.2 游标选项 #

javascript
// 设置批量大小
db.users.find().batchSize(100)

// 设置超时
db.users.find().maxTimeMS(5000)

// 不超时
db.users.find().noCursorTimeout()

十、最佳实践 #

10.1 查询设计 #

javascript
// 推荐:使用索引
db.users.createIndex({ email: 1 })
db.users.find({ email: "john@example.com" })

// 不推荐:全表扫描
db.users.find({ email: { $regex: /example\.com$/ } })

10.2 投影使用 #

javascript
// 推荐:只返回需要的字段
db.users.find({}, { name: 1, email: 1, _id: 0 })

// 不推荐:返回所有字段
db.users.find({})

10.3 分页优化 #

javascript
// 推荐:游标分页
db.users.find({ _id: { $gt: lastId } }).limit(10)

// 不推荐:skip分页(大量数据时性能差)
db.users.find().skip(10000).limit(10)

十一、总结 #

查询操作速查表:

方法 说明 示例
find 查询多个文档 db.coll.find({…})
findOne 查询单个文档 db.coll.findOne({…})
countDocuments 统计文档数 db.coll.countDocuments({…})
distinct 去重查询 db.coll.distinct(“field”)

常用操作符:

操作符 说明
$eq, $ne 等于、不等于
$gt, $gte, $lt, $lte 比较操作
$in, $nin 在列表中、不在列表中
$and, $or, $not 逻辑操作
$exists, $type 元素操作
$all, $size, $elemMatch 数组操作
$regex 正则表达式

下一步,让我们学习高级查询!

最后更新:2026-03-27