2011-09-12 71 views
1

我有一個MongoDB集合,其中包含具有id和時間戳的歷史數據。刪除文件,同時保留至少一個

我想從集合中刪除比特定的 時間戳更早的數據。但是,對於每個ID,至少有一個 文檔(最新)必須留在集合中。

假設我有我的集合中的下列文件...

{"id" : "11", "timestamp" : ISODate("2011-09-09T10:27:34.785Z")} //1 
{"id" : "11", "timestamp" : ISODate("2011-09-08T10:27:34.785Z")} //2 

{"id" : "22", "timestamp" : ISODate("2011-09-05T10:27:34.785Z")} //3 
{"id" : "22", "timestamp" : ISODate("2011-09-01T10:27:34.785Z")} //4 

...我想有一個時間戳刪除文件年紀比 2011-09-07然後 1和2不應該被刪除,因爲它們較新。 4應該被刪除,因爲它比較舊,但3不應該被刪除 (儘管它比較舊),因爲 每個ID至少有一個文檔應該保留在集合中。

有誰知道我可以如何做到這一點與casbah和/或在mongo 控制檯上?

問候, 基督教

回答

1

我能想到幾種方法的。首先,試試這個:

var cutoff = new ISODate("2011-09-07T00:00:00.000Z"); 
db.testdata.find().forEach(function(data) { 
    if (data.timestamp.valueOf() < cutoff.valueOf()) { 
     // A candidate for deletion 
     if (db.testdata.find({"id": data.id, "timestamp": { $gt: data.timestamp }}).count() > 0) { 
      db.testdata.remove({"_id" : data._id}); 
     } 
    } 
}); 

這是做你想做的工作。或者你也可以使用MapReduce作業來完成它。加載到一個文本文件,這樣的:

var map = function() { 
    emit(this.id, { 
     ref: this._id, 
     timestamp: this.timestamp 
    }); 
}; 


var reduce = function(key, values) { 
    var cutoff = new ISODate("2011-09-07T00:00:00.000Z"); 
    var newest = null; 
    var ref = null; 
    var i; 
    for (i = 0; i < values.length; ++i) { 
     if (values[i].timestamp.valueOf() < cutoff.valueOf()) { 
      // falls into the delete range 
      if (ref == null) { 
       ref = values[i].ref; 
       newest = values[i].timestamp; 
      } else if (values[i].timestamp.valueOf() > newest.valueOf()) { 
       // This one is newer than the one we are currently saving. 
       // delete ref 
       db.testdata.remove({_id : ref}); 
       ref = values[i].ref; 
       newest = values[i].timestamp; 
      } else { 
       // This one is older 
       // delete values[i].ref 
       db.testdata.remove({_id : values[i].ref}); 
      } 
     } else if (ref == null) { 
      ref = values[i].ref; 
      newest = values[i].timestamp; 
     } 
    } 
    return { ref: ref, timestamp: newest }; 
}; 

加載上面的文件入殼:load("file.js");

然後運行它:db.testdata.mapReduce(map, reduce, {out: "results"});

然後取出MapReduce的輸出:db.results.drop();

相關問題