我有一组 ProductViews
:
{
productId: "5b8c0f3204a10228b00a1745",
createdAt: "2018-09-07T17:18:40.759Z"
}
我有一个获取特定产品每日浏览量的查询:
ProductView.aggregate([
{ $match: { productId } },
{ $project: { day: { $substr: ["$createdAt", 0, 10] } } },
{
$group: {
_id: "$day",
count: { $sum: 1 },
time: { $avg: "$createdAt" },
}
},
{ $sort: { _id: 1 } },
{
$project: {
date: '$_id',
views: '$count',
},
},
]).exec((err, result) => ...)
当前给出:
[
{ date: '2018-09-01', views: 1 },
{ date: '2018-09-02', views: 3 },
{ date: '2018-09-04', views: 2 },
{ date: '2018-09-05', views: 5 },
// ...
]
问题:
问题是,此聚合不会返回 { date: '2018-09-03', views: 0 }
对于 0
View 的日子。这会导致数据显示不正确:[![在此处输入图像描述][1]][1]
结果应如下所示:
[
{ date: '2018-09-01', views: 1 },
{ date: '2018-09-02', views: 3 },
{ date: '2018-09-03', views: 0 }, <=
{ date: '2018-09-04', views: 2 },
{ date: '2018-09-05', views: 5 },
// ...
]
P.S.: 传入开始和结束日期,根据这个范围输出结果就完美了 [1]: /image/uHPBs.png
最佳答案
您需要几个额外的阶段来返回默认值。首先,您需要使用 $group
并将 _id
设置为 null
以将所有结果收集到一个文档中。然后你可以使用$map以天数数组作为输入。在那个 $map
里面你可以使用 $indexOfArray查找该日期是否存在于您当前的结果集中。如果是 (index != -1
),那么您可以返回该值,否则您需要返回默认子文档并将 views
设置为 0
。然后你可以使用$unwind取回文档列表和$replaceRoot将嵌套的 stats
提升到顶层。
ProductView.aggregate([
{ $match: { productId: '5b8c0f3204a10228b00a1745' } },
{ $project: { day: { $substr: ["$createdAt", 0, 10] } } },
{
$group: {
_id: "$day",
count: { $sum: 1 },
time: { $avg: "$createdAt" },
}
},
{ $sort: { _id: 1 } },
{
$project: {
date: '$_id',
views: '$count',
},
},
{
$group: {
_id: null,
stats: { $push: "$$ROOT" }
}
},
{
$project: {
stats: {
$map: {
input: [ "2018-09-01", "2018-09-02", "2018-09-03", "2018-09-04", "2018-09-05" ],
as: "date",
in: {
$let: {
vars: { dateIndex: { "$indexOfArray": [ "$stats._id", "$$date" ] } },
in: {
$cond: {
if: { $ne: [ "$$dateIndex", -1 ] },
then: { $arrayElemAt: [ "$stats", "$$dateIndex" ] },
else: { _id: "$$date", date: "$$date", views: 0 }
}
}
}
}
}
}
}
},
{
$unwind: "$stats"
},
{
$replaceRoot: {
newRoot: "$stats"
}
}
]).exec((err, result) => ...)
您可以使用简单循环在应用程序逻辑中生成静态日期列表。我相信这在 MongoDB 中也是可能的(使用 $range ),但它可能会使这个聚合管道复杂化。如果您对此感到满意,或者您想尝试在 MongoDB 中生成该日期数组,请告诉我。
关于node.js - 填写记录中缺失的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52235027/