MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Resampling von Zeitreihendaten mit Javascript und Mongodb

Es ist irgendwie möglich. Denken Sie daran, dass Pandas eine Bibliothek ist, die explizit für diese Art von Aufgaben erstellt wurde, und ein Biest darin, während MongoDB eine Datenbank sein soll. Aber die Chancen stehen gut, dass das Folgende Ihren Anforderungen entspricht, wenn man Ihre wahrscheinliche Notwendigkeit der Verwendung von Interpolation ignoriert:

Angenommen, Sie haben die folgenden Daten in einer MongoDB-Sammlung namens devices gespeichert

/* 0 */
{
    "_id" : ObjectId("543fc08ccf1e8c06c0288802"),
    "t" : ISODate("2014-10-20T14:56:44.097+02:00"),
    "a" : "192.168.0.16",
    "i" : 0,
    "o" : 32
}

/* 1 */
{
    "_id" : ObjectId("543fc08ccf1e8c06c0288803"),
    "t" : ISODate("2014-10-20T14:56:59.107+02:00"),
    "a" : "192.168.0.16",
    "i" : 14243,
    "o" : 8430
}

and so on...

was in diesem Fall etwa alle 15 Sekunden abgetastet wird, aber es könnte auch unregelmäßig sein. Wenn Sie es für einen bestimmten Tag auf eine 5-Minuten-Grenze neu abtasten möchten, sollten Sie Folgendes tun:

var low = ISODate("2014-10-23T00:00:00.000+02:00")
var high = ISODate("2014-10-24T00:00:00.000+02:00")
var interval = 5*60*1000;
db.devices.aggregate([
  {$match: {t:{$gte: low, $lt: high}, a:"192.168.0.16"}},
  {$group: {
     _id:{
       $subtract: ["$t", {
         $mod: [{
           $subtract: ["$t", low]
         }, interval]
       }]
     },
     total: {$sum: 1},
     incoming: {$sum: "$i"},
     outgoing: {$sum: "$o"},
    }
  },
  {
    $project: {
      total: true,
      incoming: true,
      outgoing: true,
      incoming_avg: {$divide: ["$incoming", "$total"]},
      outgoing_avg: {$divide: ["$outgoing", "$total"]},
    },
  },
  {$sort: {_id : 1}}
])

Dies wird in etwa so aussehen

{
    "result" : [ 
        {
            "_id" : ISODate("2014-10-23T07:25:00.000+02:00"),
            "total" : 8,
            "incoming" : 11039108,
            "outgoing" : 404983,
            "incoming_avg" : 1379888.5,
            "outgoing_avg" : 50622.875
        }, 
        {
            "_id" : ISODate("2014-10-23T07:30:00.000+02:00"),
            "total" : 19,
            "incoming" : 187241,
            "outgoing" : 239912,
            "incoming_avg" : 9854.78947368421,
            "outgoing_avg" : 12626.94736842105
        }, 
        {
            "_id" : ISODate("2014-10-23T07:35:00.000+02:00"),
            "total" : 17,
            "incoming" : 22420099,
            "outgoing" : 1018766,
            "incoming_avg" : 1318829.352941176,
            "outgoing_avg" : 59927.41176470588
        },
        ...

Wenn Sie den gesamten Eingang verwerfen möchten, lassen Sie die Zeile in der Phase $project einfach weg. Der eingehende_Durchschnitt ist nur ein Beispiel für die Berechnung des Durchschnitts, falls Ihre gespeicherten Daten so etwas wie das sind, was rrdtool als Messgerät bezeichnet (Temperatur, CPU, Sensordaten). Wenn Sie nur nach der in diesem Zeitintervall aggregierten Summe, also dem Eingangs- und Ausgangsfeld, suchen, können Sie die gesamte $project-Phase auslassen. Es dient nur dazu, den Durchschnitt des Zeitintervalls zu berechnen.

Siehe Mongo-Aggregation von ISODate in 45-Minuten-Chunks