Sambhav Sharma
Sambhav Sharma

Reputation: 5860

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.

Upvotes: 22

Views: 49761

Answers (2)

Jeff Widman
Jeff Widman

Reputation: 23492

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.

Upvotes: 45

Sammaye
Sammaye

Reputation: 43884

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.

Upvotes: 22

Related Questions