admin管理员组

文章数量:1391955

In MongoDB, does .find({...}).limit(#) really limit the number of queries?

I mean, when you do db.collection.find(condition), doesn't it already waste putational power to query all the results that match the given condition? If so, then does adding .limit() after it just strip off the unneeded elements from the query results?

Thanks a lot for clarifying this up!

In MongoDB, does .find({...}).limit(#) really limit the number of queries?

I mean, when you do db.collection.find(condition), doesn't it already waste putational power to query all the results that match the given condition? If so, then does adding .limit() after it just strip off the unneeded elements from the query results?

Thanks a lot for clarifying this up!

Share Improve this question edited Sep 22, 2017 at 17:57 CommunityBot 11 silver badge asked Jul 25, 2014 at 6:34 MariaMaria 3,5357 gold badges35 silver badges49 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

db.collection.find returns a cursor, not an array of results or similar. From the documentation:

When the find() method “returns documents,” the method is actually returning a cursor to the documents.

The documents are actually located when you iterate the cursor. So calling .limit tells the cursor when to say it's done iterating.

More about cursors here: http://docs.mongodb/manual/core/cursors/#read-operations-cursors

limit() is not used for post filtering of data. You can figure out this using explain(). For example, I have fired 2 queries 1)db.album.find().explain() 2) db.album.find().limit(5).explain(); here is resultant:

        > db.album.find().explain()
       {
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 1000,
        "nscannedObjects" : 1000,
        "nscanned" : 1000,
        "nscannedObjectsAllPlans" : 1000,
        "nscannedAllPlans" : 1000,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 54,
        "nChunkSkips" : 0,
        "millis" : 12,
        "server" : "delbsinha25125:27017",
       "filterSet" : false
      }

      > db.album.find().limit(5).explain()
        {
         "cursor" : "BasicCursor",
         "isMultiKey" : false,
         "n" : 5,
         "nscannedObjects" : 5,
         "nscanned" : 5,
         "nscannedObjectsAllPlans" : 5,
         "nscannedAllPlans" : 5,
         "scanAndOrder" : false,
         "indexOnly" : false,
         "nYields" : 0,
         "nChunkSkips" : 0,
         "millis" : 0,
          "server" : "delbsinha25125:27017",
         "filterSet" : false
      }

As you can see from the above execution plan, the one with limit has scanned only 5 objects.

>

So I tried to answer this question about 5 days ago but then found some interesting things that I had to actually investigate.

Limit is applied after sort and find, however, not before iteration of those results within the mongod (MongoDB) server itself, as such this means that if done right you can save a lot of putational power using limit. @Bipul's answer is a perfect eample of this but it doesn't go as far as to show the true limitations of what MongoDB can achieve here.

It should be noted that if you are using the latest version of MongoDB there is actually a bug with limit which causes etra entries to be scanned: https://jira.mongodb/browse/SERVER-14712 which was one of the things I actually found while attempting to answer this question.

It should be noted that the bug mentioned above only effects inde usage with limit.

Now considering @Bipuls answer without inde usage there is actually two sides to this story, one being what he has shown but the other also being if you add a sort:

> db.rooms.find().sort({d:1}).limit(2).explain()
{
        "clauses" : [
                {
                        "cursor" : "BasicCursor",
                        "isMultiKey" : false,
                        "n" : 2,
                        "nscannedObjects" : 5,
                        "nscanned" : 5,
                        "scanAndOrder" : true,
                        "indexOnly" : false,
                        "nChunkSkips" : 0
                },
                {
                        "cursor" : "BasicCursor",
                        "isMultiKey" : false,
                        "n" : 0,
                        "nscannedObjects" : 0,
                        "nscanned" : 0,
                        "scanAndOrder" : true,
                        "indexOnly" : false,
                        "nChunkSkips" : 0
                }
        ],
        "cursor" : "QueryOptimizerCursor",
        "n" : 2,
        "nscannedObjects" : 5,
        "nscanned" : 5,
        "nscannedObjectsAllPlans" : 5,
        "nscannedAllPlans" : 5,
        "scanAndOrder" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "server" : "ubuntu:27017",
        "filterSet" : false
}

The size of the collection being 5, you can see the limit has been applied after sort as such it shows that the collection had to be fully scanned and since this query has no inde it would have been a full inde scan and your putational saving will be nothing more than "by the looks of it".

Now if you add an inde this is different, it can actually use the order of the inde to stop a full scan and load only as far as your limit goes, however, due to the bug above it will always scan one more than needed, but that is an inde scan, not an actual document being loaded (depending on whether your queries find() is covered or not).

So to sum up, limit, when used correctly, can stop MongoDB from having to load ecessive documents, not only saving your working set but also your IO bandwidth. If you can use limit correctly with the inde etc then I would definitely remend it.

本文标签: javascriptMongoDB truth behind find()limit()Stack Overflow