javascript - style - getelementsbytagname




Trouver le dernier document du jour pour les 7 derniers jours (4)

Une solution consiste à utiliser group () pour regrouper les enregistrements par jour. Il est sophistiqué, lent et peut bloquer (ce qui signifie que rien d'autre ne peut fonctionner en même temps), mais si votre jeu d'enregistrements n'est pas trop gros, c'est assez puissant.

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

Quant à mongoose, je ne suis pas sûr qu'il supporte directement group (), mais vous pouvez utiliser l'implémentation node-mongodb-native, en faisant quelque chose comme ça (pseudo-code, pour la plupart):

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

Quelques comparaisons de plus entre les groupes et la carte réduisent de mon blog: http://j-query.blogspot.com/2011/06/mongodb-performance-group-vs-find-vs.html

Il n'y a pas de documentation sur la commande de groupe dans le pilote natif, donc vous devrez regarder le code source ici: https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/ collection.js

Pour le tri, vérifiez aussi https://developer.mozilla.org/fr/JavaScript/Reference/Global_Objects/Array/sort pour la syntaxe exacte

Edit: Meilleure idée !!!

Ayez juste une collection spéciale appelée "lastRequestOfDay" et faites le _id le jour. Remplacez la valeur à chaque nouvelle demande. Ce sera super facile à interroger et rapide à écrire et aura toujours la dernière valeur écrite chaque jour!

J'ajoute des entrées à un schéma toutes les heures afin de suivre la croissance au fil des jours tout en maintenant un score actuel pour la journée en cours. Maintenant, je voudrais être en mesure de tirer le record le plus récent pour chaque jour de la semaine dernière. Les résultats seraient 6 enregistrements à minuit ou autour de minuit pour les 6 jours précédents et le 7ème étant le dernier pour la journée en cours.

Voici mon schéma:

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

modifier

J'ai essayé d'utiliser ce statique, mais il tire exactement le même enregistrement 7 fois

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 j'utilisais SQL, je ferais une sous-requête en sélectionnant MAXDATE et je le joindrais à ma requête principale pour récupérer les résultats que je veux. De toute façon pour le faire ici?


Ajoutez une autre propriété au schéma nommé dateAdded ou quelque chose.

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

Personne ne semble essayer "près de minuit". :) Le problème que j'ai vu avec le code original était qu'il vérifiait un temps supérieur ou égal à x jours auparavant ... qui retournera toujours l'heure la plus récente. Je suis confus quant à savoir pourquoi la solution de DeaDEnD renvoie le même enregistrement 7 fois, cependant. De plus, vous n'avez jamais appelé fn , mais ce n'est pas vraiment la plus grande de vos préoccupations, n'est-ce pas?

Essayez d'ajouter .lt(now - (now % oneday) - (i - 1) * oneday) (en supposant que 0- .lt(now - (now % oneday) - (i - 1) * oneday) , si c'est 1-indexed, changez cela pour dire i - 2 )


Kristina Chodorow donne une recette détaillée pour cette tâche exacte dans son livre MongoDB: The Definitive Guide :

Supposons que nous ayons un site qui garde la trace des cours boursiers. Toutes les quelques minutes de 10 heures à 16 heures, il obtient le dernier prix pour un stock, qu'il stocke dans MongoDB. Maintenant, dans le cadre d'une application de reporting, nous voulons trouver le cours de clôture des 30 derniers jours. Cela peut être facilement accompli en utilisant le groupe.

Je ne suis pas familier avec Mongoose, mais j'ai essayé d'adapter son exemple à votre cas ci-dessous. Remarque J'ai changé la propriété default createdAt d'une valeur en une fonction et ajouté un datestamp champ datestamp à votre schéma:

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()

);




mongoose