MongoDB $last Accumulator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $last?

$last is a MongoDB accumulator for the $group stage. For each group it returns the value of an expression from the last document that entered that group—so order from a preceding $sort decides what “last” means.

Remember
$last = value from the trailing document per group

$sort first → define order (e.g. date ascending)
$group      → one bucket per key
$last       → read a field from the last doc in that order

vs $first → leading doc; vs $max → largest value, not last doc
UsePrefer
Latest date / closing value after sort$last
Earliest date / opening value$first
Largest numeric field (ignore order)$max

How to Use $last in MongoDB

Sort first, then capture one field (or $$ROOT) from the trailing document.

  1. Add $sort so documents arrive in the order you care about.
  2. Put $last inside $group on an output field.
  3. Pass a field path (e.g. "$date") or any expression, including "$$ROOT".
  4. Set _id to the group key (item, category, or null for one group).
PieceRequired?Role
$sortStrongly recommendedDefines which document is last
$group._idYesGroup key ("$item", null, …)
$lastYesExpression evaluated on the last document

Pseudocode

Pseudocode
documents = sort(input, { item: 1, date: 1 })
for each group (by item):
    lastDoc = final document that entered the group
    value   = evaluate(expression, lastDoc)   // e.g. lastDoc.date
    emit { _id: item, field: value }

Cheat Sheet

Keep these facts handy while picking the last value per group.

TopicDetail
Stage$group accumulator (also $bucket, windows)
Syntax{ $last: "$field" }
Latest date$sort: { date: 1 } then $last: "$date"
Full last document{ $last: "$$ROOT" }
Missing fieldReturns null (no fallback to earlier docs)
Sample checkabc dates Jan 1, Feb 15 → last = Feb 15

Live Preview

Watch $sort by date, then $last pick the trailing sale. Sample: abc (Jan 1, Feb 15), xyz (Feb 3, Feb 15).

Simulates ascending date sort; the last document in each item group supplies $last: "$date".

Result
abc sorted by date ↑: 2014-01-01, 2014-02-15
  → $last = 2014-02-15
xyz sorted by date ↑: 2014-02-03, 2014-02-15
  → $last = 2014-02-15

[
  { _id: "abc", lastSale: "2014-02-15" },
  { _id: "xyz", lastSale: "2014-02-15" }
]

Worked Walkthrough — Last Sale Date

Four sales, two items. Sort by date ascending; $last keeps the newest date in each bucket.

Calculation
Documents (after $sort by item, date ↑):
  { item: "abc", date: 2014-01-01 }
  { item: "abc", date: 2014-02-15 }
  { item: "xyz", date: 2014-02-03 }
  { item: "xyz", date: 2014-02-15 }

group "abc":
  enter Jan 1 → then Feb 15 (last)
  $last: "$date" → 2014-02-15

group "xyz":
  enter Feb 3 → then Feb 15 (last)
  $last: "$date" → 2014-02-15

Output:
  { _id: "abc", lastSale: ISODate("2014-02-15...") }
  { _id: "xyz", lastSale: ISODate("2014-02-15...") }

MongoDB Examples

We use a tiny sales list. First we find the latest sale date per item. Then we pair $first with $last for a date range. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine four sales in a sales collection. Each document has an item, a date, and a price.

mongosh
db.sales.insertMany([
  { item: "abc", price: 10, date: ISODate("2014-01-01T08:00:00Z") },
  { item: "abc", price: 12, date: ISODate("2014-02-15T08:00:00Z") },
  { item: "xyz", price: 5,  date: ISODate("2014-02-03T09:00:00Z") },
  { item: "xyz", price: 8,  date: ISODate("2014-02-15T14:00:00Z") }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps 4 documents in sales. Run find() to see them:

mongosh
db.sales.find()

Read each document like this:

Field in MongoDBMeaningExample
itemProduct code"abc"
priceSale price12
dateWhen the sale happened2014-02-15
Picture
abc sales: Jan 1 (price 10), Feb 15 (price 12)
xyz sales: Feb 3 (price 5), Feb 15 (price 8)

Next: $last keeps the latest sale per item (after $sort).

How It Works

  1. Insert once. The sample command adds 4 documents to sales.
  2. MongoDB stores fields as written. Each document keeps the same field names and values you inserted.
  3. find() shows the same shape. What you inserted is what you get back—ready for $last in the next examples.

After sorting by date ascending, the last sale for each item is on 2014-02-15.

Example 2 — Last Sale Date per Item

Goal: one latest date for each product. Sort by item and date ascending so the newest sale sits at the end of each group.

mongosh
db.sales.aggregate([
  // Ascending date → last document = latest sale
  { $sort: { item: 1, date: 1 } },
  {
    $group: {
      _id: "$item",
      lastSale: { $last: "$date" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Sort first. $sort: { item: 1, date: 1 } lines up sales from oldest to newest within each item.
  2. Split into buckets. _id: "$item" makes separate groups for abc and xyz.
  3. Read the trailing date. $last: "$date" takes the date from the last document that entered each group.
  4. Check the answer. abc ends on Feb 15 morning; xyz ends on Feb 15 afternoon.
  5. Need several trailing values? Use $lastN instead of one $last.

Example 3 — First and Last Dates per Item

Goal: open and close dates for each product in one pass. With ascending date order, $first is earliest and $last is latest.

ItemDates (sorted ↑)$first$last
abcJan 1, Feb 152014-01-012014-02-15
xyzFeb 3, Feb 152014-02-032014-02-15
mongosh
db.sales.aggregate([
  { $sort: { item: 1, date: 1 } },
  {
    $group: {
      _id: "$item",
      firstSale: { $first: "$date" },
      lastSale:  { $last: "$date" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Same sort, two readers. Ascending dates make the first document earliest and the last document latest.
  2. $first for open. abc opens on Jan 1; xyz opens on Feb 3.
  3. $last for close. Both items close on Feb 15 (different times).
  4. Not the same as $max. $max: "$price" would pick the highest price, which may not sit on the last-dated document.

Edge Cases & Pitfalls

Check these before shipping a “latest value” report.

$sort

Always sort when order matters

Without $sort, “last” is whatever order MongoDB processes—often not the latest date.

null

Missing field on last doc → null

$last does not skip to an earlier document. Guard with $ifNull or ensure the field exists.

$max

Last document ≠ max value

Use $last for order-based picks; use $max when you want the largest number regardless of position.

array

Array fields return the whole array

If the expression on the last doc is an array, $last returns that entire array—not its last element.

Performance Notes

ApproachCostBest for
$sort + $lastSort then one pass per groupLatest / trailing field after a clear order
$max on datesNo sort required for max aloneOnly the maximum date value (not other fields from that doc)
$lastNKeeps N trailing valuesSeveral recent values per group

Sorting can dominate cost on large collections. Filter early with $match, and sort only the fields you need (item + date). An index on the sort keys helps when the planner can use it.

Key Takeaways

  • Role: value from the trailing document in each $group.
  • Order: $sort before $group defines what “last” means.
  • Pair: $first + $last for open/close ranges after one sort.
  • vs $max: last doc by order, not the largest field value.

One line: $last reads a field from the last document in each group—sort first so that document is the one you intend.

Frequently Asked Questions

$last returns the value of an expression from the last document in each $group bucket—based on the order documents arrive at $group. Use it for latest dates, most recent order IDs, or closing values per category.
Yes, in almost every real pipeline. $last does not sort for you—it takes whatever document is last in the current order. Add $sort before $group so last means what you expect (for example, latest date).
$last reads the final document in each group; $first reads the leading one. With $sort: { date: 1 }, $first gives the earliest date and $last gives the latest.
$max returns the largest value across all documents in a group. $last returns a field from the last document in pipeline order—they can differ if the highest value is not on that last document.
$last returns null when the expression resolves to a missing field on that last document. It does not fall back to earlier documents in the group.
As an accumulator in $group, $bucket, and $bucketAuto. It is also a window operator in $setWindowFields (MongoDB 5.0+) with sortBy on the window.

Next: $lastN

Return the last N values from each group after sorting.

$lastN tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful