【问题标题】:Updating nested arrays with mongoose使用 mongoose 更新嵌套数组
【发布时间】:2016-05-03 05:35:14
【问题描述】:

所以我基本上是在为我的代码开发时间序列模式;

var GameStatisticsSchema = new mongoose.Schema({
game: { type: mongoose.Schema.ObjectId, ref: 'Game', required: true }, 
months: [
  { // monthly viewers
      epoch: { type: Number, required: true }, // entry time stamp
      weeks: [
        { // weekly viewers
            epoch: { type: Number, required: true }, // entry time stamp
            days: [
              { // daily viewers
                  epoch: { type: Number, required: true }, // entry time stamp
                  hours: [
                    { // hourly viewers
                      epoch: { type: Number, required: true }, // entry time stamp
                      statistics: [
                        { // per minute statistics.
                            viewers: { type: Number },
                            channels: { type: Number },
                        }]
                  }]
            }]
      }]
}]
});

基本上数据存储为 - 所以我可以根据自己的喜好查询每天、每分钟、每周的数据;

{ 
"_id" : ObjectId("56a78e337a9a34f8a368f719"), 
"game" : ObjectId("56a6f0b5bbfbbad0550450ee"), 
"months" : {
    "1" : {
        "weeks" : {
            "5" : {
                "days" : {
                    "26" : {
                        "hours" : {
                            "17" : {
                                "statistics" : {
                                    "18" : {
                                        "channels" : NumberInt(46), 
                                        "viewers" : NumberInt(308)
                                    }
                                }, 
                                "epoch" : NumberInt(1453820400)
                            }
                        }, 
                        "epoch" : NumberInt(1453759200)
                    }
                }, 
                "epoch" : NumberInt(1453672800)
            }
        }, 
        "epoch" : NumberInt(1451599200)
    }
}, 
"__v" : NumberInt(0)
}

基本上我使用 findOneAndUpdate() 来插入我的每分钟传感器数据;

function updateStatistics(game, data) {

 return new Promise(function (resolve, reject) {

    // get current time
    var now = moment();

    var minute = now.minute();
    var hour = now.hour();
    var day = now.date();
    var week = now.week();
    var month = now.month() + 1; // moment months are 0 indexed

    // we'll store per hour, day, week and month subdocuments. so set the epochs for those.
    var update = {};
    update["months." + month + ".epoch"] = moment().startOf('month').unix();
    update["months." + month + ".weeks." + week + ".epoch"] = moment().startOf('isoWeek').unix();
    update["months." + month + ".weeks." + week + ".days." + day + ".epoch"] = moment().startOf('day').unix();
    update["months." + month + ".weeks." + week + ".days." + day + ".hours." + hour + ".epoch"] = moment().startOf('hour').unix();

    // set the viewers & channels.
    update["months." + month + ".weeks." + week + ".days." + day + ".hours." + hour + ".statistics." + minute + ".viewers"] =  data.viewers;
    update["months." + month + ".weeks." + week + ".days." + day + ".hours." + hour + ".statistics." + minute + ".channels"] =  data.channels;

    GameStatistics.findOneAndUpdate(
      { "game": game._id },
      { $set: update },
      {
          new: true, // return the updated document
          upsert: true, // create the document if does not exist
          runValidators: true,
          setDefaultsOnInsert: true
      },
      function(err, document) {

          if(err)
            reject(err);

          resolve();
      }
    );
  });
  }

问题是,一旦我启用;

runValidators: true,
setDefaultsOnInsert: true

我的验证器将触发异常;

 Cannot update 'months.1.epoch' and 'months' at the same time

因此,如果我禁用 runValidators,我可以按原样存储数据,但文档会变成无模式 - 并与此相同;

var GameStatisticsSchema = new mongoose.Schema({
game: { type: mongoose.Schema.ObjectId, ref: 'Game', required: true }, 
months: [ { type: mongoose.Schema.Mixed }]

});

那么您可以建议任何解决方法吗?

我使用启用了翻转的 findOneAndUpdate 的原因是,没有它我不知道如何创建嵌套数组值和 save() 文档。

请记住 - 对于 26.01.2015 15:35:13,代码需要插入其中;

months[1].weeks[5].days[26].hours[15].minutes[35].statistics.{
 viewers = 25;
 channels = 50
}

【问题讨论】:

    标签: arrays mongodb mongoose nested


    【解决方案1】:

    为什么不单独设置时间戳?

    var GameStatisticsSchema = new mongoose.Schema({
        game: { type: mongoose.Schema.ObjectId, ref: 'Game', required: true  }, 
        timestamp: { type: DateTime },
        viewers: { type: Number },
        channels: { type: Number }
    });
    

    这使得更新变得简单,您可以使用 dateTime 查询月/日/等。

    上个月的查询是:

    { game: gameId, timestamp: { $gt: <date from a month ago>}}
    

    但是你需要使用我不太熟悉的 mongoose 聚合函数。

    https://docs.mongodb.org/manual/reference/operator/aggregation/avg/

    http://mongoosejs.com/docs/api.html#aggregate-js

    【讨论】:

    • 因为我想获得每周、每天、每小时、每月的数据。根据您的建议,鉴于时间戳数据频率是每分钟,您将只能查询每分钟数据。使用我当前的模式,我可以通过平均我需要的日期范围的值来查询例如每周数据。
    • 你可以对日期查询做同样的事情,平均所有结果:find({ date: { $gt: new Date(2016, 0, 1), $lt: new Date(2016, 1) , 1) }}) 用于 1 月份的所有统计数据
    • 好的,请告诉我如何使用它获取过去 4 周的数据?通过平均我的意思是,我可以挂钩模式更新并计算文档的每个周期平均值,然后这将是一个简单的访问操作。
    猜你喜欢
    • 2017-01-24
    • 2020-10-09
    • 2016-10-06
    • 1970-01-01
    • 2020-07-26
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多