Пн go агрегация удаляет все записи для идентификатора и сохраняет только самую старую - PullRequest
5 голосов
/ 10 января 2020

имеют коллекцию со значениями

_id:ObjectId('......')
ton_id :ObjectId('abcd')
value:587900
date:2019-12-13T07:09:40.075+00:00


_id:ObjectId('......')
ton_id :ObjectId('abcd')
value:50540
date:2018-1-13T07:09:40.075+00:00

_id:ObjectId('......')
ton_id :ObjectId('abcd1')
value:55400
date:2019-5-13T07:09:40.075+00:00


_id:ObjectId('......')
ton_id :ObjectId('abcd1')
value:22500
date:2018-12-13T07:09:40.075+00:00


для ton_ids abcd и abcd1 удаляют все записи, кроме самой старой.

требуемый вывод

_id:ObjectId('......')
ton_id :ObjectId('abcd')
value:50540
date:2018-1-13T07:09:40.075+00:00



_id:ObjectId('......')
ton_id :ObjectId('abcd1')
value:22500
date:2018-12-13T07:09:40.075+00:00

Ответы [ 4 ]

1 голос
/ 16 января 2020

Что-то вроде должно работать. Используйте агрегацию, чтобы выбрать идентификаторы, за которыми следуют массовые обновления, чтобы удалить другие идентификаторы.

var bulk = db.getCollection(colname).initializeUnorderedBulkOp();

db.getCollection(colname).aggregate([
    {$match:{"ton_id":{"$in":[abcd, abcd1]}}},
    {$sort:{"date":1}},
    {$group:{
        "_id":"$ton_id", 
        "keep_id":{"$first":"$_id"}
    }},
    {$project:{"_id":0, "ton_id":"$_id", "keep_id":1}}
]).forEach(function(doc){ 
    bulk.find({"_id":{"$ne":doc.keep_id},"ton_id":doc.ton_id}).remove();
}); 
bulk.execute(); 
0 голосов
/ 23 января 2020
    var bulk = Collection.collection.initializeUnorderedBulkOp();
    let removableTonIds = ["abcd", "abcd1"];
    let pipeline = [{
        $match: {
            "ton_id": {
                "$in": removableTonIds
            }
        }
    },
    {
        $sort: {
            date: -1
        }
    },
    {
        $group: {
            _id: '$ton_id',
            id: {
                $first: '$_id'
            },
        }
    }, {
        $group: {
            _id: null,
            keep_ids: {
                $addToSet: '$id'
            }
        }
    },
    {
        $project: {
            keep_ids: 1
        }
    }
]

    var cursor = Collection.aggregate(pipeline).cursor({batchSize: 1000}).exec();


    cursor.on( 'data', function( data ) {
        bulk.find( { "_id" : { $nin: data.keep_ids }, "ton_id": {$in: removableTonIds } } ).remove();
    });

    cursor.on( 'end', function() {
        if ( bulk.length === 0 ) {
            callback();
        } else {
            bulk.execute(function (error) {
                if (error) {
                    callback(error);
                } else {
                    callback();
                }
            });
        }
    });
0 голосов
/ 21 января 2020

Я думаю, что вам нужно показать самые старые данные для каждого уникального ton_id в вашей коллекции

Этого можно добиться с помощью запроса агрегации, подобного этому

db.getCollection(colname).aggregate([
    {
        $sort:{
            date:-1
        }
    },
    {
        $group:{
            _id:'$ton_id',
            id:{$first:'$_id'},
            value:{$first:'$value'},
            date:{$first:'$value'}
        }
    },{
        $project:{
            _id:'$id',
            ton_id:'$_id',
            value:1,
            date:1
        }
    }
])
0 голосов
/ 18 января 2020

К сожалению, нет способа сделать это за 1 операцию.

Таким образом, мы должны сделать это в 2 этапа, сначала найти документ, который нужно исключить, а затем удалить сброс.

let tonIds = [ObjectId("abcd"), ObjectId("abcd1")]
let docToExclude = await db.collection.findOne({ton_id: {$in: tonIds}}).sort({date: -1})
let deleteTheRest = await db.collection.removeMany({_id: {$ne: docToExclude._id}, ton_id: {$in: tonIds}})
...