Вот решение исключительно из оболочки MongoDB.
Мое решение основано на конвейере агрегирования и использовании операции проекта . В своем вопросе вы сказали:
Каждый документ может иметь разные размеры массива (fetch_dates), но структура такая же.
Исходя из этого, я не вижу причин чтобы перебрать все документы в базе данных. Вместо этого вы можете извлечь только один документ из базы данных и использовать его для создания прогноза, который должен работать со всеми документами в базе данных. Вот код, который я придумал.
function buildProjection(doc, prepend) {
var projection = {};
Object.keys(doc)
.forEach(key => {
var val = doc[key];
var path = prepend==null? key : prepend + '.' + key;
if (key == '_id') {
projection[key] = 1;
} else if ( Array.isArray(val) ) {
projection[key] = { '$slice' : [ '$'+path, -1 ] };
} else if ( typeof val === 'object' && val !== null ) {
projection[key] = buildProjection(val, path);
} else {
projection[key] = 1;
}
});
return projection;
}
/*
* Pull a document out of the database and build the projection based off of it.
* You may want to specify a particular document in the findone
* that you know to be structured correctly
*/
var sample = db.myCollection.findOne({});
var projection = buildProjection(sample, null);
db.myCollection.aggregate([
// apply the build projection
{ $project: projection },
// insert results into another collection
{ $out: 'rebuiltWithLatest' }
]);
Я не был уверен, хотите ли вы сохранить результаты в другой коллекции. Я сделал это с помощью этого решения. Это заняло несколько секунд, но у меня не было проблем с запуском этого с 300 тыс. Документов, которые были очень похожи на ваш связанный пример.
Если вы только sh для просмотра документов, удалите операцию $ output из конвейер агрегации. Затем он вернет объект курсора, который вы можете перебирать, чтобы увидеть дополнительные результаты.