MongoDB 2.4 Fixed Length Arrays & Release Candidate 2

The MongoDB Experimental Plans are updated and running MongoDB 2.4 Release Candidate 2. One of the new features in MongoDB 2.4 is fixed length arrays. It will make schema design a little easier.

Fixed Length Array in MongoDB

With MongoDB 2.4, one of the cool features is atomic fixed length arrays. To use, combine the $push and $slice functionality. Previously, to have fixed length arrays, you would need to run two separate commands: $find and inplace $set of the entire array.

Now, you can create fixed length arrays with the {$push: {"field_name": {$each: ["array_of_elements"], $slice: -4}}}where field_name is the attribute on the document, and slice is the length of the document (always negative or 0). Essentially, the example above will:
- Push to the right side of the array - Keep the 4 elements on the right side of the array An Example

We are going to record the last 5 readings for a river gauge:

> doc = db.gauges.insert({_id: ObjectId("513cc4c663c0a2303e1ec093"), name: "Niagra River"})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {lastest_gauge_readings: {$each: [{cubic_meter_second: 5796, at: new Date()}], $slice: -5}}})
> db.gauges.find()[0]
{
  "_id" : ObjectId("513cc4c663c0a2303e1ec093"),
  "lastest_gauge_readings" : [
    {
      "cubic_meter_second" : 5796,
      "at" : ISODate("2013-03-10T17:46:00.810Z")
    }
  ],
  "name" : "Niagra River"
}

As you can see the $push syntax has changed. It is using a more verbose, more functional syntax. In the example above, with $push, we are adding each element in the $each array to the right side of the index. Then, with $slice, we are keeping the 5 right most elements. Below, we will run the following 5 more times with random values:

> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {lastest_gauge_readings: {$each: [{cubic_meter_second: 5800, at: new Date()}], $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {lastest_gauge_readings: {$each: [{cubic_meter_second: 5960, at: new Date()}], $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {lastest_gauge_readings: {$each: [{cubic_meter_second: 6000, at: new Date()}], $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {lastest_gauge_readings: {$each: [{cubic_meter_second: 6200, at: new Date()}], $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {lastest_gauge_readings: {$each: [{cubic_meter_second: 6300, at: new Date()}], $slice: -5}}})
> db.gauges.find()[0]
{
  "_id" : ObjectId("513cc4c663c0a2303e1ec093"),
  "lastest_gauge_readings" : [
    {
      "cubic_meter_second" : 5800,
      "at" : ISODate("2013-03-10T17:48:31.508Z")
    },
    {
      "cubic_meter_second" : 5960,
      "at" : ISODate("2013-03-10T17:48:37.268Z")
    },
    {
      "cubic_meter_second" : 6000,
      "at" : ISODate("2013-03-10T17:48:42.308Z")
    },
    {
      "cubic_meter_second" : 6200,
      "at" : ISODate("2013-03-10T17:48:45.917Z")
    },
    {
      "cubic_meter_second" : 6300,
      "at" : ISODate("2013-03-10T17:48:49.247Z")
    }
  ],
  "name" : "Niagra River"
}

The $slice operator keeps n-right most elements of the array.

Sorted Fixed Length Arrays in MongoDB

If you like Redis’s zscore functionality, and want to bring it into MongoDB. The latest MongoDB 2.4 is bringing the sorted arrays functionality to MongoDB with the added $push features.

Common scenarios for this are like: - Content management system - related posts, top n refererring products - E-commerce storefront - top n referring products - Social Aggregation - top n retweeted status updates Sorted arrays are a nice way to cache values instead of using a sort on another query. Try to use these instead of sort queries against entire collections. We will continue to use our river gauge example on the Niagra River:

> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {highest_gauge_readings: {$each: [{cubic_meter_second: 5796, at: new Date()}], $sort: {cubic_meter_second: 1}, $slice: -5}}})

Above, we are using $sort to specify a key(s) to sort from, then using $sliceto keep the last 5. We will run 5 more pushes to the document:

> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {highest_gauge_readings: {$each: [{cubic_meter_second: 5796, at: new Date()}], $sort: {cubic_meter_second: 1}, $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {highest_gauge_readings: {$each: [{cubic_meter_second: 5900, at: new Date()}], $sort: {cubic_meter_second: 1}, $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {highest_gauge_readings: {$each: [{cubic_meter_second: 5600, at: new Date()}], $sort: {cubic_meter_second: 1}, $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {highest_gauge_readings: {$each: [{cubic_meter_second: 2500, at: new Date()}], $sort: {cubic_meter_second: 1}, $slice: -5}}})
> db.gauges.update({ _id: ObjectId("513cc4c663c0a2303e1ec093")}, {$push: {highest_gauge_readings: {$each: [{cubic_meter_second: 7500, at: new Date()}], $sort: {cubic_meter_second: 1}, $slice: -5}}})
> db.gauges.find()[0]
{
  "_id" : ObjectId("513cc4c663c0a2303e1ec093"),
  "highest_gauge_readings" : [
    {
      "cubic_meter_second" : 2500,
      "at" : ISODate("2013-03-10T17:59:59.315Z")
    },
    {
      "cubic_meter_second" : 5600,
      "at" : ISODate("2013-03-10T17:59:51.695Z")
    },
    {
      "cubic_meter_second" : 5796,
      "at" : ISODate("2013-03-10T17:59:11.096Z")
    },
    {
      "cubic_meter_second" : 5900,
      "at" : ISODate("2013-03-10T17:59:46.215Z")
    },
    {
      "cubic_meter_second" : 7500,
      "at" : ISODate("2013-03-10T18:00:05.345Z")
    }
  ],
  "name" : "Niagra River"
}

Other Features

If you are looking for a comprehensive list of MongoDB features, take a look at MongoDB 2.4 Release Notes. To begin using a Sandbox database with MongoHQ, Sign Up and create a Sandbox database. To upgrade any paid databases to 2.4.0-rc2, please send an email to support@mongohq.com with your database name.