Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding find in Node/Mongo

I am trying to learn node. Consider this code (based on official MongoDB Node.js driver)

  // Retrieve all the documents in the collection
  collection.find().toArray(function(err, documents) {
    assert.equal(1, documents.length);
    assert.deepEqual([1, 2, 3], documents[0].b);

    db.close();
  });

I have two questions:

  • is find synchronous or asynchronous?
  • If it is asynchronous, the .toArray function call is confusing me, because normally I would expect something along the lines of

    collection.find(function(err, results){});
    

Specifically I am interested what mechanism allows you to call a .toArray on result of asynchronous function? Because asynchronous functions as I get it rarely return something (I think except promises), rather invoke callbacks passed to them. Can someone clarify this situation with find and .toArray?


For example in the accepted answer of this question: How to get a callback on MongoDB collection.find(), you can see author calls find the way I envisioned, and received cursor in callback function. That is fine with me, that is how I expected it to work. But chaining result of asynchronous call find (if it is asynch?), with toArray a bit confuses me.

My speculation is find returns a handle kind of thing, the data at this point hasn't been loaded from DB, only when you call toArray the actual data arrives. Am I right?

like image 328
Giorgi Moniava Avatar asked Feb 17 '17 18:02

Giorgi Moniava


1 Answers

I concede you, this case is a bit weird. Here is for the v2.2 of mongodb-native.

First of all, find has two different usages. You can either give a callback function or not. But in any case, it returns synchronously an object. More precisely it's a cursor. We could expect a asynchronous mechanism when passing a callback but not here.

collection.find({ }, function (err, cursor) {
  assert(!err);
});
console.log('This happens after collection.find({ }, callback)');

OR

const cursor = collection.find({});
console.log('Also happening after');

On the other hand, toArray is an asynchronous function and has also two different usages. This time, the returned object is different depending on the arguments.

Are equivalent:

cursor.toArray(function (err, documents) {
  assert.equal(1, documents.length);
});

AND

cursor.toArray()
  .then(documents => {
    assert.equal(1, documents.length);
  });

In the first call, toArray returns undefined whereas in the second, it returns a Promise.

like image 101
L. Meyer Avatar answered Nov 13 '22 16:11

L. Meyer