This is an interesting question.
It works as most ECMAScript implementations actually do preserve the key order (e.g. V8 which is used by Node). However, the official Node MongoDB driver does not encourage its use, instead it offers two different notations:
Sorting can be acieved with option parameter sort which takes an array
of sort preferences
{ "sort": [['field1','asc'], ['field2','desc']] }
With single ascending field the array can be replaced with the name of the field.
{ "sort": "name" }
The Mongoose documentation does not mention anything regarding key order (at least not that I know of). But it also offers two different approaches to sorting:
// sort by "field" ascending and "test" descending
query.sort({ field: 'asc', test: -1 });
// equivalent
query.sort('field -test');
Indeed it seems that the Mongoose sort functionality was based on wrong (but currently valid) assumption. It is probably best if you use the string notation when sorting with multiple keys.
Sorting with the object notation works properly when using MongoDB directly (e.g. in the MongoDB shell) as it does not use pure JSON but extended JSON.
Also see this very related question: How can you specify the order of properties in a javascript object for a MongoDB index in node.js?
There is also a Mongoose issue about this:
Yep, that's an unfortunate dilemma for both mongoose and the mongodb
driver. ECMAScript says that keys are not ordered, but they are
actually ordered in V8 (except for numeric keys, which is a nasty edge
case), and likely will continue to be ordered in V8 for the
foreseeable future. You can use the [['field1', 'asc']] syntax or the
mongoose-specific 'field1 -field2' syntax or the ES2015 Map class
(which guarantees insertion order for keys) if you're concerned with
key order.
So when using Mongoose, either use the string notation or the newly added support for ES2015 Maps which are guaranteed to be ordered by insertion order.