MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Agregacja Mongo w odstępach czasu

Istnieje kilka sposobów podejścia do tego, w zależności od tego, który format wyjściowy najlepiej odpowiada Twoim potrzebom. Główna uwaga jest taka, że ​​w przypadku "struktury agregacji" nie można w rzeczywistości zwrócić czegoś "oddanych" jako daty, ale można uzyskać wartości, które można łatwo zrekonstruować na Date obiektu podczas przetwarzania wyników w Twoim API.

Pierwszym podejściem jest użycie "Operatorów agregacji dat" dostępne w ramach agregacji:

db.collection.aggregate([
    { "$match": {
        "time": { "$gte": startDate, "$lt": endDate }
    }},
    { "$group": {
        "_id": {
            "year": { "$year": "$time" },
            "dayOfYear": { "$dayOfYear": "$time" },
            "hour": { "$hour": "$time" },
            "minute": {
                "$subtract": [
                    { "$minute": "$time" },
                    { "$mod": [ { "$minute": "$time" }, 10 ] }
                ]
            }
        },
        "count": { "$sum": 1 }
    }}
])

Który zwraca klucz złożony dla _id zawierające wszystkie żądane wartości dla „daty”. Alternatywnie, jeśli tylko w ciągu "godziny" zawsze użyj części "minuty" i oblicz rzeczywistą datę na podstawie startDate wybranego zakresu.

Lub możesz po prostu użyć zwykłego „matematyki dat”, aby uzyskać milisekundy od „epoki”, które można ponownie przekazać bezpośrednio do konstruktora dat.

db.collection.aggregate([
    { "$match": {
        "time": { "$gte": startDate, "$lt": endDate }
    }},
    { "$group": {
        "_id": {
            "$subtract": [
               { "$subtract": [ "$time", new Date(0) ] },
               { "$mod": [
                   { "$subtract": [ "$time", new Date(0) ] },
                   1000 * 60 * 10
               ]}
            ]
        },
        "count": { "$sum": 1 }
    }}
])

We wszystkich przypadkach czego nie robisz chcesz zrobić, to użyć $project przed faktycznym zastosowaniem $group . Jako „etap potoku”, $project musi „przechodzić” przez wszystkie wybrane dokumenty i „przekształcać” treść.

To zajmuje czas i dodaje do sumy wykonania zapytania. Możesz po prostu zgłosić się do $group bezpośrednio, jak pokazano.

Lub jeśli naprawdę jesteś „czysty” co do Date obiekt zwracany bez przetwarzania końcowego, zawsze możesz użyć "mapReduce" , ponieważ funkcje JavaScript faktycznie pozwalają na przekształcenie jako datę, ale wolniej niż struktura agregacji i oczywiście bez odpowiedzi kursora:

db.collection.mapReduce(
   function() {
       var date = new Date(
           this.time.valueOf() 
           - ( this.time.valueOf() % ( 1000 * 60 * 10 ) )
       );
       emit(date,1);
   },
   function(key,values) {
       return Array.sum(values);
   },
   { "out": { "inline": 1 } }
)

Najlepszym rozwiązaniem jest jednak użycie agregacji, ponieważ przekształcenie odpowiedzi jest dość łatwe:

db.collection.aggregate([
    { "$match": {
        "time": { "$gte": startDate, "$lt": endDate }
    }},
    { "$group": {
        "_id": {
            "year": { "$year": "$time" },
            "dayOfYear": { "$dayOfYear": "$time" },
            "hour": { "$hour": "$time" },
            "minute": {
                "$subtract": [
                    { "$minute": "$time" },
                    { "$mod": [ { "$minute": "$time" }, 10 ] }
                ]
            }
        },
        "count": { "$sum": 1 }
    }}
]).forEach(function(doc) {
    doc._id = new Date(doc._id);
    printjson(doc);
})

A potem masz wyjście grupowania interwałów z rzeczywistą Date obiekty.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Dekodowanie dzienników błędów MongoDB

  2. Jak odjąć dwie daty w mongodb

  3. Funkcja agregująca MongoDB w C#

  4. Wyjaśnienie SQL NULLIF()

  5. Jak sformatować datę w MongoDB