39

I am working on a project and I am unsure if there is a difference between the way the find cursor works and the way the findOne cursor works. Is findOne just a wrapper for find().limit(1)? I was looking around for it and maybe someone knows if mongodb has a special method for it or not. I am working with the PHP API for mongodb if that makes a difference.

0

4 Answers 4

37

Based on my own benchmarks, find().limit(1) is orders of magnitude faster than findOne().

There is either an error in the MongoDB documentation or a bug in findOne(). findOne() performs more like find().limit(N) where N is the number of documents the query would return. I figured this out while trying to figure out why my simple queries were so slow!

update: response from a 10gen (MongoDB) engineer:

The two queries you are executing are very different. A find query returns a cursor, this is essentially a no-operation scenario, as no actual data is returned (only the cursor information). If you call findOne, then you are actually returning the data and closing the cursor. The docs should definitely be clearer :-)

Update: Indeed, if the find().limit(1) document is retrieved, the orders of magnitude speed difference seems to disappear. Also, I could not reproduce the major speed difference with the MongoDB JavaScript driver. I originally benchmarked using the MongoDB Java driver.

8
  • 1
    Great find. Important question, though: Do your benchmarks account for the extra operations you'd have to do with find().limit(1) in the course of normal programming (like actually retrieving the data and closing the cursor) that findOne() automatically does for you anyway? Nov 4, 2011 at 6:07
  • @Nick: I think extra operations were covered. I was finding a random document (cookbook.mongodb.org/patterns/random-attribute), getting the document with .next() and removing it from the collection. I didn't manually close any cursors...
    – Leftium
    Nov 4, 2011 at 6:41
  • 2
    @WojonsTech: a quick benchmark in JS shows findOne() is actually faster. Results may vary by driver/platform, though. For example, I could not reproduce the orders of magnitude speed difference in JS that I originally observed with the Java driver.
    – Leftium
    Nov 7, 2011 at 5:24
  • 3
    Leftium, I would edit your answer to stress that when you actually retrieve the document (which you normally would), the two functions are actually identical, just as the documentation states. Right now someone will likely read the bolded line at the beginning of your answer and conclude that if they want to retrieve one document, findOne() is worse than find().limit(1), which is incorrect. Apr 18, 2012 at 15:57
  • 1
    @bigp This is not a valid performance tip, the two methods are identical when actually retrieving the document.
    – JohnnyHK
    Jan 15, 2019 at 13:44
10

findOne() is indeed syntactic sugar for find().limit(1), given that you are actually retrieving the document (as opposed to just returning the cursor with find()).

See Leftium's answer and updates for more detail.

3
  • okay thank you i dont like using synimus functions in my programming would rather put limit one myself just so all my code is easy to track down.
    – WojonsTech
    Nov 3, 2011 at 17:51
  • 1
    Actually in benchmarks findOne() a bit faster than find().limit(1).
    – Vladimir
    Apr 25, 2012 at 9:21
  • @DairT'arg - If you have sources or data to back up this claim, by all means post an answer with the details! From what I've gathered so far, they should be identical as long as you are retrieving the document in both cases. Apr 25, 2012 at 15:50
3

The source code may helps a lot.

It's java but I guess it can help, too.

The findOne(),

DBObject findOne(DBObject o, DBObject fields, DBObject orderBy, ReadPreference readPref,
                 long maxTime, TimeUnit maxTimeUnit) {

    QueryOpBuilder queryOpBuilder = new QueryOpBuilder().addQuery(o).addOrderBy(orderBy)
                                                        .addMaxTimeMS(MILLISECONDS.convert(maxTime, maxTimeUnit));

    if (getDB().getMongo().isMongosConnection()) {
        queryOpBuilder.addReadPreference(readPref);
    }

    Iterator<DBObject> i = find(queryOpBuilder.get(), fields, 0, -1, 0, getOptions(), readPref, getDecoder());

    DBObject obj = (i.hasNext() ? i.next() : null);
    if ( obj != null && ( fields != null && fields.keySet().size() > 0 ) ){
        obj.markAsPartialObject();
    }
    return obj;
}

And here is find()

public DBCursor find( DBObject ref ){
    return new DBCursor( this, ref, null, getReadPreference());
}

As we can see that findOne() calls find() in it self, gets all the DBOject in i and then return the first.

-1

You must check this link ...

http://mongoosejs.com/docs/2.7.x/docs/finding-documents.html

  1. find - option return array []
  2. findOne - option return document {}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.