sql >> Databasteknik >  >> NoSQL >> MongoDB

Gruppera resultat med 15 minuters tidsintervall i MongoDb

Det finns ett par sätt att göra detta.

Den första är med Date Aggregation Operators, som låter dig dissekera "datum"-värdena i dokument. Specifikt för "gruppering" som den primära avsikten:

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

Det andra sättet är att använda ett litet trick för att när ett datumobjekt subtraheras (eller annan direkt matematisk operation) från ett annat datumobjekt, då blir resultatet ett numeriskt värde som representerar epoktidsstämpeln millisekunder mellan de två objekten. Så bara genom att använda epokdatumet får du representationen av epokmillisekunder. Använd sedan datummatematik för intervallet:

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

Så det beror på vilken typ av utdataformat du vill ha för grupperingsintervallet. Båda representerar i princip samma sak och har tillräckligt med data för att rekonstruera som ett "datum"-objekt i din kod.

Du kan lägga allt annat du vill i "grupperingsoperator"-delen efter grupperingen _id . Jag använder bara det grundläggande "räkneexemplet" istället för alla verkliga uttalanden från dig själv om vad du verkligen vill göra.

MongoDB 4.x och uppåt

Det har gjorts några tillägg till Date Aggregation Operators sedan den ursprungliga skrivningen, men från MongoDB 4.0 kommer det att finnas faktisk "riktig gjutning av typer" i motsats till de grundläggande matematiska tricken som görs här med BSON Date-konvertering.

Vi kan till exempel använda $toLong och $toDate som nya medhjälpare här:

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

Det är lite kortare och kräver inte att man definierar ett externt BSON-datum för "epok"-värdet som en konstant för att definiera pipelinen så det är ganska konsekvent för alla språkimplementeringar.

Det är bara två av "hjälpmetoderna" för typkonvertering som alla kopplar tillbaka till $convert metod, som är en "längre" form av implementeringen som tillåter anpassad hantering på null eller fel i konverteringen.

Det är till och med möjligt med sådan casting att få Date information från ObjectId av primärnyckeln, eftersom detta skulle vara en pålitlig källa för "skapande" datum:

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

Så "casting-typer" med den här typen av konvertering kan vara ett ganska kraftfullt verktyg.

Varning - ObjectId värden är begränsade till precision till sekund endast för det interna tidsvärde som utgör en del av deras data som tillåter $toDate omvandling. Den faktiska insatta "tiden" är troligen beroende av drivrutinen som används. Där precision krävs, rekommenderas det fortfarande att använda ett diskret BSON-datumfält istället för att förlita sig på ObjectId värden.



  1. Websocket Disconnected Anslut samtalet misslyckades

  2. Installera Apache CouchDB på Debian 9

  3. Hur vet man master/slav status för redis?

  4. $strLenBytes vs $strLenCP i MongoDB:Vad är skillnaden?