$ 8聚合汇总记录

时间:2019-01-04 07:58:32

标签: mongodb mongoose mongodb-query aggregation-framework

我有以下收藏

{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-01T07:15:32.335Z")
},
{
    "fare" : 32,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-01T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-02T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-03T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-04T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-05T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-06T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-07T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-08T08:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-09T08:15:32.335Z")
}

我需要进行汇总,将这些记录分为每8条记录对,并添加具有相同日期的fare条记录。在上述日期,2019-01-01有两个fares

我的预期输出

{ data: [
{
    "fare" : 44,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-02T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-03T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-04T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-05T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-06T07:15:32.335Z")
},
{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-07T07:15:32.335Z")
},{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-08T08:15:32.335Z")
}],
data:[{
    "fare" : 12,
    "paymentMode" : "cash",
    "rideType" : "Self",
    "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
    "createdAt" : ISODate("2019-01-09T08:15:32.335Z")
}
] }

2 个答案:

答案 0 :(得分:1)

如果我的理解正确,您应该可以使用$bucketAuto管道而不是常规的分组步骤。为此,您可能必须根据文档数预先计算所需的存储桶数量。例如。如果计数为84,则bucketCount类似于ceil(84/8) = 11。到目前为止,我还没有找到一种优雅的方法来完成此操作。

更新: 这是将文档放在两个存储桶中的示例

db.getCollection('probands').aggregate([
{   $sort : {'_id' : -1}}, // not necessary, but probably nice
{
    $bucketAuto : {
        groupBy: '$_id', // this create "groups" of one element each
        buckets: 2, // calculate this value beforehand
        output: {
            data : {
                $push : { // pushes the wanted fields into the data array
                    '_id': '$_id',
                    'fare' : '$fare',
                    'paymentMode' : '$paymentMode',
                    'createdAt' : '$createdAt',
                    'rideType': '$rideType',
                    'userId': '$userId',
                }
            }
        }
    }
},
{ $project: {_id: 0, data : 1}}
])

票价的计算是一个不同的问题,但是使用常规的$group步骤+ $sum可能比这个问题容易。

答案 1 :(得分:1)

您可以尝试以下汇总:

db.col.aggregate([
    {
        $group: {
            _id: { d: { $dayOfMonth: "$createdAt" }, m: { $month: "$createdAt" }, y: { $year: "$createdAt" } },
            fare: { $sum: "$fare" },
            paymentMode: { $first: "$paymentMode" },
            rideType: { $first: "$rideType" },
            userId: { $first: "$userId" },
            createdAt: { $first: "$createdAt" },
        }
    },
    {
        $sort: { createdAt: 1 }
    },
    {
        $project: {
            _id: 0
        }
    },
    {
        $group: {
            _id: null,
            docs: { $push: "$$ROOT" }
        }
    },
    {
        $project: {
            docs: {
                $map: {
                    input: { $range: [0,  { $ceil: { $divide: [ { $size: "$docs" }, 8 ] } } ] },
                    as: "arrayStart",
                    in: {
                        $slice: [ "$docs", { $multiply: [ "$$arrayStart", 8 ] }, 8 ]
                    }
                }
            }
        }
    },
    {
        $unwind: "$docs"
    }
])

基本上,您想按天对fares求和,因此您需要使用$dayOfMonth$month$year运算符根据日期类型来获得该天。然后,您需要获得8个元素的存储桶,以便可以将所有文档合并到单个数组中($group_id设置为null。然后,您可以简单地计算出需要多少个“桶”(使用$ceil$divide)和将$slice长数组转换为8元素数组。在最后一步中,您可以使用$unwind获得每个最终文档的8元素数组。输出:

{
    "_id" : null,
    "docs" : [
        {
            "fare" : 44,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-01T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-02T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-03T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-04T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-05T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-06T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-07T07:15:32.335Z")
        },
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-08T08:15:32.335Z")
        }
    ]
}
{
    "_id" : null,
    "docs" : [
        {
            "fare" : 12,
            "paymentMode" : "cash",
            "rideType" : "Self",
            "userId" : ObjectId("5c25c5fa12430a348459a3d7"),
            "createdAt" : ISODate("2019-01-09T08:15:32.335Z")
        }
    ]
}