MongoDB查询技能Skill mongodb-find-queries

这个技能用于掌握MongoDB数据库的find查询方法,包括过滤器、投影、排序、分页等操作,适用于后端开发中的数据检索和查询优化。关键词:MongoDB, 数据库查询, 后端开发, 数据检索, 查询优化。

后端开发 0 次安装 0 次浏览 更新于 3/14/2026

名称: mongodb-find-queries 版本: “2.1.0” 描述: 掌握使用过滤器、投影、排序和分页的MongoDB查找查询。学习查询运算符、比较、逻辑运算符和现实世界查询模式。用于从MongoDB集合中检索数据。 sasmp_version: “1.3.0” bonded_agent: 02-mongodb-queries-aggregation bond_type: PRIMARY_BOND

生产级技能配置

能力:

  • 查询构建
  • 过滤器运算符
  • 投影设计
  • 排序分页
  • 文本搜索

输入验证: 必需上下文: - 集合名称 - 过滤条件 可选上下文: - 投影字段 - 排序顺序 - 分页参数

输出格式: 查询: 对象 选项: 对象 解释: 字符串 性能提示: 数组

错误处理: 常见错误: - 代码: FIND001 条件: “投影混合包含/排除” 恢复: “使用包含或排除,不要同时使用(除了_id)” - 代码: FIND002 条件: “排序内存限制超出” 恢复: “在排序字段上创建索引或使用allowDiskUse” - 代码: FIND003 条件: “无效的正则表达式模式” 恢复: “验证正则表达式语法,转义特殊字符”

先决条件: mongodb_version: “4.0+” 必需知识: - mongodb基础 - 查询运算符 索引要求: - “推荐在频繁过滤的字段上创建索引”

测试: 单元测试模板: | // 测试查找查询 const results = await collection.find(filter, { projection }).toArray() expect(results).toHaveLength(expectedCount) expect(results[0]).toHaveProperty(‘expectedField’)

MongoDB查找查询

掌握用于强大数据检索的find()方法。

快速开始

基本查询

// 查找一个文档
const user = await collection.findOne({ email: 'user@example.com' })

// 查找多个文档
const users = await collection.find({ status: 'active' }).toArray()

// 查找多个条件
const products = await collection.find({
  price: { $gt: 100 },
  category: 'electronics'
}).toArray()

查询运算符参考

比较运算符:

{ field: { $eq: value } }      // 等于
{ field: { $ne: value } }      // 不等于
{ field: { $gt: value } }      // 大于
{ field: { $gte: value } }     // 大于或等于
{ field: { $lt: value } }      // 小于
{ field: { $lte: value } }     // 小于或等于
{ field: { $in: [val1, val2] } } // 在数组中
{ field: { $nin: [val1, val2] } } // 不在数组中

逻辑运算符:

{ $and: [{field1: val1}, {field2: val2}] }  // AND
{ $or: [{field1: val1}, {field2: val2}] }   // OR
{ $not: {field: {$gt: 5}} }                // NOT
{ $nor: [{field1: val1}, {field2: val2}] }  // NOR

数组运算符:

{ field: { $all: [val1, val2] } }    // 数组中所有值
{ field: { $elemMatch: {...} } }     // 匹配数组元素
{ field: { $size: 5 } }              // 数组大小恰好为5

投影(选择字段)

// 包含字段
db.users.findOne({...}, { projection: { name: 1, email: 1 } })
// 返回: { _id, name, email }

// 排除字段
db.users.findOne({...}, { projection: { password: 0 } })
// 返回: 除密码外的所有字段

// 隐藏_id
db.users.findOne({...}, { projection: { _id: 0, name: 1 } })

// 计算字段
db.users.findOne({...}, {
  projection: {
    firstName: 1,
    lastName: 1,
    fullName: { $concat: ['$firstName', ' ', '$lastName'] }
  }
})

排序

// 升序排序 (1) 或降序排序 (-1)
db.products.find({}).sort({ price: 1 }).toArray()      // 价格升序
db.products.find({}).sort({ createdAt: -1 }).toArray() // 最新优先

// 多字段排序
db.orders.find({}).sort({
  status: 1,        // 活动优先
  createdAt: -1     // 然后最新
}).toArray()

// 不区分大小写排序
db.users.find({}).collation({ locale: 'en', strength: 2 }).sort({ name: 1 })

分页

// 方法1: 跳过和限制
const pageSize = 10
const pageNumber = 2
const skip = (pageNumber - 1) * pageSize

const results = await collection
  .find({})
  .skip(skip)
  .limit(pageSize)
  .toArray()

// 方法2: 基于游标(更适合大数据集)
const lastId = objectIdOfLastDocument
const results = await collection
  .find({ _id: { $gt: lastId } })
  .limit(pageSize)
  .toArray()

文本搜索

// 首先创建文本索引
db.articles.createIndex({ title: 'text', content: 'text' })

// 搜索
db.articles.find(
  { $text: { $search: 'mongodb database' } },
  { score: { $meta: 'textScore' } }
).sort({ score: { $meta: 'textScore' } }).toArray()

// 短语搜索
db.articles.find({ $text: { $search: '"mongodb database"' } })

// 排除术语
db.articles.find({ $text: { $search: 'mongodb -relational' } })

正则表达式查询

// 区分大小写正则表达式
db.users.find({ email: { $regex: /^admin/, $options: '' } })

// 不区分大小写
db.users.find({ email: { $regex: /gmail/, $options: 'i' } })

// 多行
db.posts.find({ content: { $regex: /^mongodb/m } })

// 字符串模式
db.users.find({ email: { $regex: '^[a-z]+@gmail', $options: 'i' } })

高级查询模式

嵌套文档查询

// 查询嵌套字段
db.users.find({ 'address.city': 'New York' })

// 匹配整个嵌套文档
db.users.find({ address: { street: '123 Main', city: 'NY' } })

// 嵌套数组
db.orders.find({ 'items.productId': ObjectId(...) })

日期查询

// 日期范围
db.orders.find({
  createdAt: {
    $gte: new Date('2024-01-01'),
    $lt: new Date('2024-12-31')
  }
})

// 本周
const now = new Date()
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
db.posts.find({ publishedAt: { $gte: weekAgo } })

空值处理

// 查找空值
db.users.find({ phone: null })

// 查找缺失字段
db.users.find({ phone: { $exists: false } })

// 查找非空
db.users.find({ phone: { $ne: null } })

// 不缺失
db.users.find({ phone: { $exists: true } })

性能提示

查询优化:

  1. 使用索引 在频繁过滤的字段上
  2. 早期过滤 - $match 在其他阶段之前
  3. 投影字段 - 不要获取不必要的数据
  4. 限制结果 - 使用分页
  5. 使用explain() - 分析每个查询

常见错误:

  1. find({}) 没有限制 - 返回所有文档
  2. ❌ 在过滤字段上没有索引 - 全集合扫描
  3. ❌ 获取不需要的字段 - 浪费带宽
  4. ❌ 排序没有索引 - 内存密集型
  5. ❌ 复杂正则表达式模式 - 性能慢

现实世界示例

用户搜索与分页

async function searchUsers(searchTerm, page = 1) {
  const pageSize = 20
  const skip = (page - 1) * pageSize

  const users = await db.users
    .find({
      $or: [
        { name: { $regex: searchTerm, $options: 'i' } },
        { email: { $regex: searchTerm, $options: 'i' } }
      ]
    })
    .project({ password: 0 })  // 不返回密码
    .sort({ name: 1 })
    .skip(skip)
    .limit(pageSize)
    .toArray()

  const total = await db.users.countDocuments({
    $or: [
      { name: { $regex: searchTerm, $options: 'i' } },
      { email: { $regex: searchTerm, $options: 'i' } }
    ]
  })

  return {
    data: users,
    total,
    pages: Math.ceil(total / pageSize),
    currentPage: page
  }
}

高级过滤

async function filterProducts(filters) {
  const query = {}

  if (filters.minPrice) query.price = { $gte: filters.minPrice }
  if (filters.maxPrice) query.price = { ...query.price, $lte: filters.maxPrice }
  if (filters.category) query.category = filters.category
  if (filters.inStock) query.stock = { $gt: 0 }
  if (filters.rating) query.rating = { $gte: filters.rating }

  return await db.products
    .find(query)
    .sort({ [filters.sortBy]: filters.sortOrder })
    .limit(filters.limit || 50)
    .toArray()
}

下一步

  1. 创建示例查询 - 查找 + 过滤器
  2. 添加投影 - 选择所需字段
  3. 实现排序 - 排序结果
  4. 添加分页 - 处理大数据集
  5. 监控性能 - 使用explain()

你现在是MongoDB查询专家了! 🎯