skipped count 0 in aggregate function

后端 未结 3 1187
太阳男子
太阳男子 2020-12-20 01:25

I\'m stuck on this for couple of days. I\'m trying to get the count: 0 where there is no documents in the given time period. This is the aggregate function I\'m

3条回答
  •  感情败类
    2020-12-20 01:37

    this is hacky fix I did for now:

    var getCount = function(timeBlock, start, end, cb) {
    
        Document.aggregate(
        {
            $match: {
                time: {
                    $gte: new Date(start),
                    $lt: new Date(end)
                }
            }
        },
    
        {
            $project: {
                time: 1,
                delta: { $subtract: [
                    new Date(end),
                    '$time'
                ]}
            }
        },
    
        {
            $project: {
                time: 1,
                delta: { $subtract: [
                    "$delta",
                    { $mod: [
                        "$delta",
                        timeBlock
                    ]}
                ]}
            }
        },
    
        {
            $group: {
                _id: { $subtract: [
                    end,
                    "$delta"
                ]},
                count: { $sum: 1 }
            }
        },
    
        {
            $project: {
                time: "$_id",
                count: 1,
                _id: 0
            }
        },
    
        {
            $sort: {
                time: 1
            }
    
        }, function(err, results) {
            if (err) {
                cb(err)
            } else {
                // really hacky way
                var numOfTimeBlocks = ( end - start ) / timeBlock
    
                // in case there is no 0s in the given period of time there is no need
                // to iterate through all of the results
                if ( results.length === numOfTimeBlocks ) {
                    cb(results);
    
                } else {
                    var time = start;
                    var details = [];
    
                    var times = results.map(function(item) {
                        return item.time;
                    });
    
                    for( var i = 0; i < numOfTimeBlocks; i++) {
                        time += timeBlock;
                        var idx = times.indexOf(time);
    
                        if (idx > -1) {
                            details.push(results[idx]);
                        } else {
                            var documentCount = { count: 0, time: time };
                            details.push(documentCount);
                        }
                    }
    
                    cb(details);
                }
    
            }
        })
    }
    

    I was also thinking about doing one query per time block, which gives the same result but I think is inefficient because you query the database N times.

提交回复
热议问题