在开发 Web 应用时,数据库中的索引可以极大地提升查询效率,MongoDB 作为常见的 NoSQL 数据库也不例外。本文将介绍 MongoDB 中的联合索引(Compound Index)以及 Mongoose 对联合索引的支持和应用实践。
联合索引
所谓联合索引,就是将多个字段合并为一个索引,以实现更高效的查询。通常,使用多个单字段索引也能满足查询的需求,但在一些情况下,联合索引能够更好地优化查询性能:
- 多个字段组合在一起唯一性很高,单独使用单字段索引的唯一性更低
- 多个字段组合在一起经常被查询,使用联合索引会降低查询开销
下面是一个示例联合索引:
db.users.createIndex({ username: 1, email: 1 }, { unique: true });
这个联合索引将 username
和 email
字段合并,使得查询某个用户名和邮箱地址的用户时能够较快地从数据库中获取对应数据。
Mongoose 对联合索引的支持
Mongoose 是一个使用 JavaScript 对 MongoDB 进行便捷操作的 ORM 框架,提供了完整的 CRUD 操作和丰富的数据校验功能。在实际应用中,使用 Mongoose 操作 MongoDB 数据库时,联合索引显得尤为重要。
在 Mongoose 中,可以使用 Schema.index()
方法来声明一个索引。和 MongoDB 原生的创建索引类似,可以指定字段和索引类型等参数。下面是一个声明联合索引的示例:
const UserSchema = new mongoose.Schema({ username: String, email: String, }); UserSchema.index({ username: 1, email: 1 }, { unique: true });
除了在 Schema 中声明索引,也可以在模型的 ensureIndexes()
方法中显式创建索引,例如:
UserModel.ensureIndexes((err) => { if (err) console.log(err); });
注意,上述方法是异步操作,若有错误需要使用回调函数处理。
联合索引的应用实践
在实际开发中,联合索引可以使用在多种场景下,以下是几个范例。
范例 1:在连表查询中使用联合索引
假设我们有两个集合 User
和 Order
,一个用户可以下多个订单。现在我们想查询某个用户的所有订单。可以在 Order
集合中声明一个联合索引:
db.orders.createIndex({ userId: 1, createdAt: -1 });
上述联合索引将 userId
和 createdAt
字段组合,使得查询某个用户的所有订单时能够更加高效地进行。
在 Mongoose 中,查询可使用 .populate()
方法实现在两个集合之间的连表查询:
await Order.find({ userId: user._id }) .populate('user', 'username email') .sort('-createdAt') .exec();
范例 2:在时间范围查询中使用联合索引
假设我们有一个博客应用,有一张存放博客文章的集合 Post
,其中每篇文章有一个发布时间 publishDate
字段。现在我们想要查询某个时间段内所有发表的文章。可以在 Post
集合中声明一个联合索引:
db.posts.createIndex({ publishDate: -1, category: 1 });
上述联合索引将 publishDate
和 category
字段组合,使得在时间范围查询时能够更加高效地筛选出符合条件的文章。
在 Mongoose 中,查询可使用 $gte
和 $lte
操作符实现时间范围查询:
const start = new Date(2021, 0, 1); const end = new Date(2021, 11, 31); await Post.find({ publishDate: { $gte: start, $lte: end }, category: 'node.js', }).exec();
范例 3:在地理位置查询中使用联合索引
假设我们有一个位置数据查找应用,有一张存放位置数据的集合 Location
,其中每个位置有一个经纬度坐标 coordinate
字段。现在我们想要查询某个范围内的所有位置数据。可以在 Location
集合中声明一个联合索引:
db.locations.createIndex({ 'coordinate.geometry': '2dsphere' });
上述联合索引将 coordinate.geometry
字段指定为 2dsphere 类型,使得在地理位置查询时能够更加高效地筛选出符合条件的位置数据。
在 Mongoose 中,查询可使用 $near
和 $maxDistance
操作符实现地理位置查询:
const center = [-73.97, 40.77]; // 纬度在前,经度在后 const radius = 5; // 单位为千米 await Location.find({ 'coordinate.geometry': { $near: { $geometry: { type: 'Point', coordinates: center, }, $maxDistance: radius * 1000, }, }, }).exec();
总结
本文介绍了联合索引的定义与用途,并展示了如何在 Mongoose 中声明和使用联合索引。合理使用联合索引能够大大提高查询性能,是优化 MongoDB 数据库的重要技巧之一。在实际应用中,应根据具体场景选择建立合适的索引,避免创建不必要或重复的索引。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a74b68add4f0e0ff04a99e