I have an important announcement to make: over the last couple weeks I've been taking over maintaining mongoose, the popular MongoDB/NodeJS ODM. I have some very big shoes to fill, Aaron Heckmann has done an extraordinary job building mongoose into an indispensable part of the NodeJS ecosystem. As an avid user of mongoose over the last two years, I look forward to continuing mongoose's storied tradition of making dealing with data elegant and fun. However, mongoose isn't perfect, and I'm already looking forward to the next major stable release, 4.0.0. Suggestions are most welcome, but please be patient, I'm still trying to catch up on the backlog of issues and pull requests.

On to what's new in 3.8.9

On that note, Mongoose 3.8.9 was (finally) released yesterday. This was primarily a maintenance release, the major priority was to clean up several test failures against the new stable version of the MongoDB server, 2.6.x, without any backward-breaking API changes. I'm proud to say that 3.8.9 should be compatible with MongoDB 2.2.x, 2.4.x, and 2.6.x. In addition, I added improved support for a couple of key MongoDB 2.6 features:

Support for Text Search in MongoDB 2.6.x

As I mentioned in my post on text search, mongoose 3.8.8 didn't quite support text search yet: mongoose prevented you from sorting by text score. This commit, which went into mquery 0.6.0, allows you to use the new $meta operator in sort() calls. Here's an example of how you would use text search with sorting in mongoose:

/* Blog post collection with two documents:
 * { title : 'text search in mongoose' }
 * { title : 'searching in mongoose' }
 * and a text index on the 'title' field */
BlogPost.
  find(
    { $text : { $search : 'text search' } },
    { score : { $meta: "textScore" } }
  ).
  sort({ score : { $meta : 'textScore' } }).
  limit(2).
  exec(function(error, documents) {
    assert.ifError(error);
    assert.equal(2, documents.length);
    assert.equal('text search in mongoose', documents[0].title);
    assert.equal('searching in mongoose', documents[1].title);
    db.close();
    done();
  });

The relevant test case can be found here (there's also test coverage for text search without sorting). Please note that you're responsible for making sure you're running >= MongoDB 2.6.0, running text queries against older versions of MongoDB will not give you the expected behavior. MongoDB's docs about text search can be found here.

Aggregation helper for $out:

As I mentioned in my post about the aggregation framework's $out pipeline stage (which pipes the aggregation output to a collection), mongoose's aggregate() function doesn't prevent you from using $out. However, mongoose also supports syntactic sugar for chaining helper functions onto aggregate() for building an aggregation pipeline:

MyModel.aggregate()
  .group(group.$group)
  .project(project.$project)
  .exec(function (err, res) {
  });

This commit adds a .out() helper function that you can use to add a $out stage to your pipeline. Note that you're responsible for making sure that the .out() function is the last stage of your pipeline, because the MongoDB server will return an error if it isn't. The relevant test case can be found here. Here's how the new helper function looks in action:

var outputCollection = 'my_output_collection';

MyModel.aggregate()
  .group(group.$group)
  .project(project.$project)
  .out(outputCollection)
  .exec(function(error, result) {
  });

A Minor Caveat For 2.6.x Compatibility

There is still one unfortunate edge case remaining in 3.8.9 which only affects MongoDB 2.6.x. MongoDB 2.6.x unfortunately no longer allows empty $set operators to be passed to update() and findAndModify(). This change only affects mongoose in the case where you set the upsert flag to true. This commit attempts to mitigate this API inconsistency, but there is still one case where you will get an error on MongoDB 2.6.x but not in 2.4.x: if the query passed to your findAndModify() only includes an _id field. For example,

MyModel.findOneAndUpdate(
  { _id: 'MY_ID' },
  {},
  { upsert: true },
  function(error, document) {
  });

Will return a server error on MongoDB 2.6.1 but not 2.4.10. Right now, there is no good way to handle this case in both 2.4 and 2.6 without either doing an if-statement on the version or breaking the existing API. You can track the progress of this issue on Github.

Conclusion

Hope y'all are as excited about mongoose's future as I am. There's lots of exciting ideas that I'm looking forward to getting into mongoose 4.0. You're more than welcome to add suggestions for new features or behavior changes on Github issues. I'm looking forward to seeing what y'all can come up with for improving mongoose and what y'all will be able to do with future versions.

Found a typo or error? Open up a pull request! This post is available as markdown on Github
comments powered by Disqus