Как рассчитать простое скользящее среднее, используя mongodb mapreduce? - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть данные временных рядов в виде следующего формата в коллекции mongodb:

{
    "Name" : "AKBNK",
    "Date" : ISODate("2009-01-02T00:00:00Z"),
    "Close" : 3.256746559,
}

Я хочу вычислить простое скользящее среднее, используя mongodb mapreduce.Я попробовал это как следующее, чтобы выполнить скольжение окна, но оно работает медленно, когда период большой.

var mapper = function() {
    var i = 0, j = counter;
    if (j < period) {
        j = period;
        i = period - counter;
    }
    for (; i < period && j <= limit; i++, j++) {
        emit (j, this.Close);
    }

    counter++;
}

var reducer = function(key, values) {
    return Array.sum(values);
}

var finalizer = function(key, reducedValue) {
    return reducedValue / period;
}

var period = 730;

db.data.mapReduce(mapper, reducer, {finalize: finalizer, out: "smaOut", query: {Name: "AKBNK"}, sort: {Date: -1}, limit: period * 2 - 1, scope: {counter: 1, period: period, limit: period * 2 - 1}});

Любой совет, как я могу сделать это быстрее?Как я могу отобразить данные?

1 Ответ

0 голосов
/ 06 сентября 2018

Вы можете попробовать использовать приведенный ниже конвейер агрегации, который, по-видимому, дает правильные результаты с первого взгляда, но с гораздо большей скоростью:

db.data.aggregate({
    $match: {
        "Name": "AKBNK" // this stage will use and index if you have one on the "Name" field
    }
}, {
    $sort: { "Date": -1 }, // this stage will also use and index if you have one on "Date"
}, {
    $group: {
        "_id": null, // create one single document
        "allCloseValues": { $push: "$Close" } // that shall contain an array with all "Close" values
    }
}, {
    $addFields: {
        "copyOfAllCloseValues": "$allCloseValues" // duplicate the array
    }
}, {
    $unwind: {
        "path": "$copyOfAllCloseValues", // flatten the created single document
        "includeArrayIndex": "_id" // use the "_id" field to hold the array index
    }
}, {
    $project: {
        avg: {
            $avg: { // calculate the average of some part of the array "Close"
                $slice: [ "$allCloseValues", "$_id", 730 ] // which shall start at index "_id" and take up to 730 values
            }
        } 
    }
}, {
    $out: "smaOut" // write the resulting documents out to the "smaOut" collection
});
...