所以我基本上为我的代码开发了一个时间序列模式;
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 }]
});
您可以建议任何变通方法吗?
我使用upset启用findOneAndUpdate的原因是,如果没有我不知道如何创建嵌套数组值并保存()文档。
请记住 - 对于2015年1月26日15:35:13,代码需要插入到此中;
months[1].weeks[5].days[26].hours[15].minutes[35].statistics.{
viewers = 25;
channels = 50
}
答案 0 :(得分:0)
为什么不单独有时间戳?
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>}}
但是你需要使用我不太熟悉的猫鼬聚合函数。
https://docs.mongodb.org/manual/reference/operator/aggregation/avg/