MongoDB $lastN Accumulator

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
Aggregation

What You’ll Learn

The $lastN accumulator collects the last N input values from each $group bucket—ideal for the three most recent orders per customer, latest events, or trailing scores when you define order with $sort.

01

N values per group

Array of trailing records.

02

input + n

Two required properties.

03

Needs $sort

Order before $group matters.

04

vs $last

Many values vs one value.

05

vs $bottomN

Pre-sorted vs in-group rank.

06

Array operator too

Slice array tails in $project.

Definition and Usage

$lastN is a MongoDB accumulator used in the $group stage. For each group, it evaluates an input expression on the last n documents (in pipeline order) and returns those values as an array.

💡
Beginner tip

$lastN does not sort documents. It takes the final N docs that reach each group. Add $sort before $group when you need the three latest dates, most recent statuses, or lowest scores at the tail of a descending sort.

Use $lastN when the stream is already ordered. If MongoDB should rank inside the group, consider $bottomN instead. For a single trailing value, use $last.

📝 Syntax

As a $group accumulator, $lastN requires input and n:

mongosh
{
  $group: {
    _id: <expression>,
    <field>: {
      $lastN: {
        input: <expression>,
        n: <positive integer expression>
      }
    }
  }
}

Syntax Rules

  • input — expression per document: field path, projection object, or array like ["$playerId", "$score"].
  • n — positive integer; how many trailing documents to collect. Can be constant or depend on _id.
  • Array result — unlike $last, output is always an array (up to n elements).
  • Fewer than N — groups with fewer documents return all available elements.
  • Null / missing — missing fields become null and are kept in the array.
  • Array operator — also works in $project / $addFields to take the last N elements from an array field on each document.
mongosh
db.gamescores.aggregate([
  { $sort: { gameId: 1, date: 1 } },
  {
    $group: {
      _id: "$gameId",
      recentThree: {
        $lastN: {
          input: { player: "$playerId", score: "$score" },
          n: 3
        }
      }
    }
  }
]);

⚡ Quick Reference

QuestionAnswer
Stage$group accumulator (also array operator)
Required keysinput, n
ReturnsArray of up to N values per group
Latest N pattern$sort: { date: 1 } then $lastN
Group smaller than NReturns all documents in the group
MongoDB version5.2+ (accumulator)
Last 3
n: 3

Collect three trailing values

Latest by date
$sort: { date: 1 }
$lastN: { input: "$date", n: 3 }

Asc sort → last = latest

Tuple input
input: [
  "$playerId",
  "$score"
]

Pair values per element

Dynamic n
n: {
  $cond: [
    { $eq: ["$gameId", "G2"] },
    1, 3
  ]
}

n from group key

🧰 Parameters

The $lastN accumulator object has two required properties:

input Required

Expression evaluated on each of the last n documents in the group. Can be a field path, object projection, or array of fields.

input: "$score"
input: { player: "$playerId", score: "$score" }
n Required

Positive integer limiting how many trailing documents contribute. Can be a constant or an expression tied to the group _id.

n: 5
n: { $cond: [ …, 1, 3 ] }
$sort Prerequisite

Preceding stage that defines document order. Without it, “last N” follows arbitrary processing order.

{ $sort: { gameId: 1, date: 1 } }
array operator Alternate use

In $project or $addFields, slice the last N elements from an array field (e.g. last three scores from a scores array).

{ $lastN: { n: 3, input: "$scores" } }

Examples Gallery

Game scores grouped by gameId—collect the last three player records per game and see how $sort changes results.

📚 Getting Started

Sample game scores and the core $lastN grouping pattern.

Example 1 — Sample gamescores collection

mongosh
db.gamescores.insertMany([
  { playerId: "PlayerA", gameId: "G1", score: 31 },
  { playerId: "PlayerB", gameId: "G1", score: 33 },
  { playerId: "PlayerC", gameId: "G1", score: 99 },
  { playerId: "PlayerD", gameId: "G1", score: 1 },
  { playerId: "PlayerA", gameId: "G2", score: 10 },
  { playerId: "PlayerB", gameId: "G2", score: 14 },
  { playerId: "PlayerC", gameId: "G2", score: 66 },
  { playerId: "PlayerD", gameId: "G2", score: 80 }
]);

How It Works

Two games with four players each—enough data to verify last-3 arrays per group.

Example 2 — Last three players in one game

mongosh
db.gamescores.aggregate([
  { $match: { gameId: "G1" } },
  {
    $group: {
      _id: "$gameId",
      lastThree: {
        $lastN: {
          input: ["$playerId", "$score"],
          n: 3
        }
      }
    }
  }
]);

/* Result (insertion order):
[
  {
    _id: "G1",
    lastThree: [
      ["PlayerB", 33],
      ["PlayerC", 99],
      ["PlayerD", 1]
    ]
  }
]
*/

How It Works

Without $sort, “last” means whatever order documents were inserted—fine for demos, risky in production.

📈 Practical Patterns

Control order with $sort, compare with $last, and vary n.

Example 3 — Lowest three scores per game (with $sort)

mongosh
db.gamescores.aggregate([
  { $sort: { score: -1 } },
  {
    $group: {
      _id: "$gameId",
      lowestThree: {
        $lastN: {
          input: ["$playerId", "$score"],
          n: 3
        }
      }
    }
  },
  { $sort: { _id: 1 } }
]);

/* G1 lowestThree (desc sort → low scores at tail):
   [ ["PlayerB", 33], ["PlayerA", 31], ["PlayerD", 1] ]
   G2: [ ["PlayerC", 66], ["PlayerB", 14], ["PlayerA", 10] ] */
*/

How It Works

Descending sort puts high scores first; the last three documents per group sit at the low end—similar to $bottomN when the stream is pre-sorted.

Example 4 — $lastN vs $last

mongosh
db.gamescores.aggregate([
  { $sort: { gameId: 1, score: 1 } },
  {
    $group: {
      _id: "$gameId",
      latestScore: {
        $last: "$score"
      },
      lastThreeScores: {
        $lastN: {
          input: "$score",
          n: 3
        }
      }
    }
  }
]);

/* G1 (sorted asc by score):
   latestScore: 99
   lastThreeScores: [33, 99, 1] — last 3 in sort order */
*/

How It Works

Both read from the same sorted order. $last grabs one trailing value; $lastN builds an array from the final N documents.

Example 5 — Dynamic n based on group key

Return 1 trailing score for game G2 but 3 for every other game:

mongosh
db.gamescores.aggregate([
  {
    $group: {
      _id: { gameId: "$gameId" },
      scores: {
        $lastN: {
          input: "$score",
          n: {
            $cond: {
              if: { $eq: ["$gameId", "G2"] },
              then: 1,
              else: 3
            }
          }
        }
      }
    }
  },
  { $sort: { "_id.gameId": 1 } }
]);

/* G1 → [33, 99, 1]
   G2 → [80] */
*/

How It Works

n can depend on _id—useful when different categories need different tail sizes in one pipeline.

🧠 How $lastN Works

1

Documents sorted

$sort (recommended) defines the order documents flow into $group.

Sort
2

Documents bucketed

$group assigns each document to a bucket via _id.

Group
3

Last N captured

MongoDB keeps a rolling window—the final n documents determine the result.

Collect
=

Array returned

Up to n elements per group—each shaped by the input expression.

📝 Notes

  • Always $sort first when “last N” must mean latest, trailing, or lowest-at-tail.
  • $lastN requires MongoDB 5.2+ as a $group accumulator.
  • Result is an array per group; use $last for a single scalar.
  • Groups with fewer than n documents return all available trailing elements.
  • As an array operator, $lastN slices array field tails in $addFields—separate from group accumulation.
  • Pre-sorted streams: $lastN often replaces $bottomN; unsorted groups: prefer $bottomN.
  • Previous topic: $last. Next: $max.

Conclusion

$lastN extends $last to collect several trailing values per group. Pair it with $sort, set input and n, and you get clean recent-N or tail-N reports without manual array slicing.

Need only one value? Use $last. Need in-group ranking? Try $bottomN. Next up: $max for peak values across a group.

💡 Best Practices

✅ Do

  • Add $sort before $group whenever order defines “last”
  • Include tie-break sort keys (_id, timestamp) for stable tail arrays
  • Use tuple input: ["$player", "$score"] for compact recent-record rows
  • Test groups smaller than n to confirm array length behavior
  • Use the array-operator form to slice tails of embedded array fields

❌ Don’t

  • Confuse $lastN with $last (array vs single value)
  • Skip $sort and expect consistent “latest N” results
  • Use $lastN when $bottomN in-group ranking is clearer
  • Assume null/missing values are skipped—they are included in the array
  • Deploy on MongoDB versions before 5.2 without a fallback pipeline

Key Takeaways

Knowledge Unlocked

Five things to remember about $lastN

Use these points when building last-N lists inside $group.

5
Core concepts
📄 02

input + n

Two required keys.

Syntax
📅 03

$sort first

Define what last means.

Pattern
👤 04

vs $last

List vs single value.

Compare
⬇️ 05

vs $bottomN

Pre-sort vs in-group rank.

Choose

❓ Frequently Asked Questions

$lastN returns an array of the last N input values from each $group bucket—based on the order documents arrive at $group. Use it for the three most recent orders per customer, latest N events, or trailing scores when you control order with $sort.
Inside $group: { lastThree: { $lastN: { input: "$score", n: 3 } } }. Both input and n are required. It also works as an array operator in $project and $addFields to slice the last N elements from an array field.
Yes, whenever order matters. $lastN collects the last N documents as they enter each group—it does not sort for you. Add $sort before $group so last means latest, most recent, or trailing per your rules.
$last returns one value from the final document. $lastN returns an array of up to N values from the last N documents. Use $last for a single trailing field; use $lastN for a list of recent records.
$lastN assumes documents are already ordered (usually via $sort). $bottomN sorts inside $group with sortBy and picks the bottom N. Use $lastN when you sorted upstream; use $bottomN when ranking happens in the accumulator.
$lastN returns all available elements—never more than exist in the group. A group with two documents and n: 3 yields an array of two items.
Did you know?

MongoDB docs note that $lastN and $bottomN can produce similar results—use $lastN when documents are already sorted, and $bottomN when ranking should happen inside $group. $lastN also works as an array expression; $bottomN does not. See the official $lastN docs.

Continue the Accumulators Series

Build last-N arrays with $lastN, then learn $max for peak values across each group.

Next: $max →

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.

5 people found this page helpful