gpt4 book ai didi

node.js - MongoDB 聚合组最近 7 天的平均评分,值为空

转载 作者:可可西里 更新时间:2023-11-01 10:00:38 26 4
gpt4 key购买 nike

我正在尝试查询一个集合并检索过去 7 天(不包括当天)每一天的平均值。在某些或所有的日子里,可能没有平均值。

这是我目前所拥有的:

var dateTill = moment({hour:0,minute:0}).subtract(1, 'days')._d
var dateSevenDaysAgo = moment({hour:0,minute:0}).subtract(7, 'days')._d;

Rating.aggregate([
{
$match:{
userTo:facebookId,
timestamp:{$gt:dateSevenDaysAgo,$lt:dateTill}
}
},
{
$group:{
_id:{day:{'$dayOfMonth':'$timestamp'}},
average:{$avg:'$rating'}
}
},
{
$sort:{
'_id.day':1
}
}
]

这给了我

[ { _id: { day: 20 }, average: 1 },
{ _id: { day: 22 }, average: 3 },
{ _id: { day: 24 }, average: 5 } ]

我想得到的是这样的:

[1,,3,,5,,]

按顺序表示最近 7 天的平均值,并且有一个空元素,表示当天没有平均值。

我可以尝试创建一个函数来检测差距在哪里,但是当平均值分布在两个不同的月份时,这将不起作用。例如 (July 28,29,30,31,Aug 1,2] - 八月的日子将被排序到我想要的数组的前面。

有更简单的方法吗?

谢谢!

最佳答案

人们经常询问“空结果”,而他们的想法通常来自他们如何使用 SQL 查询来解决问题。

但是,虽然为不包含分组键的项目抛出一组“空结果”是“可能的”,但这是一个困难的过程,很像人们使用的 SQL 方法,它只是将这些值抛入人为地声明,它确实不是一个非常受性能驱动的替代方案。考虑使用一组制造的 key “加入”。效率不高。

更聪明的方法是直接在客户端 API 中准备好这些结果,而不是发送到服务器。然后聚合输出可以与这些结果“合并”以创建一个完整的集合。

无论您想要存储要合并的集合取决于您,它只需要一个基本的“哈希表”和查找。但这是一个使用 nedb 的例子,它允许你保持 MongoDB 查询和更新的一套思路:

var async = require('async'),
mongoose = require('mongoose'),
DataStore = require('nedb'),
Schema = mongoose.Schema,
db = new DataStore();

mongoose.connect('mongodb://localhost/test');

var Test = mongoose.model(
'Test',
new Schema({},{ strict: false }),
"testdata"
);

var testdata = [
{ "createDate": new Date("2015-07-20"), "value": 2 },
{ "createDate": new Date("2015-07-20"), "value": 4 },
{ "createDate": new Date("2015-07-22"), "value": 4 },
{ "createDate": new Date("2015-07-22"), "value": 6 },
{ "createDate": new Date("2015-07-24"), "value": 6 },
{ "createDate": new Date("2015-07-24"), "value": 8 }
];

var startDate = new Date("2015-07-20"),
endDate = new Date("2015-07-27"),
oneDay = 1000 * 60 * 60 * 24;

async.series(
[
function(callback) {
Test.remove({},callback);
},
function(callback) {
async.each(testdata,function(data,callback) {
Test.create(data,callback);
},callback);
},
function(callback) {
async.parallel(
[
function(callback) {
var tempDate = new Date( startDate.valueOf() );
async.whilst(
function() {
return tempDate.valueOf() <= endDate.valueOf();
},
function(callback) {
var day = tempDate.getUTCDate();
db.update(
{ "day": day },
{ "$inc": { "average": 0 } },
{ "upsert": true },
function(err) {
tempDate = new Date(
tempDate.valueOf() + oneDay
);
callback(err);
}
);
},
callback
);
},
function(callback) {
Test.aggregate(
[
{ "$match": {
"createDate": {
"$gte": startDate,
"$lt": new Date( endDate.valueOf() + oneDay )
}
}},
{ "$group": {
"_id": { "$dayOfMonth": "$createDate" },
"average": { "$avg": "$value" }
}}
],
function(err,results) {
if (err) callback(err);
async.each(results,function(result,callback) {
db.update(
{ "day": result._id },
{ "$inc": { "average": result.average } },
{ "upsert": true },
callback
)
},callback);
}
);
}
],
callback
);
}
],
function(err) {
if (err) throw err;
db.find({},{ "_id": 0 }).sort({ "day": 1 }).exec(function(err,result) {
console.log(result);
mongoose.disconnect();
});
}
);

这给出了这个输出:

[ { day: 20, average: 3 },
{ day: 21, average: 0 },
{ day: 22, average: 5 },
{ day: 23, average: 0 },
{ day: 24, average: 7 },
{ day: 25, average: 0 },
{ day: 26, average: 0 },
{ day: 27, average: 0 } ]

简而言之,“数据存储”是使用 nedb 创建的,它的行为基本上与任何 MongoDB 集合相同(具有精简的功能)。然后,您可以为任何结果插入您的“键”范围内的预期值和默认值。

然后运行您的聚合语句,它只会返回查询集合中存在的键,您只需使用聚合值“更新”创建的具有相同键的数据存储。

为了提高效率,我在 parallel 中同时运行空结果“创建”和“聚合”操作, 利用 "upsert"功能和 $inc值的运算符。这些不会冲突,这意味着创建可以在聚合运行的同时发生,因此没有延迟。

这很容易集成到您的 API 中,因此您可以拥有所有您想要的键,包括那些在输出集合中没有数据聚合的键。

同样的方法适用于在您的 MongoDB 服务器上使用另一个实际集合来处理非常大的结果集。但是,如果它们非常大,那么无论如何您都应该预先聚合结果,并且只使用标准查询进行抽样。

关于node.js - MongoDB 聚合组最近 7 天的平均评分,值为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31661858/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com