簡體   English   中英

如何在Mongoose查詢上設置超時?

[英]How do I set a timeout on a Mongoose query?

我正在使用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) {});

有任何想法嗎?

您可以使用Query#maxTime方法執行此Query#maxTime

所以在你的情況下,你會稱之為:

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

您可以通過maxTimeMS啟用Mongoose調試來確認它是否正確設置了maxTimeMS選項mongoose.set('debug', true); 然后你會看到這個查詢的控制台輸出,如下所示:

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

TL; DR:

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

您可以使用此查詢進行測試:

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

為什么會這樣:

您可以使用查詢修飾符

特別是這一個: $ maxTimeMS

注意 :從v3.2開始,mongo Shell中不推薦使用此運算符

我認為這應該有效。

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

這是我開始大量使用的模式。

// 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);
    });
  });
};

這樣我就會對大多數請求應用默認超時,但如果我需要根據每個呼叫進行調整,那么我可以。 或者我可以了解需要更好索引的區域。

我終於搞定了。 首先,我阻止服務器在套接字(即查詢)超時時崩潰:

//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秒后切斷了查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM