我有一个MongoDB集合,其中包含带有id和timestamp的历史数据。
我想从早于特定的集合中删除数据 时间戳。但对于每个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做到这一点 控制台?
此致 基督徒
答案 0 :(得分: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 };
};
将上述文件加载到shell中:load("file.js");
然后运行它:db.testdata.mapReduce(map, reduce, {out: "results"});
然后删除mapReduce输出:db.results.drop();