這時可以利用以下的 script 來達成!
這裡假設 Collection 的名稱是 Coll,裡面的每筆資料(每個文件)都有 time 跟 message 兩個欄位。
tail.js
// Get the started position.
var start_index = db.Coll.find().count()-10;
while(true) {
//
if(db.Coll.find().count() >= start_index) {
var index = start_index - 1;
// Get the next document with ignoring previous old messages.
var rec = db.Coll.find().skip(index);
print(rec[0].time + " | " + rec[0].message);
start_index++;
}
// Sleep for 100 ms.
sleep(0.1);
}
function sleep( milliseconds ) {
var timer = new Date();
var time = timer.getTime();
do
timer = new Date();
while( (timer.getTime() - time) < milliseconds );
}
sleep 部分的 JavaScript 取自 [3]。
tail.sh
{MONGO_PATH}/bin/mongo --quiet localhost:27017/{DB_NAME} ./tail.js
其中 {MONGO_PATH} 是 MongoDB 的路徑、{DB_NAME} 是使用的資料庫名稱。(假設 MongoDB 沒有更改連接埠,因此連線對象是 localhost: 27017)
這個寫法雖然可以動,不過已知會有幾個問題:
1、目前寫法是 sleep 0.1 秒後只會拿出一筆資料,而沒有辦法一次一整沱一起印出來
2、因為 MongoDB 的 script 好像不支援 window,所以沒有 setTimeout() 可以使用,只能用應該很浪費系統資源的迴圈來達到 sleep 的效果。
第一點可能有一些方法可以解決,例如把 while 迴圈改成以下的寫法:
while(true) {
if(db.Coll.find().count() >= start_index) {
var index = start_index - 1;
// Get the next document with ignoring previous old messages.
db.Coll.find().skip(index).forEach(function (rec) {
print(rec.time + " | " + rec.message);
start_index++;
});
}
sleep(100);
}
每次 find() 時,都會把現在剩下的所有資料都印出,然後才會 sleep,可以讓訊息更即時一點出現。如果想要減少 I/O 次數,也許還可以考慮 print 改成暫存在某個變數裡,等到迴圈結束要 sleep 之前才一次印出。
第二點目前還不知道有沒有其他更好的 sleep 寫法,所以暫時不解決。
參考資料:
1、mongodb: how to get the last N records?
2、MongoDB: Create Tailable Cursor
3、[小筆記] Javascript 中實現 sleep 的方法
沒有留言:
張貼留言