a while ago I managed to write a method to bulk upsert many information into my database. Now what I am trying to do is a method to clean old records on 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 perfectly. Then I did this, in hope it would clean the old records that I don't need anymore:
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 am running this methods with this script, which 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 I run my server it crashes saying that it cannot read property find of 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 since it works perfectly with the bulkUpsert method, which is run by a very similar code.
Anyone has any idea as to why this might be happening? Thanks a lot.
The problem here is that mongoose has not connected to the database yet, and therefore has no handle to the underlying driver object you are accessing via the .collection
accessor.
The mongoose methods themselves perform a little "magic", by essentially queuing all operations until the database connection is actually made. i.e:
Model.find().exec(function(err,docs) { }); // <-- callback queues until connection is ready
However if no connection is present, native methods will not return a collection object:
Model.collection.find({},function(err,docs) { }); <-- collection is undefined
The bulk methods just return a structure that has not executed, so the error does not present until you try to call a method on that stucture.
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 though "mongoose methods" do their own magic to "hide this away", this is needed when calling native methods. The only other way you get away with it is when you are absolutely sure that one of the "mongoose methods" has actually fired already, and that a connection has been made.
Better to be safe than sorry, so it is a wise practice to put the body of your main program initialize and methods within such a block as above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With