Node.js:Mongoose initializeUnorderedBulk返回null

Uri*_*che 4 mongoose mongodb node.js

前段时间我设法写了一个方法来将许多信息批量上传到我的数据库中.现在我要做的是清理同一数据库和表上的旧记录的方法.

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);
};
Run Code Online (Sandbox Code Playgroud)

这非常有效.然后我做了这个,希望它能清理我不再需要的旧记录:

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);
};
Run Code Online (Sandbox Code Playgroud)

我正在使用此脚本运行此方法,该脚本每30分钟尝试运行一次:

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();
Run Code Online (Sandbox Code Playgroud)

但是在我运行我的服务器后它崩溃说它无法读取undefined的属性find:

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

我完全迷失了,因为它与bulkUpsert方法完美配合,后者由一个非常相似的代码运行.

任何人都知道为什么会发生这种情况?非常感谢.

Bla*_*ven 12

这里的问题是mongoose还没有连接到数据库,因此没有处理通过访问器访问的底层驱动程序对象.collection.

通过基本上排队所有操作直到实际建立数据库连接,mongoose方法本身执行一些"魔术".即:

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

但是,如果不存在连接,则本机方法将不返回集合对象:

Model.collection.find({},function(err,docs) { }); <-- collection is undefined
Run Code Online (Sandbox Code Playgroud)

批量方法只返回一个尚未执行的结构,因此在您尝试在该结构上调用方法之前,错误不会出现.

修复很简单,只需在执行任何代码之前等待连接:

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

});
Run Code Online (Sandbox Code Playgroud)

因此,虽然"mongoose方法"做了自己的魔法来"隐藏它",但在调用本机方法时需要这样做.你逃脱它的唯一另一种方式是当你完全确定其中一个"猫鼬方法"已经实际已经解雇时,并且已经建立了连接.

最好是安全而不是遗憾,所以将主程序的主体初始化和方法放在如上所述的块中是明智的做法.