Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternatives to MongoDB cursor.toArray() in node.js

I am currently using MongoDB cursor's toArray() function to convert the database results into an array:

run = true;
count = 0;
var start = process.hrtime();
db.collection.find({}, {limit: 2000}).toArray(function(err, docs){
  var diff = process.hrtime(start);
  run = false;
  socket.emit('result', {
    result: docs,
    time: diff[0] * 1000 + diff[1] / 1000000,
    ticks: count
  });
  if(err) console.log(err);
});

This operation takes about 7ms on my computer. If I remove the .toArray() function then the operation takes about 0.15ms. Of course this won't work because I need to forward the data, but I'm wondering what the function is doing since it takes so long? Each document in the database simply consists of 4 numbers.

In the end I'm hoping to run this on a much smaller processor, like a Raspberry Pi, and here the operation where it fetches 500 documents from the database and converts it to an array takes about 230ms. That seems like a lot to me. Or am I just expecting too much?

Are there any alternative ways to get data from the database without using toArray()?

Another thing that I noticed is that the entire Node application slows remarkably down while getting the database results. I created a simple interval function that should increment the count value every 1 ms:

setInterval(function(){
  if(run) count++;
}, 1);

I would then expect the count value to be almost the same as the time, but for a time of 16 ms on my computer the count value was 3 or 4. On the Raspberry Pi the count value was never incremented. What is taking so much CPU usage? The monitor told me that my computer was using 27% CPU and the Raspberry Pi was using 92% CPU and 11% RAM, when asked to run the database query repeatedly.

I know that was a lot of questions. Any help or explanations are much appreciated. I'm still new to Node and MongoDB.

like image 328
KMK Avatar asked Apr 16 '15 12:04

KMK


People also ask

Why we use toArray in MongoDB?

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.

Which method returns a cursor in MongoDB?

In MongoDB, the find() method return the cursor, now to access the document we need to iterate the cursor.

What is toArray method in Javascript?

The toArray() method returns the elements matched by the jQuery selector as an array.

How do I search in MongoDB?

Find() Method. In MongoDB, find() method is used to select documents in a collection and return a cursor to the selected documents. Cursor means a pointer that points to a document, when we use find() method it returns a pointer on the selected documents and returns one by one.


1 Answers

db.collection.find() returns a cursor, not results, and opening a cursor is pretty fast.

Once you start reading the cursor (using .toArray() or by traversing it using .each() or .next()), the actual documents are being transferred from the database to your client. That operation is taking up most of the time.

I doubt that using .each()/.next() (instead of .toArray(), which—under the hood—uses one of those two) will improve the performance much, but you could always try (who knows). Since .toArray() will read everything in memory, it may be worthwhile, although it doesn't sound like your data set is that large.

I really think that MongoDB on Raspberry Pi (esp a Model 1) is not going to work well. If you don't depend on the MongoDB query features too much, you should consider using an alternative data store. Perhaps even an in-memory storage (500 documents times 4 numbers doesn't sound like lots of RAM is required).

like image 133
robertklep Avatar answered Sep 28 '22 02:09

robertklep