【问题标题】:mongoDB getLastError() with javascript and node.js not working带有javascript和node.js的mongoDB getLastError()不起作用
【发布时间】:2012-09-13 10:39:18
【问题描述】:

我有一个使用 mongoDB 的 node.js 应用程序,我有一个函数用于删除集合中的所有文档,然后用一些示例文档重新填充我的数据库中的集合。

当我编写新功能时,我偶尔会使用它用已知数据测试我的应用程序。

我遇到的问题是,如果我在所有集合上调用 drop(),然后调用一些插入来重新填充,有时我的记录会比我期望插入数据库的记录少,有时整个集合会丢失.我的计数检查所有说插入的 # 条记录与预期数量相匹配,但即使它说它已插入,也可能会丢失整个集合。

我只能假设,因为它只发生在大约 50% 的时间里,可能以某种方式在 drop() 完成之前插入开始插入,然后 drop() 清除插入的文档,因为它正在异步运行。

我在所有插入/更新命令上都使用 {safe:true},但 db.collection.drop() 不接受任何参数,而且似乎无法指定安全选项。

所以我试图在 drop() 之后使用 db.getLastError() 来阻止插入,直到 drop 完成。

使用 db.getLastError() 或 db.getlasterror() 会引发错误: TypeError: Object # 没有方法 'getlasterror'

对 getLastError 的简化调用:

var mongo = require("mongodb");

  var db_conn = new mongo.Db(dbName, new mongo.Server(host, port, { auto_reconnect: true }), {});
  db_conn.open(function(err, db) {
    if(!err) {
      console.log("Database connection: \033[32mopen\033[0m");
    } else {
      console.log("Database connection: \033[31mfailed\033[0m");
    }
  });
  db_conn.getLastError();
  this.db_conn = db_conn;
  this.users = db_conn.collection("users");
  this.companies = db_conn.collection("companies");
  this.suppliers = db_conn.collection("suppliers");

我已经在 mongodb 模块版本 1.1.4 和 1.1.7 上尝试过这个,只是得到一个错误。

我是否使用了错误的参考?在 JavaScript 的代码示例中,我在 stackoverflow 或网络上的 getlasterror 上找不到任何内容。

如果有更好的方法可以做到这一点,我会全力以赴。

js 文档:http://docs.mongodb.org/manual/reference/javascript/#db.getLastError

mongo 文档:http://www.mongodb.org/display/DOCS/getLastError+Command

---- 2012 年 9 月 22 日更新

使用下面的答案,我能够稍微调试一下根本问题是什么,这与我预期的一样。使用 5 个打开连接的默认连接池,drop 会随机触发,然后插入。根据它们发送的顺序以及它们各自进入的池,如果一个 drop 快速完成,然后在该集合的 drop 完成之前快速插入,它将稍后删除插入的记录。

我的解决方法是在 drop() 命令的回调中将所有 drop 封装在一个链接序列中,这样每次 drop 都会在前一个 drop 的回调被触发之后发生,然后在最后调用一个触发所有 drop 的回调插入物。这很混乱,但我现在已经用 20 个简单插入的基本记录集和 100,000 条记录的负载测试测试了 initializedb 函数大约 25 次。还没有失败。

时间会证明一切,但这个 .lastError() 答案可以解决这个问题。

---- 2012 年 9 月 30 日更新

我想测试一周左右,然后再回复以确保它确实有效。上周,我在包含 26 条记录的基本集和全部批量插入的 100,000 条记录集上运行了大约 100 次初始化脚本。现在使用我的新代码,我还没有看到它失败过一次。

我用于删除集合的代码:(我有一个 DatabaseHandler 对象与原型函数一起用于操作)

DatabaseHandler.prototype.dropAll = function(callback, callbackArg) {
  // drop all the documents
  var that = this;
  var finished = callback || function() { };
  var finishedArg = callbackArg;
  this.companies.drop(function(err, reply) {
    if(reply) {
      console.log("[db] Companies collection dropped");
    } else {
      console.log("\033[31m[Error]\033[0m Companies collection failed to drop");
    }
    // drop all the user documents
    that.users.drop(function(err, reply) {
      if(reply) {
        console.log("[db] Users collection dropped");
      } else {
        console.log("\033[31m[Error]\033[0m Users collection failed to drop");
      }
      // drop all the course documents
      that.courses.drop(function(err, reply) {
        if(reply) {
          console.log("[db] Courses collection dropped");
        } else {
          console.log("\033[31m[Error]\033[0m Courses collection failed to drop");
        }
        // drop all the course purchase documents
        that.course_purchases.drop(function(err, reply) {
          if(reply) {
            console.log("[db] Course purchases collection dropped");
          } else {
            console.log("\033[31m[Error]\033[0m Course purchases collection failed to drop");
          }
          console.log("Dropped all documents and collections");
          return finished(finishedArg);
        });
      });
    });
  });
};

然后我有一个初始化函数,它接受一个参数来指定我是否想要额外的负载测试数据初始化(addloadtestdata)。如果我指定 dropdata,它会调用 dropAll 并将初始化函数用于回调。因此,当放置完成时,它会调用初始化回调并仅在完成放置后才开始重新添加文档。 我还有一个小计数功能,用于检查完成插入后插入了多少文档,以及验证插入了正确的数字并且没有遗漏。这可能是我添加的最好的功能,所以每次初始化时,我都可以查看插入的文档的确切数量是否正确,或者我是否遗漏了 1 个。

function initialize(doLoadtest){
  // do work here
}
// drop all collections and documents
if(dropdata) {
  // drop all the data first then call the initialize as a callback function when completed dropping
  Database.dropAll(initialize, includeLoadtestData);
} else {
  initialize(includeLoadtestData);
}

希望对你有帮助

【问题讨论】:

  • 我在运行 mocha 测试时遇到了类似的问题。这绝对是一个时间问题。我也设置了{safe:true},但似乎没有太大区别。我设置了 1 秒的 setTimeout 来解决这个问题(尽管仅在测试中)。现在它在 95% 的时间内都有效。
  • 你能发布你最终使用的代码吗?
  • 上面添加了代码示例

标签: javascript mongodb getlasterror


【解决方案1】:

您使用的是 node-mongodb-native 驱动程序吗?如果是这样,请查看 lastError 命令。

http://mongodb.github.com/node-mongodb-native/api-generated/db.html#lasterror

【讨论】:

  • 是的,先生!这是我正在使用的驱动程序,并且可以正常工作。不知道为什么他们不会为此使用正常的 api 名称,但 lastError() 有效。
猜你喜欢
  • 2014-07-20
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 1970-01-01
  • 2019-03-30
  • 1970-01-01
  • 2020-07-11
相关资源
最近更新 更多