MongoDB: Exploring $first, $firstN, $last, and $lastN operators

Updated: February 3, 2024 By: Guest Contributor Post a comment

Introduction

MongoDB is a powerful NoSQL database that offers a wide range of features for manipulating and querying data. Among its arsenal of operators, the aggregation framework provides some particularly useful ones such as $first, $last, $firstN, and $lastN. These operators are essential when dealing with ordered data, and they allow developers to easily extract specific elements from arrays. In this article, we’ll explore each of these operators, understand how they work, and go through multiple examples from the most basic usage to more advanced scenarios.

Understanding $first and $last

Let’s start by discussing the $first and $last operators. As their names suggest, they are used within an aggregation pipeline to return the first and the last element of an array, respectively. It’s important to note that these operators return values only when documents are passed in a defined order, usually by a $sort pipeline stage.

Here is a simple example:

db.collection.aggregate([
  { $sort: { score: 1 } },
  { $group: { _id: '$subject', firstScore: { $first: '$score' }, lastScore: { $last: '$score' }}}
])

This will return a document for each subject, with the lowest and highest scores assuming the score field is numeric:

[{ "_id": "Math", "firstScore": 65, "lastScore": 98 },
 { "_id": "Science", "firstScore": 70, "lastScore": 93 }]

Diving into $firstN and $lastN

Introduced in MongoDB 5.2, the $firstN and $lastN operators extend the capabilities of $first and $last. Instead of returning just one element, they return the first N or last N elements of an array. Here’s how to use them:

Example of $firstN:

db.collection.aggregate([
  { $sort: { score: 1 } },
  { $group: { _id: '$subject', topThreeScores: { $firstN: {n: 3, input: '$scores'} }}}
])

Output:

[{ "_id": "Math", "topThreeScores": [65, 67, 72] },
 { "_id": "Science", "topThreeScores": [70, 74, 76] }]

Example of $lastN:

db.collection.aggregate([
  { $sort: { score: -1 } },
  { $group: { _id: '$subject', bottomThreeScores: { $lastN: {n: 3, input: '$scores'} }}}
])

Output:

[{ "_id": "Math", "bottomThreeScores": [48, 52, 60] },
 { "_id": "Science", "bottomThreeScores": [55, 60, 63] }]

Advanced Usage Patterns

Now that we have covered the basics, let’s delve into more complex scenarios where these operators can be especially helpful.

Combining $firstN with $slice:

db.collection.aggregate([
  { $sort: { date: 1 } },
  { $group: { _id: '$userId', recentActions: { $firstN: {n: 5, input: { $slice: ['$actions', -5] }} }}}
])

This aggregation pipeline retrieves the five most recent actions for each user, even when the actions array in the documents are not stored in chronological order.

Error Handling

While working with these operators, you may encounter scenarios where error handling is important. For instance, using $firstN or $lastN with a n value that exceeds the number of elements in the input array will not result in an error; instead, MongoDB returns as many elements as it can.

Performance Considerations

Performance is a key aspect in designing efficient queries, especially for large collections. You want to make sure to use these operators in a way that leverages indexing, minimizes memory usage, and ensures the overall efficiency of your data pipeline. Also, bear in mind that MongoDB limits the total amount of memory consumed by the pipeline stages, so optimizing your queries is not just a matter of speed but also a requirement for successful execution.

Conclusion

In conclusion, MongoDB’s aggregation pipeline operators $first, $last, $firstN, and $lastN offer robust options for processing and returning values from ordered datasets. Through the concepts and examples shared in this article, you should now have a solid foundation for incorporating these operators into your own MongoDB queries to achieve efficient and precise data extraction. Explore their potential to the fullest to unlock advanced MongoDB query capabilities and optimize your database operations.