การเรียงลำดับด้วย sort() และหลายคีย์
ผู้เรียนจะเรียงลำดับผลลัพธ์การค้นหาตามฟิลด์หนึ่งฟิลด์หรือมากกว่า โดยเรียงจากน้อยไปมากและจากมากไปน้อย และดูว่า sort ทำงานร่วมกับการใช้ดัชนีอย่างไร
การเรียงลำดับด้วย sort() และหลายคีย์ เป็นบทเรียน MongoDB Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน MongoDB Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส MongoDB Academy มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Ordering Query Results With sort()
The sort() method appended to a find() cursor tells MongoDB to return documents in a specific order. Pass an object where each key is a field name and each value is 1 (ascending) or -1 (descending). Sorting happens on the server before documents are sent to the client, so you receive results in order regardless of how many documents match.
// Ascending: oldest first
db.posts.find({}).sort({ createdAt: 1 });
// Descending: newest first
db.posts.find({}).sort({ createdAt: -1 });
// With Node.js driver
const posts = await db.collection('posts')
.find({})
.sort({ createdAt: -1 })
.toArray();Sorting by Multiple Keys
MongoDB sorts by the first key first, then uses subsequent keys to break ties. Pass multiple fields in the sort object. The order of keys matters: the first key is the primary sort, the second is the tiebreaker. A common example is sorting products by category ascending, then by price descending within each category.
// Primary sort: category ASC; secondary sort: price DESC
db.products.find({}).sort({ category: 1, price: -1 });
// Sorting users by role then by username alphabetically
db.users.find({}).sort({ role: 1, username: 1 });
// Sorting blog posts: featured first, then newest
db.posts.find({}).sort({ isFeatured: -1, createdAt: -1 });Sort and Index Interaction
When the sort fields match an index, MongoDB can satisfy the sort without loading and sorting all documents in memory. It walks the index in the requested direction instead. This is called an index sort and it is dramatically faster than an in-memory sort, especially on large collections. Always create an index that covers your most common sort operations.
// Create an index that supports category-then-price sorting
db.products.createIndex({ category: 1, price: -1 });
// This query now sorts via index — no in-memory sort needed
db.products.find({ isActive: true }).sort({ category: 1, price: -1 });
// verify with explain
db.products.find({}).sort({ category: 1, price: -1 }).explain('executionStats');The 32 MB In-Memory Sort Limit
If a sort cannot use an index, MongoDB must load all matching documents into memory to sort them. This in-memory sort has a hard limit of 32 MB. If the matching documents exceed 32 MB, the sort fails with Executor error: OperationFailed: Sort exceeded memory limit. The fix is to add an index that supports the sort, or use allowDiskUse: true in aggregation pipelines.
// In an aggregation, allow spilling to disk for large sorts
db.logs.aggregate(
[{ $sort: { timestamp: -1 } }],
{ allowDiskUse: true } // allows spilling sort to temporary disk files
);Sort Direction and Index Direction Must Align
For a compound index to serve a compound sort, the directions must align—either exactly match or completely reverse. An index on { a: 1, b: 1 } supports sorts on { a: 1, b: 1 } (forward scan) and { a: -1, b: -1 } (backward scan) but cannot support { a: 1, b: -1 } or { a: -1, b: 1 }. Mixed-direction sorts require an index that matches the mixed directions exactly.
// This index supports { a: 1, b: -1 } sorts
db.collection.createIndex({ a: 1, b: -1 });
// Supported: forward
db.collection.find({}).sort({ a: 1, b: -1 });
// Supported: backward (reverse scan)
db.collection.find({}).sort({ a: -1, b: 1 });
// NOT supported by this index:
// db.collection.find({}).sort({ a: 1, b: 1 });Natural Order Sort
The $natural sort key returns documents in their natural on-disk insertion order. { $natural: 1 } returns documents in insertion order; { $natural: -1 } returns them in reverse. This bypasses all indexes and is rarely used in production—it is mainly useful for capped collections, which maintain strict insertion order for log-like workloads.
// Capped collection — return events in insertion order
db.eventLog.find({}).sort({ $natural: 1 });
// Reverse insertion order
db.eventLog.find({}).sort({ $natural: -1 });Combining sort() With limit() and skip()
Sorting is almost always combined with limit() to fetch only the top N results, and sometimes with skip() for paginated results. The operation order is: filter → sort → skip → limit. MongoDB applies them in this sequence regardless of the order you chain them in your driver code. Sorting before limiting is what lets you get the 'top 10' results correctly.
// Top 10 highest-rated products in the 'electronics' category
const topProducts = await db.collection('products')
.find({ category: 'electronics', isActive: true })
.sort({ rating: -1 })
.limit(10)
.toArray();
// Page 3 of results (20 per page)
const page3 = await db.collection('products')
.find({})
.sort({ createdAt: -1 })
.skip(40) // skip pages 1 and 2
.limit(20)
.toArray();Sorting in Mongoose
Mongoose's query builder exposes .sort() with the same syntax as the native driver, plus a convenience string form. Pass a string of field names prefixed with + (ascending) or - (descending), separated by spaces. Both forms are equivalent and the driver compiles them to the same MongoDB sort document.
// Object syntax
const posts = await Post.find({}).sort({ createdAt: -1, title: 1 });
// String syntax — '-' means descending, no prefix means ascending
const posts2 = await Post.find({}).sort('-createdAt title');
// Multi-field sort with limit in a chain
const recent = await Post
.find({ isPublished: true })
.sort('-createdAt')
.limit(5)
.select('title createdAt');Sorting Null and Missing Fields
In MongoDB sort results, documents where the sort field is missing or null sort as if the field value is null. In ascending order, null and missing values appear first (before any other value). In descending order they appear last. Be aware of this behaviour when some documents are missing the sort field—it can cause unexpected ordering in mixed-schema collections.
Stable Sort With a Secondary _id Key
MongoDB's sort is not guaranteed stable when two documents have the same value for the sort key—their relative order is undefined and may change between queries. To get a deterministic, stable ordering, always include _id as a final tiebreaker. Since _id is unique, it guarantees a consistent order even when primary sort keys are equal.
// Stable sort: primary sort by rating DESC, tiebreaker by _id ASC
db.products.find({}).sort({ rating: -1, _id: 1 });
// Without _id as tiebreaker, documents with the same rating
// may appear in different order on repeated queriesVerifying Sort Uses an Index
Run explain('executionStats') and look for the SORT stage in the execution plan. If you see an IXSCAN feeding directly into a cursor without a SORT stage, the sort is served by the index (ideal). If there is a SORT stage, the sort is in-memory and an index might help. Also check memUsage inside the SORT stage to understand how much memory the sort consumed.
const plan = db.products.find({}).sort({ rating: -1 }).explain('executionStats');
// Look in plan.executionStats.executionStages for 'SORT' stage
// 'IXSCAN' without 'SORT' = index sort (best)
// 'SORT' stage = in-memory sort (may need an index)Quick Check
Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.
Lesson Recap
In this lesson you learned: sort() accepts a document of field-direction pairs where 1 is ascending and -1 is descending, compound sorts use later fields as tiebreakers, and matching an index avoids the 32 MB in-memory sort limit. Next up we explore skip and limit offset pagination and its performance trade-offs at scale.
คำถามที่พบบ่อย
บทเรียน “การเรียงลำดับด้วย sort() และหลายคีย์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การเรียงลำดับด้วย sort() และหลายคีย์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส MongoDB Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส MongoDB Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การเรียงลำดับด้วย sort() และหลายคีย์”
ผู้เรียนจะเรียงลำดับผลลัพธ์การค้นหาตามฟิลด์หนึ่งฟิลด์หรือมากกว่า โดยเรียงจากน้อยไปมากและจากมากไปน้อย และดูว่า sort ทำงานร่วมกับการใช้ดัชนีอย่างไร คุณปฏิบัติ MongoDB Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน MongoDB Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน MongoDB Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การเรียงลำดับด้วย sort() และหลายคีย์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน MongoDB Academy นี้ได้ไหม
ได้ บทเรียน MongoDB Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การเรียงลำดับด้วย sort() และหลายคีย์
- การข้ามและการจำกัด: การแบ่งหน้าแบบออฟเซ็ต
- การแบ่งหน้าแบบคีย์เซ็ตด้วยการค้นหาแบบช่วง
- การรวม sort, skip, limit และโพรเจกชัน