sql >> Databáze >  >> NoSQL >> MongoDB

Agregace Mongodb podle dne a poté po hodině

V zásadě chcete dvojité seskupení, ale pomocí operátory agregace dat , pouze příslušné části:

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

Dvojitá $group vám poskytne požadovaný formát umístěním výsledků do pole za den. Jeden dokument v ukázce, ale v zásadě získáte výsledky takto:

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

Pokud se vám zdá, že je obtížné se s výsledky operátorů data vypořádat nebo chcete zjednodušený „průchozí“ výsledek pro objekty data, můžete místo toho přetypovat jako časová razítka epoch:

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

Trik je v tom, když $subtract jeden objekt data od jiného, ​​dostanete jako výsledek hodnotu "epoch" zpět. V tomto případě použijeme počáteční datum "epochy" k získání celé hodnoty časového razítka a pouze poskytneme "matematiku data" pro opravu časů na požadované intervaly. Takže výsledek:

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

Což vám může být chutnější než to, co ve výsledku poskytují operátoři data v závislosti na vašich potřebách.

Můžete také přidat malou zkratku s MongoDB 2.6 prostřednictvím $let operátor, který vám umožňuje deklarovat "proměnné" pro operace s rozsahem:

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

Také jsem málem zapomněl zmínit, že vaše hodnoty pro "ping" a "link" jsou ve skutečnosti řetězce, pokud to není překlep. Ale pokud ne, ujistěte se, že je nejprve převedete jako čísla.




  1. Musím před vložením do MongoDB dezinfikovat uživatelský vstup (kombo MongoDB+Node js)

  2. Jak zesměšňovat rozhraní IFindFluent

  3. Mongoose - RangeError:Maximální velikost zásobníku hovorů překročena

  4. vložte pole do mongodb pomocí pymongo