Convertire la data da millisecondi all’object ISODate

Sto cercando di aggregare i record in una conversazione di MongoDB per ora e ho bisogno di convertire la data memorizzata come timestamp (millisecondi) in ISODate in modo da poter utilizzare gli operatori di data built-in del framework aggregato ($ ora, $ mese, ecc.)

I record sono archiviati come

{ "data" : { "UserId" : "abc", "ProjId" : "xyz"}, "time" : NumberLong("1395140780706"), "_id" : ObjectId("532828ac338ed9c33aa8eca7") } 

Sto cercando di utilizzare una query aggregata del seguente tipo:

 db.events.aggregate( { $match : { "time" : { $gte : 1395186209804, $lte : 1395192902825 } } }, { $project : { _id : "$_id", dt : {$concat : (Date("$time")).toString()} // need to project as ISODate } }, // process records further in $project or $group clause ) 

che produce risultati della forma:

 { "result" : [ { "_id" : ObjectId("5328da21fd207d9c3567d3ec"), "dt" : "Fri Mar 21 2014 17:35:46 GMT-0400 (EDT)" }, { "_id" : ObjectId("5328da21fd207d9c3567d3ed"), "dt" : "Fri Mar 21 2014 17:35:46 GMT-0400 (EDT)" }, ... } 

Voglio estrarre ora, giorno, mese e anno dalla data, ma poiché il tempo è proiettato in avanti come stringa, non sono in grado di utilizzare gli operatori di data incorporati del framework aggregato ($ ora, ecc.).

Come posso convertire il tempo da millisecondi alla data ISO per fare in un momento simile al seguente:

 db.events.aggregate( { $match : { "time" : { $gte : 1395186209804, $lte : 1395192902825 } } }, { $project : { _id : "$_id", dt :  } }, { $project : { _id : "$_id", date : { hour : {$hour : "$dt"} } } } ) 

Presumo che non ci sia modo di farlo. Perché il framework di aggregazione è scritto in codice nativo. non facendo uso del motore V8. Quindi tutto ciò che riguarda JavaScript non funzionerà all’interno del framework (ed è anche per questo che il framework di aggregazione funziona molto più velocemente).
Map / Reduce è un modo per risolvere questo problema, ma il framework di aggregazione ha sicuramente ottenuto prestazioni molto migliori.

Informazioni su Mappa / Riduci prestazioni, leggi questa discussione .

Un altro modo per risolverlo sarebbe ottenere un risultato “grezzo” dal framework di aggregazione, metterlo in un array JSON. Quindi eseguire la conversione eseguendo JavaScript. Un po ‘come:

 var results = db.events.aggregate(...); reasult.forEach(function(data) { data.date = new Date(data.dateInMillionSeconds); // date is now stored in the "date" property } 

In realtà, è ansible, il trucco è aggiungere il tempo di millisecondi a un object Date () zero-millisecondi usando una syntax simile a:

 dt : {$add: [new Date(0), "$time"]} 

Ho modificato la tua aggregazione dall’alto per produrre il risultato:

 db.events.aggregate( { $project : { _id : "$_id", dt : {$add: [new Date(0), "$time"]} } }, { $project : { _id : "$_id", date : { hour : {$hour : "$dt"} } } } ); 

Il risultato è (con una voce dei dati di esempio):

 { "result": [ { "_id": ObjectId("532828ac338ed9c33aa8eca7"), "date": { "hour": 11 } } ], "ok": 1 } 

Per restituire una data BSON valida, tutto ciò di cui hai bisogno è una piccola data “matematica” usando l’operatore $add . È necessario aggiungere una new Date(0) al timestamp. La new Date(0) rappresenta il numero di millisecondi dall’epoca Unix (1 gennaio 1970) ed è una scorciatoia per la new Date("1970-01-01") .

 db.events.aggregate([ { "$match": { "time": { "$gte" : 1395136209804, "$lte" : 1395192902825 } } }, { "$project": { "hour": { "$hour": { "$add": [ new Date(0), "$time" ] } }, "day": { "$dayOfMonth": { "$add": [ new Date(0), "$time" ] } }, "month": { "$month": { "$add": [ new Date(0), "$time" ] } }, "year": { "$year": { "$add": [ new Date(0), "$time" ] } } }} ]) 

Quale produce:

 { "_id" : ObjectId("532828ac338ed9c33aa8eca7"), "hour" : 11, "day" : 18, "month" : 3, "year" : 2014 } 

usalo se {$add: [new Date(0), "$time"] } la funzione che restituisce il string type non è un ISO date type

Uso tutta questa opzione, ma fallisco, perché la mia nuova data da $project restituisce un string type come '2000-11-2:xxxxxxx' non di date type come ISO('2000-11-2:xxxxxxx') per chiunque ho lo stesso problema con me usare questo.

 db.events.aggregate( { $project : { _id : "$_id", dt : {$add: [new Date(0), "$time"]} } }, { $project : { _id : "$_id", "year": { $substr: [ "$dt", 0, 4 ] }, "month": { $substr: [ "$dt", 5, 2] }, "day": { $substr: [ "$dt", 8, 2 ] } } } ); 

il risultato sarà

  { _id: '59f940eaea87453b30f42cf5', year: '2017', month: '07', day: '04' }, 

puoi ottenere ore o minuti se vuoi, a seconda della string che vuoi subset , quindi puoi group nuovo in base alla stessa data, mese o anno