我有以下文件:
{
"_id" : ObjectId("540dadfcf3116b60d401c314"),
"value" : 2,
"d_c_at" : [
"2013",
"201311",
"2013w46",
"20131116"
]
}
我希望按d_c_at
数组中的最后一个元素(20131116
)对它们进行分组,这些元素将年,月,日商店表示为结构化日期。
这是我到目前为止所做的:
db.points.aggregate(
{ $match: { "d_c_at.0": '2014' } },
{ $group: { _id: "$d_c_at.0", value: { $sum: "$value" } } }
)
返回:
{ "_id" : [ ], "value" : 1207 }
我尝试使用$unwind
但没有成功:
db.points.aggregate(
{ $match: { "d_c_at.0": '2014' } },
{ $unwind: "$d_c_at" },
{ $group: { _id: "$d_c_at", value: { $sum: "$value" } } }
)
看起来几乎不错,但它也在其他数组元素上分组:
{ ... }
{ "_id" : "20140519", "value" : 33 }
{ "_id" : "20140707", "value" : 36 }
{ "_id" : "20140330", "value" : 37 }
{ "_id" : "20140709", "value" : -28 }
{ "_id" : "20140620", "value" : 14 }
{ "_id" : "2014w9", "value" : -250 }
{ ... }
预期产出:
{ ... }
{ "_id" : "20140519", "value" : 33 }
{ "_id" : "20140707", "value" : 36 }
{ "_id" : "20140330", "value" : 37 }
{ "_id" : "20140709", "value" : -28 }
{ "_id" : "20140620", "value" : 14 }
{ ... }
答案 0 :(得分:3)
虽然使用聚合可以实现这一点,但使用Map-reduce可以轻松实现预期输出: 假设您的d_c_at,总是有4个元素,或者第4个元素是您的组ID标准,正如您的示例结构所示。
将键作为第4个元素发出,以便文档按“d_c_at”的第4个元素分组。
var map = function(){emit(this.d_c_at[3],{"sum":this.value});}
完成后,计算总和:
var reduce = function(id,Arr){
var sum = 0;
for(var i=0;i<Arr.length;i++)
{
var obj = Arr[i];
var value = obj.sum;
sum = sum+value;
}
return {"sum":sum};
}
将结果转储到“输出”。
db.test.mapReduce(
map,
reduce,
{ out: "output" }
)
O / P:
> db.output.find()
{ "_id" : "20131116", "value" : { "sum" : 6 } }
{ "_id" : "20131117", "value" : { "sum" : 6 } }
使用的样本i / p:
{
"_id" : 1,
"value" : 2,
"d_c_at" : [
"2013",
"201311",
"2013w46",
"20131116"
]
}
{
"_id" : 2,
"value" : 4,
"d_c_at" : [
"2013",
"201311",
"2013w46",
"20131116"
]
}
{
"_id" : 3,
"value" : 6,
"d_c_at" : [
"2013",
"201311",
"2013w46",
"20131116"
]
}