Sling Academy
Home/MongoDB/MongoDB: Exploring $first, $firstN, $last, and $lastN operators

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

Last updated: February 03, 2024

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.

Next Article: MongoDB: Using $mergeObjects to merge multiple documents into one

Previous Article: MongoDB: Check if a field is number with $isNumber operator

Series: MongoDB Tutorials

MongoDB

You May Also Like

  • MongoDB: How to combine data from 2 collections into one
  • Hashed Indexes in MongoDB: A Practical Guide
  • Partitioning and Sharding in MongoDB: A Practical Guide (with Examples)
  • Geospatial Indexes in MongoDB: How to Speed Up Geospatial Queries
  • Understanding Partial Indexes in MongoDB
  • Exploring Sparse Indexes in MongoDB (with Examples)
  • Using Wildcard Indexes in MongoDB: An In-Depth Guide
  • Matching binary values in MongoDB: A practical guide (with examples)
  • Understanding $slice operator in MongoDB (with examples)
  • Caching in MongoDB: A practical guide (with examples)
  • CannotReuseObject Error: Attempted illegal reuse of a Mongo object in the same process space
  • How to perform cascade deletion in MongoDB (with examples)
  • MongoDB: Using $not and $nor operators to negate a query
  • MongoDB: Find SUM/MIN/MAX/AVG of each group in a collection
  • References (Manual Linking) in MongoDB: A Developer’s Guide (with Examples)
  • MongoDB: How to see all fields in a collection (with examples)
  • Type checking in MongoDB: A practical guide (with examples)
  • How to query an array of subdocuments in MongoDB (with examples)
  • MongoDB: How to compare 2 documents (with examples)