Andrew
Andrew

Reputation: 238907

How to retrieve the last 100 documents with a MongoDB/Moped query?

I am using the Ruby Mongoid gem and trying to create a query to retrieve the last 100 documents from a collection. Rather than using Mongoid, I would like to create the query using the underlying driver (Moped). The Moped documentation only mentions how to retrieve the first 100 records:

session[:my_collection].find.limit(100)

How can I retrieve the last 100?

Upvotes: 0

Views: 1129

Answers (2)

LXSoft
LXSoft

Reputation: 596

I have found a solution, but you will need to sort collection in descending order. If you have a field id or date you would do:

Method .sort({fieldName: 1 or -1})

The 1 will sort ascending (oldest to newest), -1 will sort descending (newest to oldest). This will reverse entries of your collection.

session[:my_collection].find().sort({id:-1})  or
session[:my_collection].find().sort({date:-1})

If your collection contain field id (_id) that identifier have a date embedded, so you can use

session[:my_collection].find().sort({_id:-1})

In accordance with your example using .limit() the complete query will be:

session[:my_collection].find().sort({id:-1}).limit(100);

Upvotes: 1

mu is too short
mu is too short

Reputation: 434735

Technically that query isn't finding the first 100, that's essentially finding 100 random documents because you haven't specified an order. If you want the first then you'd have to say explicitly sort them:

session[:my_collection].find.sort(:some_field => 1).limit(100)

and to reverse the order to find the last 100 with respect to :some_field:

session[:my_collection].find.sort(:some_field => -1).limit(100)
# -----------------------------------------------^^

Of course you have decide what :some_field is going to be so the "first" and "last" make sense for you.

If you want them sorted by :some_field but want to peel off the last 100 then you could reverse them in Ruby:

session[:my_collection].find
                       .sort(:some_field => -1)
                       .limit(100)
                       .reverse

or you could use use count to find out how many there are then skip to offset into the results:

total = session[:my_collection].find.count
session[:my_collection].find
                       .sort(:some_field => 1)
                       .skip(total - 100)

You'd have to check that total >= 100 and adjust the skip argument if it wasn't of course. I suspect that the first solution would be faster but you should benchmark it with your data to see what reality says.

Upvotes: 0

Related Questions