Cursors: MongoDB Tutorial - SASTRA University
Document Details

Uploaded by AdvancedSanctuary5639
SASTRA University
2025
Tags
Summary
These slides explain the concept of cursors in MongoDB, which allow iteration over query results. It discusses lazy loading, retrieving data in batches, and optimizing memory usage. The presentation also covers limits, skips, sorts, finding random documents, and techniques for managing consistent results.
Full Transcript
CURSORS 04/24/25 02:36 AM 1 Cursors In MongoDB, a cursor is an object that allows you to iterate over the results of a query. The database returns results from find() using a cursor. When you run a find() operation or a...
CURSORS 04/24/25 02:36 AM 1 Cursors In MongoDB, a cursor is an object that allows you to iterate over the results of a query. The database returns results from find() using a cursor. When you run a find() operation or any other query that returns multiple documents, MongoDB doesn’t just give you all the results at once—it gives you a cursor that points to those results. Thursday, April 24, 2025 2 WHY CURSORS?? It enables lazy loading, which means MongoDB fetches documents as needed, not all at once—great for performance and memory usage. Cursors retrieve data in batches, not all at once Avoids memory leaks and lets you handle long operations safely 04/24/25 02:36 AM 3 Cursors To create a cursor with the shell put some documents into a collection do a query on them assign the results to a local variable (variables defined with "var" are local). We Create a very simple collection and query it, storing the results in the cursor variable: > for(i=0; i var cursor = db.collection.find(); Thursday, April 24, 2025 4 Cursors The advantage of doing this is that you can look at one result at a time. If you store the results in a global variable or no variable at all the MongoDB shell will automatically iterate through Display the first couple of documents. Thursday, April 24, 2025 5 Cursors To iterate through the results use the next method on the cursor. You can use hasNext to check whether there is another result. A typical loop through results looks like the following: > while (cursor.hasNext()) {... obj = cursor.next();... // do stuff... } cursor.hasNext() checks that the next result exists, and cursor.next() fetches it. Thursday, April 24, 2025 6 Limits, Skips, and Sorts The most common query options are limiting the number of results returned, skipping a number of results, and sorting. All these options must be added before a query is sent to the database. To set a limit, chain the limit function onto your call to find. For example, to only return three results, use this: > db.c.find().limit(3) If there are fewer than three documents matching your query in the collection only the number of matching documents will be returned; limit sets an upper limit, not a lower limit. Thursday, April 24, 2025 7 Limits, Skips, and Sorts skip works similarly to limit: > db.c.find().skip(3) This will skip the first three matching documents and return the rest of the matches. If there are fewer than three documents in your collection, it will not return any documents. Thursday, April 24, 2025 8 Limits, Skips, and Sorts sort takes an object: a set of key/value pairs where the keys are key names and the values are the sort directions. Sort direction can be 1 (ascending) or −1 (descending). If multiple keys are given the results will be sorted in that order. For instance, to sort the results by "username" ascending and "age" descending, we do the following: > db.c.find().sort({username : 1, age : -1}) Thursday, April 24, 2025 9 Limits, Skips, and Sorts These three methods can be combined. This is often handy for pagination. For example, suppose that you are running an online store and someone searches for mp3. If you want 50 results per page sorted by price from high to low you can do the following: > db.stock.find({"desc" : "mp3"}).limit(50).sort({"price" : -1}) Thursday, April 24, 2025 10 Limits, Skips, and Sorts If that person clicks Next Page to see more results you can simply add a skip to the query which will skip over the first 50 matches (which the user already saw on page 1): > db.stock.find({"desc" : "mp3"}).limit(50).skip(50).sort({"price" : - 1}) Thursday, April 24, 2025 11 Finding a random document Thursday, April 24, 2025 12 Finding a random document One common problem is how to get a random document from a collection. The naive (and slow) solution is to count the number of documents then do a find skipping a random number of documents between 0 and the size of the collection: > // do not use > var total = db.foo.count() > var random = Math.floor(Math.random()*total) db.foo.find().skip(random).limit(1) highly inefficient to get a random element Thursday, April 24, 2025 13 Finding a random document Efficient Solution is to add an extra random key to each document when it is inserted. if we’re using the shell, use the Math.random() function (which creates a random number between 0 and 1): > db.people.insert({"name" : "joe", "random" : Math.random()}) > db.people.insert({"name" : "john", "random" : Math.random()}) > db.people.insert({"name" : "jim", "random" : Math.random()}) Thursday, April 24, 2025 14 Finding a random document To find a random document from the collection Calculate a random number use that as query criteria > var random = Math.random() result = db.foo.findOne({"random" : {"$gt" : random}}) > if (result == null) {... result = db.foo.findOne({"random" : {"$lt" : random}})... } Thursday, April 24, 2025 15 Getting Consistent Results Thursday, April 24, 2025 16. No documents are skipped or duplicated The data doesn’t change midway through your operation You should get a "stable snapshot" of the data as it was at the start of your read. The solution to this problem is to snapshot your query. For example, instead of db.foo.find(): > db.foo.find().snapshot() Prevent MongoDB from returning the same document more than once if the collection was being modified during the query. Ensure that the query results were not affected by index changes or document movement 04/24/25 02:36 AM 17 Immortal Cursors Thursday, April 24, 2025 18 Immortal Cursors There are two sides to a cursor: the client-facing cursor the database cursor that the client-side one represents On the server side, a cursor takes up memory and resources. Once a cursor runs out of results or the client sends a message telling it to die, the database can free the resources it was using. Freeing these resources lets the database use them for other things we want to make sure that cursors can be freed quickly Thursday, April 24, 2025 19 An immortal cursor is a cursor that does not expire automatically after a period of inactivity. Even if the user hasn’t iterated through all the results the cursor is still in scope after 10 minutes of inactivity a database cursor will automatically “die.” > const cursor = db.myCollection.find().noCursorTimeout(); Since this cursor won’t time out, you should close it manually when you're done. > cursor.close(); 04/24/25 02:36 AM 20