Ticket: Projection - Cursor id already in use

Hello,

In the Ticket: Projection lab, the use of cursor.next() is not used, and the cursor.toArray() method is used to return the results of the movies.find().

So, I thought to to console.log(cursor.toArray()) from within the getMoviesByCountry, just after the find.movies is executed. However this error popped up.

With this piece of code

So I am intrigued as to the meaning of this message? Since my console.log(cursor) returns something, and I thought to look inside cursor at the data, that is being sent back, from within the function getMoviesByCountry.

Is toArray() doing more than just parsing an array?

Cheers.

The method cursor.toArray() consumes the result set. If you want to console.log() you must use a temporary variable to hold the result of toArray(). Then you console.log() and return that variable.

1 Like

Hi @NeilM, :wave:

No, the toArray() method returns an array that contains all the documents from a cursor. The method iterates completely the cursor, loading all the documents into RAM and exhausting the cursor.

So you might want to update your function as:

const resultsArray = await cursor.toArray()
console.log(resultsArray)

In case you have any doubts, please feel free to reach out to us.

Thanks and Regards.
Sourabh Bagrecha,
Curriculum Services Engineer

1 Like

I love that word consume :slight_smile:

Thank you for that, I had a feeling it was something of that nature, but I have learnt not to assume anything.

So true. I think the same. Enjoy.

It looks like there is a rewind() method that can be used.

See Cursor() — MongoDB Node.JS Driver 1.4.9 documentation

Yes, I noticed that method in the docs, once I understood what was happening based upon your comment.

I tried the a search for reset, and those clever people in documentation had used that word reset along side rewind method :+1:

Thank for the example.

So, in your example, I notice that you use the await in this line, which I get: -

const resultsArray = await cursor.toArray()

However lower down, outside of the try block is the: -

return cursor.toArray()

Without the await, I appreciate that this is showing a lack of my understanding, towards async/await.

I am certainly getting value out of the Ticket: Projection lab :slight_smile:

Outside the try block you use

return resultsArray

That is what I meant by

Okay. I suppose my question is, why isn’t the await necessary outside of the try block when the return is executed, what has changed?

Hi @NeilM, :wave:
That’s because whenever the function getMoviesByCountry will be called from any other function/file getMoviesByCountry will always return a Promise.
So if you want the value after resolving the promise you need to call it in the following manner:

// From some other file/function
const value = await getMoviesByCountry(["India"])

I hope it helps.

In case you have any doubts, please feel free to reach out to us.

Thanks and Regards.
Sourabh Bagrecha,
Curriculum Services Engineer

@Sourabh_Bagrecha

It seems like I didn’t give you the whole piece of code I was looking for an explanation on. It is a slight expansion of the getMoviesByCountry function. However, what you said makes sense.

static async getMoviesByCountry(countries) {

let cursor
try {
  cursor = await movies.find(     // 1.
    {countries: {$in: countries}},
    {projection: {title: 1}}
  )

  const cursor2 = await cursor.toArray();   // 2.
  console.log(cursor2);

} catch (e) {
  console.error(`Unable to issue find command, ${e}`)
  return []
}

return cursor.toArray() // Why does this not need an await? // 3.

}

So, I phoned a friend (get it :wink: ) and he gave me the following comment.

  1. The first, because you are hitting the database

  2. The second because if you didn’t console.log may display nothing

  3. There isn’t an await on the third because the call to this method would have an await.

Which given your comment:-

// From some other file/function
const value = await getMoviesByCountry(["India"])

Makes complete sense now, I do feel happier.

2 Likes