Node.js 如何修复mongo db查询?

Node.js 如何修复mongo db查询?,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我正在写一份db的统计请求。代码如下: Stats.aggregate([ { $group: { _id: { 'advertiser': '$advertiser', 'offer': '$offer' }, stats: { $push: { 'date': '

我正在写一份db的统计请求。代码如下:

Stats.aggregate([
    {
        $group: {
            _id: {
                'advertiser': '$advertiser',
                'offer': '$offer'
            },
            stats: {
                $push: {
                    'date': '$date',
                    'spent': '$spent',
                    'revenue': '$revenue'
                }
            }
        }
    },
    {
        $group: {
            _id: '$_id.advertiser',
            offers: {
                $push: {
                    _id: '$_id.offer',
                    stats: '$stats'
                }
            }
        }
    }], callback);
我想让广告商知道他所有的报价,在报价中有关于天数以及花费和收入的统计数据。问题是,每天的统计数据可能不止一个,我得到的答案是:

stats   […]
0   {…}
date    2018-01-30T22:00:00.000Z
spent   100
revenue 200
1   {…}
date    2018-01-30T22:00:00.000Z
spent   20
revenue 20
但是,我需要把同样的日子折成一天,花掉并增加收入 此外,我还想将“优惠”集合中的优惠信息添加到结果优惠中,就像我对广告商所做的那样。也许有人知道怎么做。多谢各位

数据库中的统计信息:

{
"_id": {
    "$oid": "5a4f873d381727000404d171"
},
"advertiser": {
    "$oid": "5a4f74619f0251000438fe4a"
},
"offer": {
    "$oid": "5a4f748c9f0251000438fe4b"
},
"spent": 415.19,
"revenue": 780.92,
"date": "2018-01-02T22:00:00.000Z",
"user": {
    "$oid": "5a4f74259f0251000438fe40"
},
"__v": 0
}

统计模式

const StatsSchema = mongoose.Schema({
advertiser: {
    type: ObjectId,
    ref: 'Advertiser',
    required: true
},
offer: {
    type: ObjectId,
    ref: 'Offer',
    required: true
},
spent: {
    type: Number,
    required: true
},
revenue: {
    type: Number,
    required: true
},
date: {
    type: String,
    required: true
},
user: {
    type: ObjectId,
    ref: 'User',
    required: true
}});

您可以首先投影
,然后按如下所示进行相应分组。这是一个相对较长的查询,您可以根据您的工作流添加一些优化

db.createCollection('statistics');

db.statistics.insertMany([
    {advertiser: "1", offer: "1", date: "2018-01-30T22:00:00.000Z", spent: 10, revenue: 20},
    {advertiser: "1", offer: "1", date: "2018-01-30T21:00:00.000Z", spent: 20, revenue: 20},
    {advertiser: "2", offer: "2", date: "2018-01-30T22:00:00.000Z", spent: 10, revenue: 20},
    {advertiser: "2", offer: "2", date: "2018-01-30T21:00:00.000Z", spent: 1000, revenue: 2000},
    {advertiser: "2", offer: "2", date: "2018-01-31T22:00:00.000Z", spent: 25, revenue: 50}
])

transform_date = {
    $project: {
        advertiser: 1,
        offer: 1,
        date: { $dateFromString: { dateString: { $arrayElemAt: [ {$split: ["$date", "Z"]}, 0 ] }, timezone: 'UTC' } },
        spent: 1,
        revenue: 1      
    }
}

project_year_month_day = {
    $project: {
        advertiser: 1,
        offer: 1,
        date: 1,
        spent: 1,
        revenue: 1,
        year: { $year: "$date" },
        month: { $month: "$date" },
        day: { $dayOfMonth: "$date" }
    }
}

group_by_date_advertiser_offer_and_sum = {
    $group: {
        _id: {
            advertiser: "$advertiser",
            offer: "$offer",
            day: "$day",
            month: "$month",
            year: "$year"
        },
        spent: { $sum: "$spent" },
        revenue: { $sum: "$revenue" },
        dates: { $push: "$date" }
    }
}

group_advertiser_offer_and_push = {
    $group: {
        _id: {
            advertiser: "$_id.advertiser",
            offer: "$_id.offer"
        },
        stats: {
            $push: {
                dates: "$dates",
                spent: "$spent",
                revenue: "$revenue"
            }
        }
    }
}

group_advertiser_and_push = {
    $group: {
        _id: "$_id.advertiser",
        offers: {
            $push: {
                _id: "$_id.offer",
                stats: "$stats"
            }
        }
    }
}

db.statistics.aggregate([
    transform_date, 
    project_year_month_day, 
    group_by_date_advertiser_offer_and_sum, 
    group_advertiser_offer_and_push, 
    group_advertiser_and_push
])
输出

[{
    "_id": "2",
    "offers": [{
        "_id": "2",
        "stats": [{
            "dates": [ISODate("2018-01-31T22:00:00Z")],
            "spent": 25,
            "revenue": 50
        }, {
            "dates": [ISODate("2018-01-30T22:00:00Z"), ISODate("2018-01-30T21:00:00Z")],
            "spent": 1010,
            "revenue": 2020
        }]
    }]
} {
    "_id": "1",
    "offers": [{
        "_id": "1",
        "stats": [{
            "dates": [ISODate("2018-01-30T22:00:00Z"), ISODate("2018-01-30T21:00:00Z")],
            "spent": 30,
            "revenue": 40
        }]
    }]
}]

请从
Stats
集合中添加一些示例文档,以便人们更容易提供帮助。如果我的日期类型为字符串,这会有大问题吗?我是否可以将$project date转换为new date(“$date”)。我更新了代码段,检查这是否适用于您的用例。您可以在项目中使用
dateFromString
,但要使用该
Z
,日期字符串中不应出现该值,这就是我使用拆分(“Z”)并获取预期解析的第一个元素的原因。确定。如何将报价信息从报价集合推送到结果中的报价中?您可以尝试使用mongoose中的QueryPopulation API使用
ref
,或者使用
$lookup
聚合,这可能会非常费劲。我已修复。谢谢你的时间和帮助