Node.js: Mongoose initializeUnorderedBulk returning null

Some time ago I was able to write a method to bulk input a lot of information into my database. Now what I am trying to do is a method of clearing old records in the same database and table.

raidSchema.statics.bulkUpsert = function (raids, callback) {
  var bulk = Raid.collection.initializeUnorderedBulkOp();

  for (var i = 0; i < raids.length; i++) {
    var raid = raids[i];
    var date = new Date();
    bulk.find({id: raid.id, hash: raid.hash}).upsert().update({
      $setOnInsert: {
        ...
      },
      $set: {
        ...
      }
    });
  }

  bulk.execute(callback);
};

      

This works great. I then did this, hoping it would clear out old entries that I no longer need:

raidSchema.statics.cleanOldRaids = function (callback) {
  var date = new Date();
  date.setMinutes(date.getMinutes() - 30);

  var bulk = Raid.collection.initializeUnorderedBulkOp();
  bulk.find({$or: [ { maxHealth: {$lte: 0} }, { isComplete: true }, {updatedOn: {$lte: date.getTime()}} ] }).remove();
  bulk.execute(callback);
};

      

And I run these methods with this script that tries to run it every 30 minutes:

var Raid = require('../models/raid');
var async = require('async');

var cleanInterval = 1000 * 60 * 30;

var cleanRaids = function () {
  console.log('cleanRaids: Starting cleaning');

  async.series([
      function (callback) {
        Raid.cleanOldRaids();
        callback(null, 'All servers');
      }],
    function (err, results) {
      if (err) throw err;

      console.log("cleanRaids: Done cleaning (" + results.join() + ")");
      setTimeout(cleanRaids, cleanInterval);
    })
};

cleanRaids();

      

but right after starting my server, it gives a message that it cannot read the find property undefined:

.../models/raid.js:104
  bulk.find({$or: [ { maxHealth: {$lte: 0} }, { isComplete: true }, {updatedO
       ^
TypeError: Cannot read property 'find' of undefined

      

I am completely lost as it works great with the bulkUpsert method, which is triggered by very similar code.

Does anyone know why this might be happening? Many thanks.

+3


source to share


1 answer


The problem is that mongoose has not yet connected to the database and therefore does not have a handle to the underlying driver object that you access through the accessory .collection

.

The mongoose methods themselves perform a little "magic", essentially queuing up all operations until the actual connection to the database is established. i.e:

Model.find().exec(function(err,docs) { });   // <-- callback queues until connection is ready

      

However, if there is no connection, the built-in methods will not return a collection object:

Model.collection.find({},function(err,docs) { }); <-- collection is undefined

      



The methods explained simply return a structure that has not been executed, so the error does not appear until you try to call a method on that structure.

The fix is โ€‹โ€‹easy, just wait for the connection before executing any code:

mongoose.connection.on("open",function(err) {
  // body of program in here

});

      

So, while the "mongoose methods" do their own magic to "hide it", it is necessary when calling your own methods. The only way to avoid this is when you are absolutely sure that one of the "mongoose" methods is already running and that a connection has been made.

It's better to be safe than sorry, so it is a smart practice to expose your main program body and methods in a block like above.

+9


source







All Articles