2016-05-19 11 views
6

Ich habe einen Datensatz, der Datenpunkte für alle 5 Sekunden pro Tag enthält. Dies würde zu einem Datensatz von Artikel pro Tag führen. Dieses Set ist viel zu groß und ich möchte es kleiner (ich verwende diese Elemente, um ein Diagramm zu zeichnen).Symfony/Doctrine/MongoDB Holen Sie sich jedes Nth item

Da die x-Achse des Graphen mit der Zeit übereinstimmt, habe ich entschieden, dass eine Lücke von 5 Minuten pro Datenpunkt gut genug ist. Dies wird in Datenpunkte pro Tag zurückkehren. Viel weniger und gut genug, um einen Graphen zu erstellen.

Mein MongoCollection sieht wie folgt aus:

{ 
    "timestamp":"12323455", 
    "someKey":123, 
    "someOtherKey": 345, 
    "someOtherOtherKey": 6789 
} 

Die Daten alle 5 Sekunden in die Datenbank geschrieben wird. Der Zeitstempel wird also für jedes Ergebnis um 5 Sekunden abweichen.

Da meine X-Achse in 5 Minuten Sequenzen unterteilt ist, würde ich gerne die Durchschnittswerte von someKey, someOtherKey und someOtherOtherkey über diese 5 Minuten berechnen. Dieser neue Durchschnittswert ist einer der Datenpunkte in meinem Diagramm.

Wie würde man alle Datenpunkte von 1 Tag mit durchschnittlich 5 Minuten voneinander erhalten? (288 Datenpunkte pro Tag).

Was jetzt habe ich jedes Dokument von Mitternacht an diesem Tag bin Auswahl:

$result = $collection 
    ->createQueryBuilder() 
    ->field('timestamp')->gte($todayMidnight) 
    ->sort('timestamp', 'DSC') 
    ->getQuery() 
    ->execute(); 

Wie würde man diese Liste von Daten filtern (innerhalb der gleichen Abfrage), um die Datenpunkte für alle 5 Minuten zu bekommen (und die Datenpunkt ist ein Durchschnitt der Punkte innerhalb dieser 5 Minuten)?

Es wäre schön, diese Abfrage mit Doktrin erstellt zu haben, da ich es in meiner Symfony-Anwendung brauche.

BEARBEITEN Ich habe versucht, meine Abfrage zuerst innerhalb der Mongoshell arbeiten. Wie in den Kommentaren vorgeschlagen, sollte ich anfangen, aggregation zu verwenden.

Die Abfrage die ich bisher gemacht habe, ist auf eine andere Frage basiert hier bei fragte stackoverflow

Dies ist die aktuelle Abfrage:

db.Pizza.aggregate([ 
    { 
     $match: 
     { 
      timestamp: {$gte: 1464559200} 
     } 
    }, 
    { 
     $group: 
     { 
      _id: 
      { 
       $subtract: [ 
        "$timestamp", 
        {"$mod": ["$timestamp", 300]} 
       ] 
      }, 
      "timestamp":{"$first":"$timestamp"}, 
      "someKey":{"$first":"$someKey"}, 
      "someOtherKey":{"$first":"$someOtherKey"}, 
      "someOtherOtherKey":{"$first":"$someOtherOtherKey"} 
     } 
    } 
]) 

Diese Abfrage gibt mir das letzte Ergebnis für jede 300 Sekunden (5 Minuten) von heute Mitternacht. Ich möchte sie alle Dokumente innerhalb dieser 300 Sekunden erhalten und einen Durchschnitt über die Spalten someKey, someOtherKey, So someOtherOtherKey

berechnen, wenn wir dieses Beispiel-Datensatz nehmen:

{ 
    "timestamp":"1464559215", 
    "someKey":123, 
    "someOtherKey": 345, 
    "someOtherOtherKey": 6789 
}, 
{ 
    "timestamp":"1464559220", 
    "someKey":54, 
    "someOtherKey": 20, 
    "someOtherOtherKey": 511 
}, 
{ 
    "timestamp":"1464559225", 
    "someKey":654, 
    "someOtherKey": 10, 
    "someOtherOtherKey": 80 
}, 
{ 
    "timestamp":"1464559505", 
    "someKey":90, 
    "someOtherKey": 51, 
    "someOtherOtherKey": 1 
} 

Die Abfrage zurückgeben soll nämlich Reihen:

{ 
    "timestamp":"1464559225", 
    "someKey":277, 
    "someOtherKey": 125, 
    "someOtherOtherKey": 2460 
}, 
{ 
    "timestamp":"1464559505", 
    "someKey":90, 
    "someOtherKey": 51, 
    "someOtherOtherKey": 1 
} 

Das erste Ergebnis wie folgt berechnet:

Result 1 - someKey = (123+54+654)/3 = 277 
Result 1 - someOtherKey = (345+20+10)/3 = 125 
Result 1 - someOtherOtherKey = (6789+511+80)/3 = 2460 

Wie würde man diese Berechnung innerhalb der Mongoshell mit der Aggregationsfunktion machen?

+0

Das klingt wie ein Job für Aggregation Framework, haben Sie es versucht? – malarzm

+0

Wie würde man das Aggregations-Framework verwenden? Ich habe versucht mit der Gruppe, aber ich steckte fest:/ – Baklap4

+1

Ich bin nicht sehr flüssig mit mir selbst, wahrscheinlich durch Dokumentation und andere SO Fragen werden etwas Licht werfen :) Wenn es um die Verwendung von Aggregation mit Doctrine ODM nicht bietet noch kein Zucker (es gibt unvollendete PR für die Hydratation), aber es ist möglich, es zu benutzen. – malarzm

Antwort

2

Basierend auf den gegebenen Antworten hier auf Stackoverflow habe ich es geschafft, genau das zu bekommen, was ich wollte.

Dies ist die große Aggregation Abfrage ich wieder alle meine Ergebnisse machen müssen zu bekommen:

db.Pizza.aggregate([ 
    { 
     $match: 
     { 
      timestamp: {$gte: 1464559200} 
     } 
    }, 
    { 
     $group: 
     { 
      _id: 
      { 
       $subtract: [ 
        '$timestamp', 
        {$mod: ['$timestamp', 300]} 
       ] 
      }, 
      timestamp: {$last: '$timestamp'}, 
      someKey: {$avg: '$someKey'}, 
      someOtherKey: {$avg: '$someOtherKey'}, 
      someOtherOtherKey: {$avg: '$someOtherOtherKey'} 
     } 
    }, 
    { 
     $project: 
     { 
      _id: 0, 
      timestamp: '$timestamp', 
      someKey: '$someKey', 
      someOtherKey:'$someOtherKey', 
      someOtherOtherKey:'$someOtherOtherKey' 
     } 
    } 
]) 

Das Spiel ist Teil jedes Ergebnis nach heute Mitternacht (Zeitstempel von heute Mitternacht) für immer.

Der Gruppenteil ist der interessanteste Teil. Hier durchlaufen wir jedes gefundene Dokument und berechnen alle 300 Sekunden (5 Minuten) einen Modulus. Dann füllen wir den Zeitstempel der Eigenschaft mit dem letzten Ergebnis der Modulo-Operationen.

Der Projektteil ist notwendig, um die _id aus dem tatsächlichen Ergebnis zu entfernen, da das Ergebnis nicht mehr etwas in der Datenbank darstellt.

Da answeres wo diese answere auf basiert:

MongoDB - Aggregate max/min/average for multiple variables at once

How to subtract in mongodb php

MongoDB : Aggregation framework : Get last dated document per grouping ID

Lehre Lösung

$collection->aggregate([ 
    [ 
     '$match' => [ 
      'timestamp' => ['$gte' => 1464559200] 
     ] 
    ], 
    [ 
     '$group' => [ 
      '_id' => [ 
       '$subtract' => [ 
        '$timestamp', 
        [ 
         '$mod' => ['$timestamp',300] 
        ] 
       ] 
      ], 
      'timestamp' => [ 
       '$last' => '$timestamp' 
      ], 
      $someKey => [ 
       '$avg' => '$'.$someKey 
      ], 
      $someOtherKey => [ 
       '$avg' => '$'.$someOtherKey 
      ], 
      $someOtherOtherKey => [ 
       '$avg' => '$'.$someOtherOtherKey 
      ] 
     ] 
    ] 
]); 
Verwandte Themen