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

Agregacja Mongodb według dnia, a następnie godziny

To, czego zasadniczo potrzebujesz, to podwójne grupowanie, ale nie odzyskujesz całego obiektu daty za pomocą operatory agregacji dat , tylko odpowiednie części:

db.collection.aggregate([
    { "$group": {
        "_id": {
            "customerId": "$customerId",
            "day": { "$dayOfYear": "$startTime" },
            "hour": { "$hour": "$startTime" }
        },
        "pings": { "$sum": "$ping" },
        "links": { "$sum": "$link" }
    }},
    { "$group": {
       "_id": {
           "customerId": "$_id.customerId",
           "day": "$_id.day"
       },
       "hours": { 
           "$push": { 
               "hour": "$_id.hour",
               "pings": "$pings",
               "links": "$links"
           }
       }
    }}
])

Podwójne $group daje żądany format, umieszczając wyniki w tablicy na dzień. Pojedynczy dokument w próbce, ale zasadniczo otrzymujesz takie wyniki:

{
    "_id" : {
            "customerId" : 123,
            "day" : 365
    },
    "hours" : [
            {
                    "hour" : 10,
                    "pings" : 2,
                    "links" : 3
            }
    ]
}

Jeśli okaże się, że wyniki operatorów dat są zbyt trudne do opanowania lub chcesz uzyskać uproszczony wynik „przekazywania” dla obiektów daty, możesz zamiast tego rzutować jako znaczniki czasu epoki:

db.collection.aggregate([
    { "$group": {
        "_id": {
            "customerId": "$customerId",
            "day": {
               "$subtract": [
                   { "$subtract": [ "$startTime", new Date("1970-01-01") ] },
                   {
                       "$mod": [
                           { "$subtract": [ "$startTime", new Date("1970-01-01") ] },
                           1000*60*60*24   
                       ]
                   }
               ]
            },
            "hour": {
               "$subtract": [
                   { "$subtract": [ "$startTime", new Date("1970-01-01") ] },
                   {
                       "$mod": [
                           { "$subtract": [ "$startTime", new Date("1970-01-01") ] },
                           1000*60*60   
                       ]
                   }
               ]
            }
        },
        "pings": { "$sum": "$ping" },
        "links": { "$sum": "$link" }
    }},
    { "$group": {
       "_id": {
           "customerId": "$_id.customerId",
           "day": "$_id.day"
       },
       "hours": { 
           "$push": { 
               "hour": "$_id.hour",
               "pings": "$pings",
               "links": "$links"
           }
       }
    }}
])

Sztuczka polega na tym, że $subtract jeden obiekt daty z innego otrzymujesz w rezultacie wartość "epoka". W tym przypadku używamy daty rozpoczęcia "epoki", aby uzyskać całą wartość znacznika czasu i po prostu dostarczamy "matematykę daty", aby poprawić czasy do wymaganych interwałów. Wynik:

{
    "_id" : {
            "customerId" : 123,
            "day" : NumberLong("1419984000000")
    },
    "hours" : [
            {
                    "hour" : NumberLong("1420020000000"),
                    "pings" : 2,
                    "links" : 3
            }
    ]
}

Co może być dla Ciebie przyjemniejsze niż to, co zapewniają operatorzy dat w zależności od Twoich potrzeb.

Możesz również dodać krótki skrót do MongoDB 2.6 za pośrednictwem $let operator, który pozwala deklarować "zmienne" dla operacji w zakresie:

db.event.aggregate([
    { "$group": {
        "_id": {
            "$let": {
                "vars": { 
                   "date": { "$subtract": [ "$startTime", new Date("1970-01-01") ] },
                   "day": 1000*60*60*24,
                   "hour": 1000*60*60
                },
                "in": {
                    "customerId": "$customerId",
                    "day": {
                        "$subtract": [
                            "$$date",
                            { "$mod": [ "$$date", "$$day" ] }
                         ]
                    },
                    "hour": {
                        "$subtract": [
                            "$$date",
                            { "$mod": [ "$$date", "$$hour" ] }
                         ]
                    }
                }
            }
        },
        "pings": { "$sum": "$ping" },
        "links": { "$sum": "$link" }
    }},
    { "$group": {
       "_id": {
           "customerId": "$_id.customerId",
           "day": "$_id.day"
       },
       "hours": { 
           "$push": { 
               "hour": "$_id.hour",
               "pings": "$pings",
               "links": "$links"
           }
       }
    }}
])

Prawie zapomniałem też wspomnieć, że twoje wartości dla "ping" i "link" są w rzeczywistości ciągami, chyba że jest to literówka. Ale jeśli nie, upewnij się, że najpierw przekonwertujesz je jako liczby.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongoose Zaludnij bazę na innym polu Dynamic ref

  2. Wiosna:Czy klasa może być zarówno @Document, jak i @Table?

  3. $geoNear pasująca do najbliższej tablicy

  4. znajdź pierwszy z dokumentów dla każdej odrębnej wartości dla jednego pola

  5. Jak przerwać uruchomione zapytanie w powłoce MongoDB?