To play around with cursors, I'll use my movie data database and there, remember we had movies where
if I counted, we have 240 documents. By the way count is already one method we can chain on a cursor because
find gives us a cursor,
so whatever we call here is called on the cursor and count simply has a look at the cursor and determines
how many elements can I get from the cursor,
so that's important.
How does this work technically?
Well on the database side, the query will already have ran and therefore information like this is already
loaded into memory and ready to be delivered to us,
so it's not like that if we now cycle through all the elements, we have to manually read them from a
file, they have been loaded efficiently into memory there already.
So now with this, we can of course execute find with the pretty command and the pretty command is really
just the utility command,
we could also output it like this and get a bunch of documents, to be precise 20.
That's just something the shell does for us and the shell also gives us this shortcut to type it to
get the next 20
and we can do this until this is exhausted, the it command will not be available to you when working with
a driver and there, you will indeed work differently with the cursor.
So on find, then in most drivers, you will have some next method you can call. If I call next here, I get
back exactly one document,
hence you also see no type it to see more at the bottom.
I get back exactly one document because next gives me the next document,
the cool thing is now that I called next,
I got back Glee with the id 8,
if I call it again, I get back the next document in line.
However, this again is glee because this query is now basically executed from scratch.
This is different
if I store my data cursor, however you want to name it, you could name it just cursor in a variable or constant
and since the shell uses javascript, I can use javascript syntax to create such a variable here.
So here I can use db.movies find without any condition to find all
and now I can use my data cursor here with next to get the first element which again is Glee with the
id 8
and if I now use that same cursor again with next, I get a different element with the id 7, Homeland
and If I type this again, I get yet another document ID 5,
True Detective.
So this is the cursor doing its work.
The cursor also has other methods, so that was our data cursor here, if I execute it like this, it gives
me 20 documents again
but if I use that data cursor, I also can specify forEach method.
Now again this will vary on the driver you are using, for javascript,
you can use it like this, forEach takes a function that will be executed for every element that can
be loaded through the cursor
and now in there, we therefore get the document.
Now this is just a special function syntax provided by javascript
with that arrow here, here is the input to the function which is given to us by the forEach method
and here is then our function body where we write what we want to do
and then we got print json which is a method provided by the shell to output the document.
And what this would do now is it would cycle through all the documents that are in the cursor
and that by the way are only documents we didn't look at yet,
so the two we fetched via next and the 20 we fetched via just typing the cursor name will be
excluded
and now we will cycle through the remaining documents which we haven't fetched yet and it will fetch
them from the database and output them here as you see.
And that is why you see no type it
to see more at the bottom because we did now fetch all documents in the database simply with forEach.
So this another way of using the cursor to go through all the documents
and of course inside of the function you execute on every document,
you could also have some condition, an if check to for example see if you want to output that document,
though just be aware, if you use an if check to filter out a document,
it would be more efficient to filter that already as a filter in the find method and not fetch it from
the database because here, you're only filtering on the client side,
that of course is not as efficient as filtering on the mongodb server side but you can run
any code you want on all the documents or as I mentioned, use next to only fetch one at a time.
By the way, if I execute next now, I get an error because the cursor has been exhausted.
You can check for that manually with the hasNext field here,
function excuse me, hasNext function,
this is false
and this indicates there is no data to be fetched.
If I recreate my cursor by again reassigning it and this was a constant, so I'm not allowed to do that,
so let's create a new one, just named cursor.
So now I'm creating a new cursor based on the same query but the shell doesn't know that.
So I got a new cursor, now on that cursor if I call hasNext, I get
true and hence I can safely execute next.
Now with cursors, you can do a couple of other things too,
there are other methods you can execute
and again this is something which you can always of course find in the official docs. There, under
mongodb crud operations, query documents, you want to have a look at iterate a cursor in the mongo shell to
learn more about using that cursor and different ways of iterating through it
and we'll also have a look at how to use a cursor in the environment of our mongodb drivers.
It is important for you to understand what a cursor is and why it exists though and I hope this became
clearer.