不太确定,如果我建议MapReduce用于这种类型的操作,会说聚合框架将会执行更好性能的聚合,因为操作全部在本地代码中完成,而不会产生代码以便编译JavaScript(在MapReduce案例)。
随着聚合操作,所有你需要的是一个$group
管道,它利用了$cond
运营商允许你变换分析逻辑条件为价值。在这种情况下,您需要指定pages
作为键和它们的计数值,其中文档按UserID
分组。
考虑蒙戈壳运行以下聚合操作:
db.collection.aggregate([
{
"$group": {
"_id": "$UserID",
"A": {
"$sum": {
"$cond": [
{ "$eq": [ "$Page", "A" ] },
1,
0
]
}
},
"B": {
"$sum": {
"$cond": [
{ "$eq": [ "$Page", "B" ] },
1,
0
]
}
},
"C": {
"$sum": {
"$cond": [
{ "$eq": [ "$Page", "C" ] },
1,
0
]
}
},
"D": {
"$sum": {
"$cond": [
{ "$eq": [ "$Page", "D" ] },
1,
0
]
}
},
"E": {
"$sum": {
"$cond": [
{ "$eq": [ "$Page", "E" ] },
1,
0
]
}
}
}
}
])
这将产生输出:
{
"_id": "Paul",
"A": 1,
"B": 0,
"C": 0,
"D": 0,
"E": 0
}
用于上述示例文档。
为了简便起见,如果假设你有页面的列表事前,可以动态生成管道如下:
var groupOperation = { "$group": { "_id": "$UserID" } },
pages = ["A", "B", "C", "D", "E"];
pages.forEach(function (page){
groupOperation["$group"][page] = {
"$sum": {
"$cond": [
{ "$eq": [ "$Page", page ] },
1,
0
]
}
};
})
db.collection.aggregate([groupOperation]);
现在,要将这种以PHP如下:
<?php
$group_pipeline = [
'$group' => [
'_id' => '$UserID',
'A' => [
'$sum' => [
'$cond' => [ [ '$eq' => [ '$Page', 'A' ] ], 1, 0 ]
]
],
'B' => [
'$sum' => [
'$cond' => [ [ '$eq' => [ '$Page', 'B' ] ], 1, 0 ]
]
],
'C' => [
'$sum' => [
'$cond' => [ [ '$eq' => [ '$Page', 'C' ] ], 1, 0 ]
]
],
'D' => [
'$sum' => [
'$cond' => [ [ '$eq' => [ '$Page', 'D' ] ], 1, 0 ]
]
],
'E' => [
'$sum' => [
'$cond' => [ [ '$eq' => [ '$Page', 'E' ] ], 1, 0 ]
]
]
],
];
$aggregation = $collection->aggregate([ group_pipeline ]);
?>
如果您宁愿坚持MapReduce,那么考虑更改地图并减少功能:
db.collection.mapReduce(
function() {
var obj = {};
["A", "B", "C", "D", "E"].forEach(function (page){ obj[page] = 0; });
obj[this.Page] = 1;
emit(this.UserID, obj);
},
function(key, values) {
var obj = {};
values.forEach(function(value) {
Object.keys(value).forEach(function(key) {
if (!obj.hasOwnProperty(key)){
obj[key] = 0;
}
obj[key]++;
});
});
return obj;
},
{ "out": { "inline": 1 } }
)
其中给出的输出:
{
"results" : [
{
"_id" : "Paul",
"value" : {
"A" : 1,
"B" : 0,
"C" : 0,
"D" : 0,
"E" : 0
}
}
]
}
翻译上述映射精简操作PHP是微不足道的。
The Results seam只给出了访问过的所有页面的总数。假设页面被访问,我得到“A”:6,“B”:6,“C”:6,“D”:6,“E”:6.谢谢你的描述性答案。 –