vitae varios validar una tutorial tecnico subdocumentos subconsultas sexuales recursos principiantes para pagina node mujer mostrar mientras mayor libro laboral jefe insertar imagenes igual humanos hombre hacia hacer funcion formulario experiencia examples ejemplos ejemplo ejecutar documentos despues deseos desde curriculum consultas como comandos chrome cero cargar carga caracteristicas basicas avanzado avanzadas asincrona antes activar javascript node.js mongodb mongoose

javascript - varios - Encuentra el último documento del día durante los últimos 7 días



subconsultas en mongodb (5)

Agregue otra propiedad al esquema llamado dateAdded o algo así.

schema.statics.getLastWeek = function(name, fn) { var oneday = 60 * 60 * 24 , now = Date.now() , docs = [] for (var i = 0; i < 7; i++) { this.where(''name'', new RegExp(name, ''i'')) .where(''createdAt'') .lt(now - (i * oneday)) .gte(now - ((i + 1) * oneday)) .desc(''createdAt'') .findOne(function(err,doc){ // might not always find one docs.push(doc) }) } return fn(null, docs) }

Estoy agregando entradas a un esquema cada hora con el fin de rastrear el crecimiento en el transcurso de los días, manteniendo un puntaje actual para el día actual. Ahora me gustaría poder obtener el registro más reciente de cada día de la semana pasada. Los resultados serían 6 registros alrededor de la medianoche durante 6 días previos y el 7mo será el más reciente para el día actual.

Aquí está mi esquema:

var schema = new Schema({ aid: { type: Number } , name: { type: String } , score: { type: Number } , createdAt: { type: Date, default: Date.now() } })

Editar

Intenté usar esta estática, pero saca exactamente el mismo registro 7 veces

schema.statics.getLastWeek = function(name, fn) { var oneday = 60 * 60 * 24 , now = Date.now() , docs = [] for (var i = 1; i <= 7; i++) { this.where(''name'', new RegExp(name, ''i'')) .where(''createdAt'') .gte(now - (i * oneday)) .desc(''createdAt'') .findOne(function(err,doc){ docs.push(doc) }) } }

Si estuviera usando SQL, haría una subconsulta seleccionando MAXDATE y unirla a mi consulta principal para recuperar los resultados que deseo. De todos modos para hacer esto aquí?


Una solución es usar grupos () para agrupar registros por día. Es elegante, lento y puede bloquear (es decir, nada más se puede ejecutar al mismo tiempo), pero si el conjunto de registros no es demasiado grande, es bastante potente.

Grupo: http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group

En cuanto a la mangosta, no estoy seguro de si admite group () directamente, pero puede usar la implementación node-mongodb-native, haciendo algo como esto (pseudo-código, en su mayoría):

schema.statics.getLastWeek = function(name, cb) { var keys = {} // can''t remember what this is for var condition = {} // maybe restrict to last 7 days var initial = {day1:[],day2:[],day3:[],day4:[],day5:[],day6:[],day7:[]} var reduce = function(obj, prev) { // prev is basically the same as initial (except with whatever is added) var day = obj.date.slice(0,-10) // figure out day, however it works prev["day" + day].push(obj) // create grouped arrays // you could also do something here to sort by _id // which is probably also going to get you the latest for that day // and use it to replace the last item in the prev["day" + 1] array if // it''s > that the previous _id, which could simplify things later } this.collection.group(keys, condition, initial, reduce, function(err, results) { // console.log(results) var days = results // it may be a property, can''t remember var lastDays = {} days.forEach(function(day) { // sort each day array and grab last element lastDays[day] = days[day].sort(function(a, b) { return a.date - b.date // check sort syntax, you may need a diff sort function if it''s a string }).slice(-1) // i think that will give you the last one }) cb(lastDays) // your stuff }) }

Algunas comparaciones más entre grupos y mapa se reducen desde mi blog: http://j-query.blogspot.com/2011/06/mongodb-performance-group-vs-find-vs.html

No hay documentos sobre el comando de grupo en el controlador nativo, por lo que tendrá que leer el código fuente aquí: https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/ collection.js

También para ordenar, verifique https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort para obtener una sintaxis exacta

Editar: ¡Mejor idea!

Solo tiene una colección especial llamada "lastRequestOfDay" y haga que _id el día. Sobrescriba el valor con cada nueva solicitud. ¡Será súper fácil de consultar y rápido de escribir y siempre tendrá el último valor escrito cada día!


Nadie parece estar intentando "cerca de la medianoche". :) El problema que vi con el código original fue que se verificó por un tiempo mayor o igual a x días atrás ... que siempre devolverá la hora más reciente. Sin embargo, estoy confundido sobre por qué la solución de DeaDEnD devuelve el mismo registro 7 veces. Además, nunca fn , pero esa no es realmente la mayor de tus preocupaciones, ¿o sí?

Intente agregar .lt(now - (now % oneday) - (i - 1) * oneday) (suponiendo 0-indexado; si está indexado en 1, cámbielo para decir i - 2 )


Pruebe algo como esto:

schema.statics.getLastWeek = function(name, fn) { var oneday = 60 * 60 * 24 , now = Date.now() , docs = [] , that = this function getDay(day){ that.where(''name'', new RegExp(name, ''i'')) .where(''createdAt'') .gte(now - (day * oneday)) .desc(''createdAt'') .findOne(function(err,doc){ docs.push(doc) }) } for (var i = 1; i <= 7; i++) { getDay(i); } }


Kristina Chodorow brinda una receta detallada para esta tarea exacta en su libro MongoDB: The Definitive Guide :

Supongamos que tenemos un sitio que realiza un seguimiento de los precios de las acciones. Cada pocos minutos, de 10 a.m. a 4 p.m., obtiene el último precio de una acción que almacena en MongoDB. Ahora, como parte de una aplicación de informes, queremos encontrar el precio de cierre de los últimos 30 días. Esto se puede lograr fácilmente usando un grupo.

No estoy familiarizado con Mongoose, sin embargo, he tratado de adaptar su ejemplo a su caso a continuación. Tenga en cuenta que cambié la propiedad createdAt default de un valor a una función y agregué una fecha de campo datestamp a su esquema:

var oneday = 24 * 60 * 60; var schema = new Schema({ aid: { type: Number } , name: { type: String } , score: { type: Number } // default: is a function and called every time; not a one-time value! , createdAt: { type: Date, default: Date.now } // For grouping by day; documents created on same day should have same value , datestamp: { type: Number , default: function () { return Math.floor(Date.now() / oneday); } } }); schema.statics.getLastWeek = function(name, fn) { var oneweekago = Date.now() - (7 * oneday); ret = this.collection.group({ // Group by this key. One document per unique datestamp is returned. key: "datestamp" // Seed document for each group in result array. , initial: { "createdAt": 0 } // Update seed document if more recent document found. , reduce: function(doc, prev) { if (doc.createdAt > prev.createdAt) { prev.createdAt = doc.createdAt; prev.score = doc.score; // Add other fields, if desired: prev.name = doc.name; } // Process only documents created within past seven days , condition: { "createdAt" : {"$gt": oneweekago} } }}); return ret.retval; // Note ret, the result of group() has other useful fields like: // total "count" of documents, // number of unique "keys", // and "ok" is false if a problem occurred during group() );