繁体   English   中英

查找过去7天的当天的最后一份文件

[英]Find last document of the day for the last 7 days

我每小时都会在架构中添加条目,以便跟踪几天内的增长情况,同时保持当前一天的当前得分。 现在,我希望能够获取过去一周每天的最新记录。 结果将是前6天午夜或前后的6条记录,而第7条是当天的最新记录。

这是我的架构:

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

编辑

我试过使用此静态,但它提取相同的记录7次

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

如果我使用的是SQL,我将选择MAXDATE进行子查询,并将其加入我的主查询中,以检索所需的结果。 无论如何要在这里做?

克里斯蒂娜(Kristina Chodorow)在她的《 MongoDB:权威指南 》( MongoDB:The Definitive Guide)一书中详细介绍了该任务的详细配方

假设我们有一个跟踪股价的站点。 从上午10点到下午4点每隔几分钟,它将获取最新的股票价格,并将其存储在MongoDB中。 现在,作为报表应用程序的一部分,我们希望找到过去30天的收盘价。 使用组可以很容易地做到这一点。

我对猫鼬不熟悉,但是我尝试将她的示例调整为适合您的以下情况。 注意,我将createdAt default属性从一个值更改为一个函数,并向您的模式添加了一个额外的字段datestamp

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

);

一种解决方案是使用group()按天对记录进行分组。 它花哨,缓慢且可能会阻塞(意味着其他任何东西都无法同时运行),但是如果您的记录集不是太大,那么它就非常强大。

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

至于猫鼬,我不确定它是否直接支持group(),但是您可以通过执行以下操作(主要是伪代码)来使用node-mongodb-native实现:

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

群组和地图之间的其他一些比较从我的博客中减少了: http : //j-query.blogspot.com/2011/06/mongodb-performance-group-vs-find-vs.html

本机驱动程序中没有有关group命令的文档,因此您必须在此处浏览源代码: https : //github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/ collection.js

同样要进行排序,请检查https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort以获取确切的语法

编辑:更好的主意!

只需有一个名为“ lastRequestOfDay”的特殊集合,并将_id设置为当天即可。 用每个新请求覆盖值。 这将是超级容易查询和快速编写的方法,并且总是每天都有最后写入的值!

将另一个属性添加到名为dateAdded的架构中。

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

尝试这样的事情:

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

似乎没人试图“接近午夜”。 :)我在原始代码中看到的问题是它检查的时间大于或等于x天前……这将始终返回最近的时间。 我对为什么DeaDEnD的解决方案会返回7次相同的记录感到困惑。 另外,您从未致电过fn ,但这并不是您最担心的问题,不是吗?

尝试添加.lt(now - (now % oneday) - (i - 1) * oneday) (假设0索引;如果是1索引,则改成i - 2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM