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

Gruppieren Sie das Ergebnis nach 15-Minuten-Zeitintervall in MongoDb

Dafür gibt es mehrere Möglichkeiten.

Die erste ist mit Datumsaggregationsoperatoren, mit denen Sie die "Datums"-Werte in Dokumenten analysieren können. Speziell für "Gruppierung" als primäre Absicht:

db.collection.aggregate([
  { "$group": {
    "_id": {
      "year": { "$year": "$created_at" },
      "dayOfYear": { "$dayOfYear": "$created_at" },
      "hour": { "$hour": "$created_at" },
      "interval": {
        "$subtract": [ 
          { "$minute": "$created_at" },
          { "$mod": [{ "$minute": "$created_at"}, 15] }
        ]
      }
    }},
    "count": { "$sum": 1 }
  }}
])

Die zweite Möglichkeit besteht darin, einen kleinen Trick zu verwenden, wenn ein Datumsobjekt (oder eine andere direkte mathematische Operation) von einem anderen Datumsobjekt subtrahiert wird, dann ist das Ergebnis ein numerischer Wert, der den Zeitstempel der Epoche in Millisekunden zwischen den beiden Objekten darstellt. Wenn Sie also nur das Epochendatum verwenden, erhalten Sie die Millisekundendarstellung der Epoche. Verwenden Sie dann Datumsmathematik für das Intervall:

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

Es hängt also davon ab, welches Ausgabeformat Sie für das Gruppierungsintervall wünschen. Beide stellen im Grunde dasselbe dar und haben genügend Daten, um sie als "Datums"-Objekt in Ihrem Code zu rekonstruieren.

Sie können im Abschnitt "Gruppierungsoperator" nach der Gruppierungs-_id alles andere einfügen, was Sie möchten . Ich verwende nur das grundlegende "Zählen"-Beispiel anstelle einer echten Aussage von Ihnen darüber, was Sie wirklich tun möchten.

MongoDB 4.x und höher

Seit dem ursprünglichen Schreiben gab es einige Ergänzungen zu Datumsaggregationsoperatoren, aber ab MongoDB 4.0 wird es im Gegensatz zu den grundlegenden mathematischen Tricks, die hier mit der BSON-Datumskonvertierung durchgeführt werden, tatsächlich ein „echtes Casting von Typen“ geben.

Zum Beispiel können wir $toLong verwenden und $toDate als neue Helfer hier:

db.collection.aggregate([
  { "$group": {
    "_id": {
      "$toDate": {
        "$subtract": [
          { "$toLong": "$created_at" },
          { "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
        ]
      }
    },
    "count": { "$sum": 1 }
  }}
])

Das ist etwas kürzer und erfordert kein Definieren eines externen BSON-Datums für den „Epochen“-Wert als Konstante beim Definieren der Pipeline, sodass es für alle Sprachimplementierungen ziemlich konsistent ist.

Dies sind nur zwei der "Hilfsmethoden" für die Typkonvertierung, die alle auf $convert zurückgreifen -Methode, die eine "längere" Form der Implementierung ist, die eine benutzerdefinierte Behandlung von null ermöglicht oder Konvertierungsfehler.

Mit einem solchen Casting ist es sogar möglich, das Date zu erhalten Informationen aus der ObjectId des Primärschlüssels, da dies eine zuverlässige Quelle für das "Erstellungsdatum" wäre:

db.collection.aggregate([
  { "$group": {
    "_id": {
      "$toDate": {
        "$subtract": [
          { "$toLong": { "$toDate": "$_id" }  },
          { "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
        ]
      }
    },
    "count": { "$sum": 1 }
  }}
])

"Typen umwandeln" mit dieser Art von Konvertierung kann also ein ziemlich mächtiges Werkzeug sein.

Warnung - ObjectId Werte sind auf Sekunde begrenzt nur für den internen Zeitwert, der einen Teil ihrer Daten ausmacht und den $toDate ermöglicht Wandlung. Die tatsächlich eingefügte "Zeit" hängt höchstwahrscheinlich vom verwendeten Treiber ab. Wo Präzision erforderlich ist, wird dennoch empfohlen, ein diskretes BSON-Datumsfeld zu verwenden, anstatt sich auf ObjectId zu verlassen Werte.