Php MapReduce使用命令无法从服务器解码文档
我有一个Php MapReduce使用命令无法从服务器解码文档,php,mongodb,mapreduce,aggregation-framework,Php,Mongodb,Mapreduce,Aggregation Framework,我有一个Test数据库,其中包含一个名为collection的集合: { "_id": "576008e5b47a6120c800418d", "UserID": "Paul", "Page": "A" } 我想记录webactivity并使用mapreduce获得如下结果 { "_id": "Paul", "value": { "A": 1, "B": 0, "C": 0, "D":
Test
数据库,其中包含一个名为collection
的集合:
{
"_id": "576008e5b47a6120c800418d",
"UserID": "Paul",
"Page": "A"
}
我想记录webactivity并使用mapreduce获得如下结果
{
"_id": "Paul",
"value": {
"A": 1,
"B": 0,
"C": 0,
"D": 0,
"E": 0
}
}
首先,我尝试了一个PHP 7 MongoDB驱动程序1.1.7 MapReduce的简单代码,使用的命令无法从服务器解码文档:
<?php
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$command = new MongoDB\Driver\Command(array(
"mapReduce" => "collection",
"map" => "function() { emit(this.UserID, 1); }",
"reduce" => "function(Users, Pages){".
"return Pages;}",
"out" => "ex"
));
try {
$cursor = $manager->executeCommand('Test.collection', $command);
$response = $cursor->toArray()[0];
} catch(MongoDB\Driver\Exception $e) {
echo $e->getMessage(), "\n";
exit;
}
var_dump($response);
?>
任何想法都将不胜感激。不太确定我是否会推荐MapReduce用于这种类型的操作,我会说聚合框架将以更好的性能进行聚合,因为操作都是在本机代码中完成的,而无需将代码派生到JavaScript进行编译(在MapReduce的情况下) 使用聚合操作,您只需要一个管道,它使用运算符,允许您将逻辑条件转换为值。在这种情况下,您希望将
页面
指定为键,并将其计数指定为值,文档按用户ID
分组
考虑在mongo shell中运行以下聚合操作:
将产生以下输出:
{
"_id": "Paul",
"A": 1,
"B": 0,
"C": 0,
"D": 0,
"E": 0
}
{
"results" : [
{
"_id" : "Paul",
"value" : {
"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 ]);
?>
它给出了输出:
{
"_id": "Paul",
"A": 1,
"B": 0,
"C": 0,
"D": 0,
"E": 0
}
{
"results" : [
{
"_id" : "Paul",
"value" : {
"A" : 1,
"B" : 0,
"C" : 0,
"D" : 0,
"E" : 0
}
}
]
}
将上述mapReduce操作转换为PHP非常简单。我不太确定我是否会推荐mapReduce用于这种类型的操作,我会说聚合框架将以更好的性能进行聚合,因为操作都是在本机代码中完成的,而无需将代码生成JavaScript进行编译(在MapReduce案例中) 使用聚合操作,您只需要一个管道,该管道使用运算符,允许您将逻辑条件转换为值。在这种情况下,您希望将
页面
指定为键,并将其计数指定为值,文档按用户ID
分组。
考虑在mongo shell中运行以下聚合操作:
将产生以下输出:
{
"_id": "Paul",
"A": 1,
"B": 0,
"C": 0,
"D": 0,
"E": 0
}
{
"results" : [
{
"_id" : "Paul",
"value" : {
"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 ]);
?>
它给出了输出:
{
"_id": "Paul",
"A": 1,
"B": 0,
"C": 0,
"D": 0,
"E": 0
}
{
"results" : [
{
"_id" : "Paul",
"value" : {
"A" : 1,
"B" : 0,
"C" : 0,
"D" : 0,
"E" : 0
}
}
]
}
将上述mapReduce操作转换为PHP非常简单。结果接缝仅给出访问的所有页面的总数。假设页面已访问,我得到“a”:6,“B”:6,“C”:6,“D”:6,“E”:6。感谢您提供了描述良好的答案。结果接缝仅给出访问的所有页面的总数。假设页面已访问,我得到“a”:6,“B”:6,“C”:6,“D”:6,“E”:6.谢谢你描述得很好的回答。