sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongodb Aggregation per dag sedan timme

Vad du i princip vill ha är en dubbel gruppering, men du får inte tillbaka hela datumobjektet med hjälp av operatorer för datumaggregation , bara de relevanta delarna:

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

Den dubbla $group ger dig det format du vill ha genom att placera resultaten i en array per dag. Ett enda dokument i provet, men du får i princip resultat så här:

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

Om du tycker att resultaten från datumoperatorerna är för svåra att hantera eller vill ha ett förenklat "genomgångsresultat" för datumobjekt, kan du istället använda som epoktidsstämplar:

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

Tricket där är när du $subtract ett datumobjekt från ett annat får du "epok"-värdet tillbaka som ett resultat. I det här fallet använder vi "epokens" startdatum för att få hela tidsstämpelvärdet och tillhandahåller bara "datummatematiken" för att korrigera tiderna till de nödvändiga intervallen. Så resultatet:

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

Vilket kan vara mer tilltalande för dig än vad datumoperatörerna tillhandahåller beroende på dina behov.

Du kan också lägga till en liten förkortning för detta med MongoDB 2.6 via $let operator som låter dig deklarera "variabler" för scoped operationer:

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

Jag glömde också nästan att nämna att dina värden för "ping" och "länk" faktiskt är strängar om det inte är ett stavfel. Men om inte, se till att du konverterar dem som siffror först.




  1. Hur jag vet storleken på mitt dokument i MongoDB med ruby-drivrutinen

  2. pymongo.errors.ConnectionFailure:kunde inte ansluta till localhost:27017:[Errno 111] Anslutningen avvisades

  3. MongoDB kan inte starta servern:Standardlagringsmotorn 'wiredTiger' är inte tillgänglig med denna version av mongod

  4. Mongodb samling objekt total timmar samling