阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 条件查询与复杂过滤

条件查询与复杂过滤

作者:陈川 阅读数:58610人阅读 分类: MongoDB

条件查询基础

Mongoose提供了丰富的查询方法,最基本的是find()方法。它接受一个条件对象作为参数,返回匹配该条件的所有文档。

const User = mongoose.model('User', userSchema);

// 查找所有年龄大于18的用户
User.find({ age: { $gt: 18 } })
  .then(users => console.log(users))
  .catch(err => console.error(err));

常用比较操作符包括:

  • $eq: 等于
  • $ne: 不等于
  • $gt: 大于
  • $gte: 大于等于
  • $lt: 小于
  • $lte: 小于等于
  • $in: 在数组中
  • $nin: 不在数组中

逻辑操作符组合查询

Mongoose支持使用逻辑操作符组合多个条件,实现更复杂的查询逻辑。

// 查找年龄在18到30之间,或者名字为"张三"的用户
User.find({
  $or: [
    { age: { $gte: 18, $lte: 30 } },
    { name: '张三' }
  ]
}).exec();

主要逻辑操作符:

  • $and: 逻辑与
  • $or: 逻辑或
  • $nor: 逻辑非或
  • $not: 逻辑非

数组条件查询

当查询包含数组的字段时,Mongoose提供了专门的操作符来处理数组查询。

const Post = mongoose.model('Post', postSchema);

// 查找标签包含"技术"的文章
Post.find({ tags: '技术' }).exec();

// 查找标签同时包含"技术"和"编程"的文章
Post.find({ tags: { $all: ['技术', '编程'] } }).exec();

// 查找tags数组长度为3的文章
Post.find({ tags: { $size: 3 } }).exec();

数组专用操作符:

  • $all: 包含所有指定元素
  • $elemMatch: 数组元素匹配所有条件
  • $size: 数组长度匹配

嵌套文档查询

对于嵌套文档或对象类型的字段,可以使用点表示法进行查询。

const Order = mongoose.model('Order', orderSchema);

// 查找送货地址城市为"北京"的订单
Order.find({ 'shipping.address.city': '北京' }).exec();

// 使用$elemMatch查询嵌套数组
Order.find({
  items: {
    $elemMatch: {
      product: '手机',
      quantity: { $gte: 2 }
    }
  }
}).exec();

正则表达式查询

Mongoose支持使用正则表达式进行模糊查询,特别适合文本搜索。

// 查找名字以"张"开头的用户
User.find({ name: /^张/ }).exec();

// 使用RegExp对象,不区分大小写
User.find({ name: new RegExp('wang', 'i') }).exec();

分页与排序

结合条件查询,通常需要实现分页和排序功能。

const page = 1;
const limit = 10;

User.find({ active: true })
  .sort({ createdAt: -1 }) // 按创建时间降序
  .skip((page - 1) * limit) // 跳过前面的记录
  .limit(limit) // 限制返回数量
  .exec();

聚合查询

对于更复杂的数据分析和统计,可以使用Mongoose的聚合框架。

User.aggregate([
  { $match: { age: { $gte: 18 } } }, // 条件筛选
  { $group: { 
    _id: '$city', 
    total: { $sum: 1 },
    avgAge: { $avg: '$age' }
  } }, // 按城市分组统计
  { $sort: { total: -1 } }, // 按总数降序
  { $limit: 5 } // 只返回前5条
]).exec();

查询性能优化

针对大型数据集,查询性能优化至关重要。

  1. 索引优化
userSchema.index({ name: 1 }); // 单字段索引
userSchema.index({ age: 1, city: 1 }); // 复合索引
  1. 选择性查询:只查询需要的字段
User.find({}, 'name email').exec(); // 只返回name和email字段
  1. 使用lean():返回普通JS对象而非Mongoose文档,减少开销
User.find().lean().exec();

链式查询构建

Mongoose查询支持链式调用,可以动态构建查询条件。

const query = User.find();

// 根据条件动态添加查询
if (minAge) {
  query.where('age').gte(minAge);
}
if (maxAge) {
  query.where('age').lte(maxAge);
}
if (namePattern) {
  query.where('name').regex(new RegExp(namePattern, 'i'));
}

query.exec().then(users => {
  // 处理结果
});

高级查询技巧

  1. 使用$where:可以执行JavaScript表达式
User.find({ $where: 'this.age > this.minAge + 5' }).exec();
  1. 地理空间查询:对于包含地理坐标的数据
const Place = mongoose.model('Place', placeSchema);

Place.find({
  location: {
    $near: {
      $geometry: {
        type: 'Point',
        coordinates: [longitude, latitude]
      },
      $maxDistance: 1000 // 1公里范围内
    }
  }
}).exec();
  1. 文本搜索:需要先创建文本索引
postSchema.index({ content: 'text' });

Post.find({ $text: { $search: '数据库 优化' } })
  .sort({ score: { $meta: 'textScore' } })
  .exec();

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌