sql >> Databasteknik >  >> NoSQL >> MongoDB

Gruppera efter datumintervall

Det finns datumaggregationsoperatörer tillgängliga för aggregationsramverket för MongoDB. Så till exempel en $dayOfYear operatorn används för att hämta det värdet från datumet för användning i gruppering:

db.collection.aggregate([
    { "$group": {
        "_id": { "$dayOfYear": "$datetime" },
        "total": { "$sum": "$count" }
    }}
])

Eller så kan du använda en datummatematik istället. Genom att använda epokdatumet konverterar du datumobjektet till ett tal där matematiken kan tillämpas:

db.collection.aggregate([
    { "$group": {
        "_id": { 
            "$subtract": [
                { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                { "$mod": [
                    { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                    1000 * 60 * 60 * 24
                ]}
            ]
        },
        "total": { "$sum": "$count" }
    }}
])

Om det du är ute efter är intervaller från en aktuell tidpunkt så är det du vill ha i princip datummatematiken och att arbeta i vissa villkor via $cond operatör:

db.collection.aggregate([
    { "$match": {
        "datetime": { 
            "$gte": new Date(new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 ))
        }
    }},
    { "$group": {
        "_id": null,
        "24hours": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 )
                    ]},
                    "$count",
                    0
                ]
            }
        },
        "30days": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 30 )
                    ]},
                    "$count",
                    0
                ]
            }
        },
        "OneYear": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 )
                    ]},
                    "$count",
                    0
                ]
            }
        }
    }}
])

Det är i huvudsak samma tillvägagångssätt som SQL-exemplet, där frågan villkorligt utvärderar om datumvärdet faller inom det obligatoriska intervallet och bestämmer om värdet ska läggas till summan eller inte.

Det enda tillägget här är den ytterligare $match steg för att begränsa frågan till att endast agera på de objekt som eventuellt skulle ligga inom det maximala ettårsintervallet du efterfrågar. Det gör den lite bättre än den presenterade SQL-en eftersom ett index kan användas för att filtrera bort dessa värden och du behöver inte "brute force" genom icke-matchande data i samlingen.

Alltid en bra idé att begränsa inmatningen med $match när du använder en aggregeringspipeline.



  1. HBase-uppgradering ovanpå Event Sourcing och CQRS-arkitektur på 3 veckor

  2. NodeJS - anslut säkert till extern redis-server

  3. Hur kan jag lösenordsskydda min /sidekiq-rutt (dvs. kräver autentisering för Sidekiq::Web-verktyget)?

  4. MongoDB infogar float när man försöker infoga heltal