如何得出mongodb每年最小和最大日期值的差异

时间:2017-11-01 07:48:49

标签: mongodb-query aggregation-framework

如何使用mongodb中的聚合管道或地图缩小来计算集合中每年最小和最大日期的记录的特定列的值的差异?

我有以下系列:

/* 1 */
{
    "_id" : 1,
    "item" : "abc",
    "price" : 10,
    "quantity" : 2,
    "date" : ISODate("2014-01-01T08:00:00.000Z")
},

/* 2 */
{
    "_id" : 2,
    "item" : "jkl",
    "price" : 20,
    "quantity" : 1,
    "date" : ISODate("2014-02-03T09:00:00.000Z")
},

/* 3 */
{
    "_id" : 3,
    "item" : "xyz",
    "price" : 5,
    "quantity" : 5,
    "date" : ISODate("2014-02-03T09:05:00.000Z")
},

/* 4 */
{
    "_id" : 4,
    "item" : "abc",
    "price" : 10,
    "quantity" : 10,
    "date" : ISODate("2014-02-15T08:00:00.000Z")
},

/* 5 */
{
    "_id" : 5,
    "item" : "xyz",
    "price" : 5,
    "quantity" : 10,
    "date" : ISODate("2014-02-15T09:05:00.000Z")
},

/* 6 */
{
    "_id" : 6,
    "item" : "abc",
    "price" : 10,
    "quantity" : 2,
    "date" : ISODate("2013-01-01T08:00:00.000Z")
},

/* 7 */
{
    "_id" : 7,
    "item" : "jkl",
    "price" : 20,
    "quantity" : 1,
    "date" : ISODate("2013-02-03T09:00:00.000Z")
},

/* 8 */
{
    "_id" : 8,
    "item" : "xyz",
    "price" : 5,
    "quantity" : 5,
    "date" : ISODate("2013-02-03T09:05:00.000Z")
},

/* 9 */
{
    "_id" : 9,
    "item" : "abc",
    "price" : 10,
    "quantity" : 10,
    "date" : ISODate("2013-02-15T08:00:00.000Z")
},

/* 10 */
{
    "_id" : 10,
    "item" : "xyz",
    "price" : 5,
    "quantity" : 10,
    "date" : ISODate("2013-02-15T09:05:00.000Z")
},

/* 11 */
{
    "_id" : 11,
    "item" : "abc",
    "price" : 10,
    "quantity" : 2,
    "date" : ISODate("2012-01-01T08:00:00.000Z")
},

/* 12 */
{
    "_id" : 12,
    "item" : "jkl",
    "price" : 20,
    "quantity" : 1,
    "date" : ISODate("2012-02-03T09:00:00.000Z")
},

/* 13 */
{
    "_id" : 13,
    "item" : "xyz",
    "price" : 5,
    "quantity" : 5,
    "date" : ISODate("2012-02-03T09:05:00.000Z")
},

/* 14 */
{
    "_id" : 14,
    "item" : "abc",
    "price" : 10,
    "quantity" : 10,
    "date" : ISODate("2012-02-15T08:00:00.000Z")
},

/* 15 */
{
    "_id" : 15,
    "item" : "xyz",
    "price" : 5,
    "quantity" : 10,
    "date" : ISODate("2012-02-15T09:05:00.000Z")
},

我希望结果采用以下形式:

{
{"year": 2014}, {"minDtQuantity": 2}, {"maxDtQuantity": 10}, {"quantityDiff": 8},
{"year": 2013}, {"minDtQuantity": 2}, {"maxDtQuantity": 10}, {"quantityDiff": 8},
{"year": 2012}, {"minDtQuantity": 2}, {"maxDtQuantity": 10}, {"quantityDiff": 8},
}

对于每年,我们需要找到最小和最大日期并按年份分组,然后在这些日期找到“数量”值,然后找出每年最小和最大日期的数量之间的差异。

甚至可以使用聚合管道或mongodb中的map-reduce吗?

1 个答案:

答案 0 :(得分:2)

这可以通过按日期排序使用聚合管道来完成,然后在按年份分组时将数量推送到数组中(使用$ year运算符从日期对象中提取年份)。那一年中最小和最大日期的数量分别是数组中的第一个和最后一个值。这些可以使用$ arrayElemAt从数组中取出。

db.collection.aggregate(
[
    {
        $sort: {
            "date": 1
        }
    },
    {
        $group: {
            "_id": { "$year": "$date" },
            "quantityArray": { "$push": "$quantity" },
        }
    },
    {
        $project: {
            "_id": 0,
            "year": "$_id",
            "minDtQuantity": { "$arrayElemAt": [ "$quantityArray", 0 ] },
            "maxDtQuantity": { "$arrayElemAt": [ { "$reverseArray": "$quantityArray" }, 0 ] },
            "quantityDiff": { "$subtract": [ 
                                 { "$arrayElemAt": [ { "$reverseArray": "$quantityArray" }, 0 ] },
                                 { "$arrayElemAt": [ "$quantityArray", 0 ] }, 
                                           ] }
        }
    },
  ]
);

此聚合会在您的数据上返回这些结果:

{ 
"year" : NumberInt(2014), 
"minDtQuantity" : NumberInt(2), 
"maxDtQuantity" : NumberInt(10), 
"quantityDiff" : NumberInt(-8)
},
{ 
"year" : NumberInt(2013), 
"minDtQuantity" : NumberInt(2), 
"maxDtQuantity" : NumberInt(10), 
"quantityDiff" : NumberInt(-8)
},
{ 
"year" : NumberInt(2012), 
"minDtQuantity" : NumberInt(2), 
"maxDtQuantity" : NumberInt(10), 
"quantityDiff" : NumberInt(-8)
}

这不是您指定的格式。我不确定你需要什么,你需要在一份文件中返回的结果吗?