Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is order of properties maintained for sort in mongodb?

As per the answer to the question, the order of properties on an object is not guaranteed. Then how does the sort function work flawlessly in MongoDB when we pass multiple sort fields as an object?

db.users.find({}).sort({firstName: 1, age:-1}).exec(callback);

How does mongodb know that it first has to sort by firstName and then by age? Is it working on a wrong assumption?

like image 564
sidgate Avatar asked Jan 25 '17 11:01

sidgate


People also ask

How does sort work in MongoDB?

This operation sorts the documents in the users collection, in descending order according by the age field and then in ascending order according to the value in the posts field. When comparing values of different BSON types, MongoDB uses the following comparison order, from lowest to highest: MinKey (internal type)

What is MongoDB default sort order?

by default mongo appears to return documents in insertion order. MongoDB returns documents in natural order when no sort order is specified.

How does MongoDB order data?

MongoDB can perform sort operations on a single-field index in ascending or descending order. In compound indexes, the sort order determines whether the index can be sorted. The sort keys must be listed in the same order as defined in the index.


2 Answers

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.

like image 161
str Avatar answered Oct 16 '22 23:10

str


In your example you use indexes for sort operations in MongoDB and if you sort with multiple fields you create a compound index to support sorting on multiple fields. As you did when you give indexes, the query planner obtain the sort order from your indexes (your example's order: firstname, lastname) and it will sort by your order. In the other example it is a javascript object. Javascript doesn't warrant sorting.

like image 42
utaco Avatar answered Oct 16 '22 21:10

utaco