MongoDB查询深入理解:复杂查询与优化技巧
写在前面MongoDB的查询功能非常强大掌握好查询语法是使用MongoDB的关键。本篇将深入讲解MongoDB的各种查询技巧包括条件查询、逻辑运算、数组查询、嵌套文档查询等高级用法。文章目录一、查询操作符详解1.1 比较操作符1.2 数组操作符二、逻辑操作符2.1a n d 、 and、and、or、n o t 、 not、not、nor2.2 组合复杂查询三、嵌套文档查询3.1 嵌套文档结构3.2 点号查询嵌套字段四、投影Projection详解4.1 基本投影4.2 数组投影4.3 条件投影五、排序与分页5.1 排序5.2 分页实现5.3 实战带过滤的分页查询六、正则表达式查询6.1 基本正则查询6.2 正则选项七、聚合管道查询7.1 $match - 过滤7.2 $group - 分组统计八、查询性能优化8.1 使用explain分析查询8.2 优化建议九、实战案例电商商品筛选9.1 多维度筛选9.2 复杂搜索9.3 聚合统计十、总结一、查询操作符详解1.1 比较操作符// 准备测试数据db.products.insertMany([{name:iPhone 15,price:5999,category:手机,stock:100},{name:MacBook Pro,price:14999,category:电脑,stock:50},{name:iPad,price:2999,category:平板,stock:200},{name:AirPods,price:999,category:耳机,stock:500},{name:小米13,price:3999,category:手机,stock:150}])// $eq - 等于默认可以省略db.products.find({price:5999})db.products.find({price:{$eq:5999}})// $ne - 不等于db.products.find({category:{$ne:手机}})// $gt - 大于db.products.find({price:{$gt:5000}})// $gte - 大于等于db.products.find({price:{$gte:5000}})// $lt - 小于db.products.find({price:{$lt:3000}})// $lte - 小于等于db.products.find({price:{$lte:3000}})// 组合查询价格在3000-10000之间db.products.find({price:{$gte:3000,$lte:10000}})1.2 数组操作符// 准备带数组的数据db.students.insertMany([{name:张三,subjects:[数学,英语,物理]},{name:李四,subjects:[数学,化学,生物]},{name:王五,subjects:[英语,历史,地理]},{name:赵六,subjects:[数学,英语,化学]}])// $all - 数组包含所有指定元素db.students.find({subjects:{$all:[数学,英语]}})// 结果张三、赵六都包含数学和英语// $in - 数组包含任一指定元素db.students.find({subjects:{$in:[数学,历史]}})// 结果所有包含数学或历史的学生// $nin - 数组不包含任一指定元素db.students.find({subjects:{$nin:[数学]}})// 结果王五// $size - 数组长度为指定值db.students.find({subjects:{$size:3}})// $elemMatch - 数组中至少有一个元素匹配db.scores.insertMany([{name:张三,scores:[85,92,78]},{name:李四,scores:[90,88,95]},{name:王五,scores:[60,75,70]}])// 至少有 一门成绩大于90db.scores.find({scores:{$elemMatch:{$gt:90}}})// 结果李四// 多条件成绩在80-90之间db.scores.find({scores:{$elemMatch:{$gte:80,$lte:90}}})二、逻辑操作符2.1a n d 、 and、and、or、n o t 、 not、not、nor// $and - 所有条件都满足默认写法db.products.find({price:{$gt:3000},category:手机})// 显式写法效果相同db.products.find({$and:[{price:{$gt:3000}},{category:手机}]})// $or - 任一条件满足db.products.find({$or:[{category:手机},{category:电脑}]})// 复杂组合价格大于5000或者是手机类别db.products.find({$or:[{price:{$gt:5000}},{category:手机}]})// $not - 取反db.products.find({price:{$not:{$gt:5000}}})// 价格不大于5000即 5000// $nor - 所有条件都不满足db.products.find({$nor:[{category:手机},{price:{$gt:10000}}]})// 既不是手机类别价格也不超过100002.2 组合复杂查询// 查询示例价格在3000-10000的手机或电脑db.products.find({$and:[{price:{$gte:3000,$lte:10000}},{category:{$in:[手机,电脑]}}]})// 查询库存充足100的低价5000产品db.products.find({$or:[{stock:{$gt:100},price:{$lt:5000}},{price:{$lt:1000}}]})三、嵌套文档查询3.1 嵌套文档结构// 插入订单数据嵌套文档db.orders.insertMany([{orderId:O001,customer:{name:张三,phone:13800138000,address:{city:北京,district:朝阳区,street:建国路88号}},items:[{product:iPhone 15,quantity:1,price:5999},{product:AirPods,quantity:2,price:1998}],total:7997,status:completed},{orderId:O002,customer:{name:李四,phone:13900139000,address:{city:上海,district:浦东新区,street:世纪大道100号}},items:[{product:MacBook Pro,quantity:1,price:14999}],total:14999,status:pending}])3.2 点号查询嵌套字段// 查询北京的用户订单db.orders.find({customer.address.city:北京})// 查询朝阳区且已完成订单db.orders.find({customer.address.district:朝阳区,status:completed})// 查询订单中包含iPhone的订单db.orders.find({items.product:iPhone 15})// 嵌套数组中精确匹配db.orders.find({items:{$elemMatch:{product:iPhone 15,quantity:1}}})四、投影Projection详解4.1 基本投影// 只返回name和price字段db.products.find({},{name:1,price:1})// 排除_id字段db.products.find({},{name:1,price:1,_id:0})// 排除某些字段db.products.find({},{stock:0,category:0})4.2 数组投影// 数组投影$slicedb.orders.find({orderId:O001},{items.product:1,items.$:1// 只返回匹配的第一个元素})// 返回数组的前N个元素db.orders.find({},{items:{$slice:2}}// 只返回前2个)// 跳过前N个返回后续db.orders.find({},{items:{$slice:[1,2]}}// 跳过第1个返回2个)4.3 条件投影// 数组条件只返回满足条件的元素db.orders.find({orderId:O001},{items:{$elemMatch:{quantity:1}}})五、排序与分页5.1 排序// 按价格升序db.products.find().sort({price:1})// 按价格降序db.products.find().sort({price:-1})// 多字段排序// 先按类别升序同类按价格降序db.products.find().sort({category:1,price:-1})// 按嵌套字段排序db.orders.find().sort({customer.address.city:1})5.2 分页实现// 每页10条constpageSize10// 第一页db.products.find().limit(pageSize)// 第二页db.products.find().skip(10).limit(pageSize)// 第三页db.products.find().skip(20).limit(pageSize)// 通用分页函数functiongetPage(collection,page,pageSize){returncollection.find().skip((page-1)*pageSize).limit(pageSize)}// 实际使用constpage1getPage(db.products,1,10)constpage2getPage(db.products,2,10)5.3 实战带过滤的分页查询// 带条件、排序、分页的完整查询db.products.find({category:手机,price:{$gt:3000}}// 查询条件).sort({price:-1})// 按价格降序.skip(0)// 跳过0条.limit(10)// 取10条// 返回总数用于分页导航db.products.countDocuments({category:手机,price:{$gt:3000}})六、正则表达式查询6.1 基本正则查询// 查询名称以i开头的商品db.products.find({name:/^i/})db.products.find({name:{$regex:^i}})// 查询名称包含Phone的商品db.products.find({name:/Phone/})db.products.find({name:{$regex:Phone}})// 查询名称以Pro结尾的商品db.products.find({name:/Pro$/})db.products.find({name:{$regex:Pro$}})// 不区分大小写db.products.find({name:{$regex:iphone,$options:i}})// 忽略重音符号db.products.find({name:{$regex:iphone,$options:si}})6.2 正则选项选项说明i不区分大小写m多行匹配s让.匹配换行符x忽略空白和注释七、聚合管道查询7.1 $match - 过滤// 使用聚合管道进行复杂查询db.orders.aggregate([{$match:{status:completed}},{$sort:{total:-1}},{$limit:5}])7.2 $group - 分组统计// 按类别统计商品数量和平均价格db.products.aggregate([{$group:{_id:$category,count:{$sum:1},avgPrice:{$avg:$price},totalStock:{$sum:$stock}}}])// 按城市统计订单数量db.orders.aggregate([{$group:{_id:$customer.address.city,orderCount:{$sum:1},totalAmount:{$sum:$total}}},{$sort:{totalAmount:-1}}])八、查询性能优化8.1 使用explain分析查询// 分析查询执行计划db.products.find({category:手机,price:{$gt:3000}}).explain(executionStats)// 查看关键指标// - executionTimeMillis: 执行时间// - totalDocsExamined: 扫描的文档数// - indexUsed: 是否使用索引8.2 优化建议 查询优化技巧 1. 只查询需要的字段 db.users.find({}, { name: 1, email: 1 }) 2. 使用索引字段进行查询 db.users.find({ age: 25 }) // age有索引 3. 避免全表扫描 ❌ db.users.find({ name: { $ne: test } }) ✅ db.users.find({ status: active }) 4. 使用覆盖索引 查询字段都是索引字段 5. 限制返回结果数量 db.products.find().limit(100)九、实战案例电商商品筛选9.1 多维度筛选// 需求筛选手机类别价格在3000-6000库存大于50db.products.find({category:手机,price:{$gte:3000,$lte:6000},stock:{$gt:50}}).sort({price:1})9.2 复杂搜索// 需求搜索名称包含手机或iPhone价格小于5000的商品db.products.find({$or:[{name:{$regex:手机}},{name:{$regex:iPhone,$options:i}}],price:{$lt:5000}})9.3 聚合统计// 需求统计各类别商品数量、平均价格、最高最低价db.products.aggregate([{$group:{_id:$category,count:{$sum:1},avgPrice:{$avg:$price},maxPrice:{$max:$price},minPrice:{$min:$price}}},{$sort:{count:-1}}])十、总结 本篇总结 ✅ 掌握内容 - 比较操作符$eq、$ne、$gt、$lt、$in、$nin - 逻辑操作符$and、$or、$not、$nor - 数组查询$all、$elemMatch、$size - 嵌套文档点号访问、$elemMatch - 投影字段选择、数组切片 - 排序与分页 - 正则表达式 - 聚合管道基础 - 查询优化技巧作者刘~浪地球更新时间2026-05-09本文声明原创不易转载需授权