您正在处理的数据看起来已经作为 mapReduce 操作的输出,因为它具有 mapReduce 产生的特定“_id”和“value”结构。因此,您最好回到如何实现该过程的逻辑并遵循相同的方法来提取和汇总您想要的内容,或者至少将其输出形式更改为:
{
_id: {
evt: "click",
val: { "type": "default", "x": "125", "y": "311", "time": "1" }
},
value: { count: 1 }
},
{
_id: {
evt: "click",
val: { "type": "default", "x": "154", "y": "321", "time": "2" }
},
value: { count: 2 }
},
{
_id: {
evt: "click",
val: { "type": "default", "x": "192", "y": "263", "time": "1" }
},
value: { count: 4 }
}
因为问题是聚合框架“目前”缺乏解决数组“索引”位置(真正的“非关联”数组而不是 PHP 数组)的能力,并且在您尝试时总是返回 null这样做。
缺乏返回原始源或 mapReduce 操作的能力,那么您可以在此数据上编写 mapReduce 操作以获得预期结果(shell 表示,因为它无论如何都会是 JavaScript):
db.collection.mapReduce(
function() {
emit({ evt: this._id.evt, time: this._id.val[3] }, this.value.count)
},
function(key,values) {
return Array.sum(values)
},
{ out: { inline: 1 } }
)
返回典型的 mapReduce 输出如下:
{
"_id" : {
"evt" : "click",
"time" : "1"
},
"value" : 5
},
{
"_id" : {
"evt" : "click",
"time" : "2"
},
"value" : 2
}
如果您至少能够将当前输出集合转换为上面最初建议的形式,那么您将使用这样的聚合框架来运行(再次通用表示):
{ "$group": {
"_id": {
"evt": "$_id.evt",
"time": "$_id.val.time"
},
"count": { "$sum": "$value.count" }
}}
这当然会从改变的数据中产生:
{ "_id" : { "evt" : "click", "time" : "2" }, "count" : 2 }
{ "_id" : { "evt" : "click", "time" : "1" }, "count" : 5 }
在 MongoDB 的未来版本中,将有一个 $slice 运算符允许数组处理,因此使用您当前的结构,您可以这样做:
{ "$group": {
"_id": {
"evt": "$_id.evt",
"time": { "$slice": [ "$_id.val", 3,1 ] }
},
"count": { "$sum": "$value.count" }
}}
这允许从数组中选择“第三个”索引元素,尽管这当然仍会返回一个“数组”作为元素,如下所示:
{ "_id" : { "evt" : "click", "time" : [ "2" ] }, "count" : 2 }
{ "_id" : { "evt" : "click", "time" : [ "1" ] }, "count" : 5 }
所以现在,如果你可以改变你的初始 mapReduce 输出,那就去做吧。可以使用此处显示的表单,也可以仅使用对初始查询的修改来获得您想要的最终结果。修改为推荐的形式至少可以让.aggregate() 命令像这里的第二个示例中所示的那样工作。
如果不是,那么mapReduce仍然是目前唯一的写法,如“第一个”例子所示。