Удаление документов при сохранении хотя бы одного - PullRequest
1 голос
/ 12 сентября 2011

У меня есть коллекция MongoDB, содержащая данные истории с идентификатором и отметкой времени.

Я хочу удалить данные из коллекции старше определенной метка времени. Но для каждого идентификатора хотя бы один документ (самый новый) должен оставаться в коллекции.

Предположим, у меня есть следующие документы в моей коллекции ...

{"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 не следует удалять (хотя это старше), потому что в коллекции должен оставаться хотя бы один документ на идентификатор.

Кто-нибудь знает, как я могу это сделать с помощью касбы и / или на монго? консоль

С уважением, Кристиан

1 Ответ

1 голос
/ 14 сентября 2011

Я могу придумать пару способов. Сначала попробуйте это:

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();

...