這時可以利用以下的 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 的方法
沒有留言:
張貼留言