sql >> Database teknologi >  >> NoSQL >> MongoDB

Mongodb Aggregation efter Dag derefter Time

Det du grundlæggende ønsker er en dobbelt gruppering, men du får ikke hele datoobjektet tilbage ved at bruge datoaggregationsoperatører , kun de relevante dele:

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 dobbelte $group giver dig det format, du ønsker, ved at placere resultaterne i en matrix pr. dag. Enkelt dokument i prøven, men du får grundlæggende resultater som dette:

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

Hvis du finder resultaterne af datooperatorerne for svære at håndtere eller ønsker et forenklet "pass-through"-resultat for datoobjekter, så kan du i stedet kaste som epoketidsstempler:

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 derinde er, når du $subtract et datoobjekt fra et andet får du "epoke"-værdien tilbage som et resultat. I dette tilfælde bruger vi "epoken"-startdatoen til at få hele tidsstemplets værdi og angiver blot "datomatematikken" for at rette tiderne til de nødvendige intervaller. Så resultatet:

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

Hvilket måske er mere velsmagende for dig end hvad datooperatørerne giver som et resultat afhængigt af dine behov.

Du kan også tilføje en lille stenografi til dette med MongoDB 2.6 via $let operator, der tillader dig at erklære "variabler" for 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"
           }
       }
    }}
])

Også jeg glemte næsten at nævne, at dine værdier for "ping" og "link" faktisk er strenge, medmindre det er en tastefejl. Men hvis ikke, så sørg for at konvertere dem som tal først.




  1. MEAN-Stack gem et array i MongoDB med mongoose

  2. Udfyld specifikke felter i $lookup

  3. MongoDB Kafka Sink Connector behandler ikke RenameByRegex-processoren

  4. Spring Boot Data og MongoDB - Filter Subdocument Array Query