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

Mongodb - forespørg om dagens totaler, uges totaler og måneds totaler i én forespørgsel

Dette er mere virkelig et spørgsmål om, hvordan du forventer, at output skal se ud, da ethvert aggregeret resultat i det væsentlige skal grupperes på det laveste niveau og derefter gradvist grupperes ved højere "korn", indtil det største niveau ("måned") er nået. Denne form for indebærer data grupperet efter "måned" i sidste ende, medmindre du opdeler dem på anden måde.

I det væsentlige, gradvist $group :

db.collection.aggregate([
    // First total per day. Rounding dates with math here
    { "$group": {
        "_id": {
            "$add": [
                { "$subtract": [
                    { "$subtract": [ "$createdAt", new Date(0) ] },
                    { "$mod": [
                        { "$subtract": [ "$createdAt", new Date(0) ] },
                        1000 * 60 * 60 * 24
                    ]}                        
                ]},
                new Date(0)
            ]
        },
        "week": { "$first": { "$week": "$createdAt" } },
        "month": { "$first": { "$month": "$createdAt" } },
        "total": { "$sum": "$num" }
    }},

    // Then group by week
    { "$group": {
        "_id": "$week",
        "month": { "$first": "$month" },
        "days": {
            "$push": {
                "day": "$_id",
                "total": "$total"
            }
        },
        "total": { "$sum": "$total" }
    }},

    // Then group by month
    { "$group": {
        "_id": "$month",
        "weeks": {
            "$push": {
                "week": "$_id",
                "total": "$total",
                "days": "$days"
            }
        },
        "total": { "$sum": "$total" }
    }}
])

Så hvert niveau efter det første, som opsummerer pr. dag, skubbes derefter gradvist ind i matrixindholdet for dets "runde op"-værdi, og totalerne summeres derefter også på det niveau.

Hvis du vil have et fladere output med én post pr. dag, der indeholder dets ugentlige og månedlige totaler samt det samlede antal dage, skal du blot tilføje to $unwind udsagn til slutningen af ​​pipelinen:

{ "$unwind": "$weeks" },
{ "$unwind": "$weeks.days" }

Og eventuelt $project de "prikkede" felter ud til noget fladere og læsbart, hvis du skal.

Hvis du spænder over "år" med dette, så inkluder en sådan operation i grupperingsnøglen i det mindste fra "uge"-niveauet, så du muligvis ikke kombinerer data fra forskellige år, og de er adskilt.

Det er også min egen generelle præference at bruge "date math" tilgang ved afrunding af datoer, da den returnerer en Date objekt, men som det bruges på de andre niveauer end "dag", kan du bare skiftevis bruge datoaggregationsoperatører i stedet.

Intet behov for mapReduce da dette er ret intuitivt, og der er et begrænset antal dage i en måned, betyder det, at BSON-grænsen, når indlejring af arrays i indholdet, mens aggregering ikke vil blive brudt.




  1. Java Spring Mongo Sort Ignorer sag problem

  2. Mongo:samle $geoNear og $text ingen resultater

  3. Hvordan forhindrer jeg _t-feltet i at blive vist, når jeg opretter ind i MongoDB?

  4. Forbindelse nægtet af Docker-container