Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB difference between $orderby and Sort

I want to fetch the latest document, which obviously is a single document, thus findOne should work fine. But findOne here returns the first document inserted. So I have two options now either use $orderBy with findOne or use .sort() function with .limit() in find()

Using $orderBy it would look something like:

db.collection.findOne({$query:{},$orderby:{_id:-1}}) 

And using sort:

db.collection.find().sort({_id:-1}).limit(1).pretty()

Both work fine, I just wanted to know which query should I prefer here? In terms of performance, or does both of them work the same way internally and there is no such difference between the two.

like image 319
Sambhav Sharma Avatar asked Jul 31 '14 11:07

Sambhav Sharma


People also ask

What is the use of sort () in MongoDB?

Using the sort() method will increase the readability of a query, which leads to a better understanding of a given dataset. Not only that, sorted data will be used by developers to write more complex algorithms. (This article is part of our MongoDB Guide.

What is sort key in MongoDB?

If the sort keys correspond to the index keys or an index prefix, MongoDB can use the index to sort the query results. A prefix of a compound index is a subset that consists of one or more keys at the start of the index key pattern. The following query and sort operations use the index prefixes to sort the results.

How do I sort a timestamp in MongoDB?

MongoDB sort by date is used to sort the date field in ascending or descending order, we can sort the date by using the sort method in MongoDB. We can also use the aggregate method to sort the date and timestamp field in MongoDB. We need to pass -1 or 1 value with the date field to sort the data.

How do I sort an array in MongoDB?

To sort the whole array by value, or to sort by array elements that are not documents, identify the input array and specify 1 for an ascending sort or -1 for descending sort in the sortBy parameter.


2 Answers

As of Mongo 3.2, $orderby is deprecated.

The docs explicitly say:

The $orderby operator is deprecated. Use cursor.sort() instead.

Unfortunately, findOne() doesn't support the sort() method, so you'll need to switch to find():

db.collection.find({}).sort({'key': -1}).limit(1)

This will return a cursor, so you'll then need to pull the first result from the cursor.

like image 59
Jeff Widman Avatar answered Sep 21 '22 14:09

Jeff Widman


They are the same and in fact the documentation page for $orderby actually talks mostly about the sort() function that is provided.

These query modifiers that allow you to add sections of a query on without using the functional accessors do exist but there is a bug mixing these two together so I would recommend you pick either the query modifiers or the functional methods and stick to that option.

In attempting to provide example code I have also found out one other thing when I looked at your question again. You provide:

db.collection.findOne({"$query":{},"$orderby":{ "_id": -1 }}) 

But it is good to note that:

db.collection.findOne({}).sort({ "_id":-1})

Actually produces:

2014-07-31T04:59:50.183-0700 TypeError: Object [object Object] has no method 'sort'

and as you can see here by my test data set:

> db.rooms.find()
{ "_id" : ObjectId("53ad206e1d8f2d8351182830"), "id" : 1, "from" : ISODate("2014-06-26T00:00:00Z"), "to" : ISODate("2014-06-28T00:00:00Z") }
{ "_id" : ObjectId("53ad276f1d8f2d8351182831"), "id" : 1, "from" : ISODate("2014-06-24T00:00:00Z"), "to" : ISODate("2014-07-01T00:00:00Z") }
{ "_id" : ObjectId("53ad28ad1d8f2d8351182832"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-06-28T00:00:00Z") }
{ "_id" : ObjectId("53ad28c61d8f2d8351182833"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-07-03T00:00:00Z") }
{ "_id" : ObjectId("53ad29971d8f2d8351182834"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-06-21T00:00:00Z") }

the answer is actually correct:

> db.rooms.findOne({ "$query":{}, "$orderby":{ "_id": -1 }})
{
        "_id" : ObjectId("53ad29971d8f2d8351182834"),
        "id" : 1,
        "from" : ISODate("2014-06-20T00:00:00Z"),
        "to" : ISODate("2014-06-21T00:00:00Z")
}

So it is interesting to note that query modifiers are supported by findOne where as functional accessors are not, which could be a reason to use query modifiers instead.

like image 42
Sammaye Avatar answered Sep 24 '22 14:09

Sammaye