2016-05-19 40 views
6

Mam zbiór danych, który zawiera punkty danych na każde 5 sekund dziennie. Spowoduje to, że zbiór danych o wartości elementów dziennie. Ten zestaw jest o wiele za duży i chcę go pomniejszyć (używam tych elementów do rysowania wykresu).Symfony/Doctrine/MongoDB Zdobądź każdy N-ty produkt

Ponieważ oś X na wykresie jest z czasem postanowiłem, że przerwa 5 minut na punkt danych jest wystarczająco dobra. To powróci do datapoints dziennie. O wiele mniej i wystarczająco dobrze, by stworzyć wykres.

My MongoCollection wygląda następująco:

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

dane zostaną wysłane co 5 sekund do bazy danych. Tak więc znacznik czasu będzie się różnić 5 sekund dla każdego wyniku.

Ponieważ moja oś X jest podzielona na 5 minut sekwencji, chciałbym obliczyć średnie wartości someKey, someOtherKey i someOtherOtherkey w ciągu tych 5 minut. Ta nowa średnia będzie jednym z punktów danych na moim wykresie.

W jaki sposób można uzyskać wszystkie punkty danych od 1 dnia, przy czym każde przeciętne 5 minut różni się od siebie? (288 punktów danych dziennie).

Jak na razie jestem wybierając każdy dokument z północy tego dnia:

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

jaki sposób jeden filtrować tej listy danych (w ramach tego samego zapytania), aby uzyskać punktów danych dla każdych 5 minut (i punkt danych jest średnią punktów w ciągu tych 5 minut)?

Byłoby miło mieć to zapytanie zbudowane z doktryną, ponieważ będę jej potrzebować w mojej aplikacji symfony.

EDYTOWANIE Próbowałem najpierw uzyskać zapytanie w ramach pracy w języku mongol. Zgodnie z sugestiami dotyczącymi komentarzy powinienem zacząć używać aggregation.

Zapytanie zrobiłem do tej pory opiera się na innym pytanie zadane tutaj w stackoverflow

to jest obecny zapytania:

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"} 
     } 
    } 
]) 

To zapytanie da mi ostatni wynik dla każdych 300 sekund (5 minut) od dziś Północ. chcę, aby wszystkie dokumenty w ciągu tych 300 sekund i obliczyć średnią ponad kolumnami someKey, someOtherKey, someOtherOtherKey

Więc jeśli weźmiemy ten przykładowy zestaw danych:

{ 
    "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 
} 

Kwerenda powinna powrócić wiersze mianowicie:

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

pierwszy wynik jest obliczany następująco:

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

W jaki sposób dokonać obliczeń w ramach mongleta z funkcją agregacji?

+0

To brzmi jak praca dla frameworka agregacji, czy próbowałeś go użyć? – malarzm

+0

W jaki sposób można wykorzystać strukturę agregacji? Próbowałem używać grupy, ale utknąłem:/ – Baklap4

+1

Nie jestem zbyt biegły z tym sam, prawdopodobnie przechodząc przez dokumentację i inne pytania SO rzucić trochę światła :) Jeśli chodzi o użycie agregacji z Doctrine ODM nie zapewnia jakikolwiek cukier jeszcze (jest niedokończony PR dla uwodnienia), ale można go wykorzystać. – malarzm

Odpowiedz

2

Na podstawie podanych tu answeresów na stackoverflow udało mi się uzyskać dokładnie to, co chciałem.

Jest to duży kwerendy agregacji muszę zrobić, aby wszystkie moje wyniki z powrotem:

część
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' 
     } 
    } 
]) 

mecz jest dla uzyskania każdy wynik Po dzisiejszym północy (timestamp dzisiejszej północy).

Część grupowa to najciekawsza część. Tutaj przechodzimy przez każdy znaleziony dokument i obliczamy moduł na każde 300 sekund (5 minut), a następnie wypełniamy znacznik czasu właściwości ostatnim wynikiem operacji modulus.

Część projektu jest niezbędna do usunięcia _id z rzeczywistego wyniku, ponieważ wynik nie reprezentuje już czegoś w bazie danych.

Podane answeres gdzie to answere opiera się na:

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

Doctrine Rozwiązanie

$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 
      ] 
     ] 
    ] 
]);