0

UPDATE

After some testing around, this works:

Url.count({}, (err, data) => {
    console.log(data); // prints correct number
  });

But this doesn't:

let len;
Url.count({}, (err, data) => {
  len = data;
});
console.log(len); // prints undefined

Is there a way to get the length data and then use it in subsequent operations?

END UPDATE

I'm a beginner with Node and Mongoose. How can I get the total number of documents in my database collection (which is called "Url")?

Some code I have tried:

1.

let len = Url.count();

2.

let len = Url.count({});

3.

let len = Url.find().count();

4.

let len = Url.find().count({});

5.

let len = function(done) {
    Url.count({}, (err, data) => {
      if (err) { done(err) }
      else { done(null, data) }
    });
};

I'm looking to get back a number, but when I console.log(len), I get a huge object that goes on for lines and lines: enter image description here

Scott
  • 1,207
  • 2
  • 15
  • 38
  • The reason the first way works and the secons doesnt is because the log in your second approach is after an async action and since js is not sync, the log gets executed before the actual count finishes – Siya Mzam May 05 '18 at 18:50
  • How can I fix it so it works? I want to use the current length of the collection to be a property on the item I save. – Scott May 05 '18 at 21:06
  • Possible duplicate of [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) and [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Patrick Roberts May 05 '18 at 23:55

2 Answers2

1

This is becuase of the order of operations happening. First this happens

let len;

then

Url.count({}, (err, data) => {
// Nothing is happening in here yet, still waiting to finish counting
});

then

console.log(len); // So len IS undefined here. 

Finally, once it has finished counting:

len = data;

Luckily mongoose can help you here as they support .then

const numberOfUrls = Url.count({});
numberOfUrls.then(number => {
    // Now you can do whatever you need to do with the number
    console.log('number', number)
});

just one important point,

Mongoose queries are not promises. They have a .then() function for co and async/await as a convenience. If you need a fully-fledged promise, use the .exec() function.

http://mongoosejs.com/docs/promises.html

Hope that helps!

Mike Rudge
  • 206
  • 1
  • 7
1

I have struggled with this as well. Javascript asynchronous design at play here. Console.log() even before the query finishes executes the callback.

So, you can either do this:

let len;
Url.count({}, (err, data) => {
  len = data;
  console.log(len);
});

Or, wrap the whole thing around in an async function:

// Just in case :)
mongoose.Promise = global.Promise;

async function dbOperations() {
  let len;
  // Ideally, you must also include error catching.
  // I am not, for now.
  len = await Url.count({}).exec();
  console.log(len);
}
dbOperations();

Please let me know if this works.

benSooraj
  • 447
  • 5
  • 18
  • Thanks for this. A lot of scary code here (async function?, await?) , but this did work and I'm happy to be exposed to it. – Scott May 06 '18 at 16:31