MongoDB - 排序记录
MongoDB - 文档排序
Section titled “MongoDB - 文档排序”文档排序是数据库的基本操作之一。本章将深入探讨如何在 MongoDB 中使用现代最佳实践对查询结果进行排序。
sort() 方法
Section titled “sort() 方法”要对 find() 查询返回的文档进行排序,可以链式调用 sort() 方法。此方法接受一个文档,该文档指定了要排序的字段及其排序顺序。使用 1 表示升序,-1 表示降序。
db.collectionName.find(query).sort({ field1: 1, field2: -1, ... })示例:基本排序和多字段排序
Section titled “示例:基本排序和多字段排序”首先,让我们向 products 集合插入一些示例数据。请注意,我们使用了现代 BSON 类型,例如用于整数值的 NumberInt。
// 确保集合为空,以便进行干净的测试db.products.drop();
// 使用 insertMany 插入示例文档db.products.insertMany([ { name: "Laptop Pro", category: "Electronics", price: 1200, stock: 15 }, { name: "Wireless Mouse", category: "Accessories", price: 25, stock: 200 }, { name: "Mechanical Keyboard", category: "Accessories", price: 75, stock: 50 }, { name: "4K Monitor", category: "Electronics", price: 400, stock: 30 }, { name: "Webcam HD", category: "Accessories", price: 75, stock: 0 }]);现在,让我们按价格降序(最贵优先)对这些产品进行排序:
> db.products.find().sort({ price: -1 })
// 结果:[ { _id: ..., name: 'Laptop Pro', category: 'Electronics', price: 1200, stock: 15 }, { _id: ..., name: '4K Monitor', category: 'Electronics', price: 400, stock: 30 }, { _id: ..., name: 'Mechanical Keyboard', category: 'Accessories', price: 75, stock: 50 }, { _id: ..., name: 'Webcam HD', category: 'Accessories', price: 75, stock: 0 }, { _id: ..., name: 'Wireless Mouse', category: 'Accessories', price: 25, stock: 200 }]对于多字段排序,MongoDB 会按照字段列出的顺序进行排序。让我们先按类别升序排序,然后在每个类别内按价格降序排序:
> db.products.find().sort({ category: 1, price: -1 })
// 结果:[ { _id: ..., name: 'Mechanical Keyboard', category: 'Accessories', price: 75, stock: 50 }, { _id: ..., name: 'Webcam HD', category: 'Accessories', price: 75, stock: 0 }, { _id: ..., name: 'Wireless Mouse', category: 'Accessories', price: 25, stock: 200 }, { _id: ..., name: 'Laptop Pro', category: 'Electronics', price: 1200, stock: 15 }, { _id: ..., name: '4K Monitor', category: 'Electronics', price: 400, stock: 30 }]排序可能是一项资源密集型操作,尤其是在大型数据集上。如果排序操作没有索引支持,MongoDB 必须在内存中执行“阻塞式排序”(blocking sort)。如果此操作需要的 RAM 超过 32 兆字节,则查询将失败。
为了确保高效排序,您应该创建与排序键匹配的索引。对于上述多字段排序,理想的索引将是:
> db.products.createIndex({ category: 1, price: -1 })有了这个索引,MongoDB 可以直接从索引中读取预排序的文档,这大大加快了速度,并避免了内存排序的限制。
使用聚合管道进行排序
Section titled “使用聚合管道进行排序”对于更复杂的场景,排序通常作为聚合管道 (aggregation pipeline) 中的一个阶段 (stage) 完成,使用 $sort 操作符。这允许您在排序数据之前对其进行转换。
// 示例:查找所有配件,按价格排序,并仅投影名称和价格字段db.products.aggregate([ { $match: { category: "Accessories" } }, { $sort: { price: -1 } }, { $project: { _id: 0, name: 1, price: 1 } }])
// 结果:[ { name: 'Mechanical Keyboard', price: 75 }, { name: 'Webcam HD', price: 75 }, { name: 'Wireless Mouse', price: 25 }]常见错误与调试
Section titled “常见错误与调试”- 超出内存限制: 如果您看到类似
Sort operation used more than the maximum 32MB of RAM的错误,这明确表明您的排序查询缺少适当的索引。 - 区分大小写: 排序文档中的字段名是区分大小写的,必须与文档中的字段完全匹配。
- 使用
explain()调试: 要验证您的排序是否使用了索引,请使用explain()方法:db.products.find().sort({ price: -1 }).explain('executionStats')。在输出中查找使用IXSCAN(索引扫描)的FETCH阶段,并确保计划中没有SORT阶段,这表明这是一个高效的、使用索引的排序。