MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Gruppieren nach Datumsintervallen

Für das Aggregationsframework von MongoDB stehen Datumsaggregationsoperatoren zur Verfügung. Also zum Beispiel ein $dayOfYear -Operator wird verwendet, um diesen Wert aus dem Datum zur Verwendung in der Gruppierung abzurufen:

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

Oder Sie können stattdessen einen Datumsmathematikansatz verwenden. Indem Sie das Epochendatum anwenden, wandeln Sie das Datumsobjekt in eine Zahl um, auf die die Mathematik angewendet werden kann:

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

Wenn Sie nach Intervallen von einem aktuellen Zeitpunkt suchen, dann möchten Sie im Grunde den Ansatz der Datumsmathematik und das Arbeiten mit einigen Bedingungen über $cond Betreiber:

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

Es ist im Wesentlichen derselbe Ansatz wie im SQL-Beispiel, bei dem die Abfrage bedingt auswertet, ob der Datumswert in den erforderlichen Bereich fällt, und entscheidet, ob der Wert zur Summe hinzugefügt wird oder nicht.

Die einzige Ergänzung hier ist das zusätzliche $match Schritt, um die Abfrage so einzuschränken, dass sie nur auf die Elemente reagiert, die möglicherweise innerhalb des von Ihnen angeforderten Zeitraums von maximal einem Jahr liegen. Das macht es ein bisschen besser als das vorgestellte SQL, da ein Index verwendet werden könnte, um diese Werte herauszufiltern, und Sie nicht durch nicht übereinstimmende Daten in der Sammlung "roh erzwingen" müssen.

Es ist immer eine gute Idee, die Eingabe mit $match einzuschränken bei Verwendung einer Aggregationspipeline.