如何在Mongoose查询上设置超时?

时间:2015-03-12 07:54:05

标签: node.js mongodb mongoose

我正在使用Mongoose和一个非常大的Mongo数据库,我希望像MySet.find({})这样昂贵的查询在10秒后超时。

我已经尝试在我的连接上设置套接字超时,但是如果超时超时则服务器崩溃:

var options = {server: {socketOptions: {socketTimeoutMS: 10000}}};
var conn = mongoose.connect('mongodb://localhost/my_db', options);

我已尝试将maxTimeMS选项传递给find函数,但这根本没有任何效果:

MySet.find({}, {}, {timeout: true, maxTimeMS: 10000}, function(err, doc) {});

有什么想法吗?

5 个答案:

答案 0 :(得分:9)

您可以使用Mongoose本身未记录的Query#maxTime方法执行此操作,但它是Mongoose用于其流畅查询界面的mquery库的一部分。

所以在你的情况下,你会把它称为:

MySet.find({}).maxTime(10000).exec(function(err, doc) { ... });

您可以通过maxTimeMS启用Mongoose调试来确认它是否正确设置mongoose.set('debug', true);选项,然后您将看到此查询的控制台输出,如下所示:

Mongoose: myset.find({}) { maxTimeMS: 10000, safe: true, fields: {} }

答案 1 :(得分:0)

TL; DR:

MySet.find({ $query: { /*Query here*/ }, $maxTimeMS: 10000 });

您可以使用此查询进行测试:

MySet.find({ $query: {"$where": "sleep(100) || true"}, $maxTimeMS: 10000 });

为什么会这样:

您可以使用Query modifiers

特别是这一个:$maxTimeMS

小心:自v3.2起,mongo Shell中不推荐使用此运算符

答案 2 :(得分:-2)

我认为这应该有用。

db.mycoll.find()。maxTimeMS(50)

答案 3 :(得分:-2)

这是我开始大量使用的模式。

// Default time out timeout in ms
const DEFAULT_TIME_OUT = 500;

// Default timeout message
const DEFAULT_MESSAGE = `Timeout fetching data(${DEFAULT_TIME_OUT}ms)`;

// Function that triggers a Promise's reject after a set amount of time
function timeoutReject(reject, message, timeout) {
  setTimeout(function(){

    // Reject the Promise if the time is reached
    reject(message || DEFAULT_MESSAGE);
  }, timeout || DEFAULT_TIME_OUT);
};

function youAreNotAuthentic() {
  // Logic to validate user and request return boolean
};

// Throw error if the user cannot access this data
function youCantTouchThis() {
  throw new Error('You cannot access this data.');
};

// Function to request data
function getDataById(_id) {
  // First check if this is authentic
  if (youAreNotAuthentic()) youCantTouchThis();

  // Return a Promise
  return new Promise((resolve, reject) => {

    // Set a timeout to reject if we do not get a response in x time
    timeoutReject(reject, 'Custom Message', 300);

   // Could look like this to just use the defaults
   // timeoutReject(reject);

    // Query for the data
    Collection.findOne({ _id }).then(data => {

       // Resolve the Promise with the retrieved data
       resolve(data);
    });
  });
};

这样我就会对大多数请求应用默认超时,但如果我需要根据每个呼叫进行调整,那么我可以。或者我可以了解需要更好索引的区域。

答案 4 :(得分:-8)

我终于开始工作了。首先,我阻止服务器在套接字(即查询)超时时崩溃:

//don't crash the server if a query times out
mongoose.connection.on('error', function() {});

然后,每次我想查询数据库时,我断开连接并重新连接到数据库,将socketTimeoutMS设置为10000:

mongoose.disconnect();
mongoose.connect('mongodb://localhost/my_db', {
  server: {socketOptions: {socketTimeoutMS: 10000}}
});
MySet.find({}, function(err, doc) {});

这会在执行10秒后切断查询。