不太確定,如果我建議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.謝謝你的描述性答案。 –