第一次来这里 - 请轻松......;)
我首次使用MongoDB - 使用官方PHP驱动程序与应用程序进行交互。 这是我遇到的关于聚合框架的第一个问题。 我有一个文档集合,所有文档都包含一系列数字,如下面的缩写示例......
{
"_id": ObjectId("51c42c1218ef9de420000002"),
"my_id": 1,
"numbers": [
482,
49,
382,
290,
31,
126,
997,
20,
145
],
}
{
"_id": ObjectId("51c42c1218ef9de420000006"),
"my_id": 2,
"numbers": [
19,
234,
28,
962,
24,
12,
8,
643,
145
],
}
{
"_id": ObjectId("51c42c1218ef9de420000008"),
"my_id": 3,
"numbers": [
912,
18,
456,
34,
284,
556,
95,
125,
579
],
}
{
"_id": ObjectId("51c42c1218ef9de420000012"),
"my_id": 4,
"numbers": [
12,
97,
227,
872,
103,
78,
16,
377,
20
],
}
{
"_id": ObjectId("51c42c1218ef9de420000016"),
"my_id": 5,
"numbers": [
212,
237,
103,
93,
55,
183,
193,
17,
346
],
}
使用聚合框架和PHP(我认为这是正确的方法),我试图计算出一个数字在数组中没有出现的平均次数(在数字数组中)再次出现之前。 例如,在上面的例子中,数字20没有出现的平均次数是1.5(存在2个集合的间隙,后面是1的间隙 - 将这些值加在一起,除以间隙的数量)。 如果数字20在结果数组中,然后使用$ cond运算符,根据结果传递一个值,我可以得到。这是我的PHP ......
$unwind_results = array(
'$unwind' => '$numbers'
);
$project = array (
'$project' => array(
'my_id' => '$my_id',
'numbers' => '$numbers',
'hit' => array('$cond' => array(
array(
'$eq' => array('$numbers',20)
),
0,
1
)
)
)
);
$group = array (
'$group' => array(
'_id' => '$my_id',
'hit' => array('$min'=>'$hit'),
)
);
$sort = array(
'$sort' => array( '_id' => 1 ),
);
$avg = $c->aggregate(array($unwind_results,$project, $group, $sort));
我想要实现的目的是设置某种增量计数器,每次数字数组中出现数字20时重置,然后抓住所有这些数字并从那里算出平均值...但我真正难倒
我知道我可以从应用程序方面的文档集合中得出平均值,但理想情况下我希望Mongo能够给出我想要的结果,因此它更具可移植性。
Map / Reduce是否需要涉及某个地方?
任何帮助/建议/指针都非常受欢迎!
答案 0 :(得分:1)
正如Asya所说,聚合框架不适用于问题的最后部分(平均管道中文档之间“点击”的差距)。 Map / reduce似乎也不适合这项任务,因为你需要按顺序(并按排序顺序)处理文件以进行此计算,并且MR强调并行处理。
鉴于聚合框架以排序的顺序处理处理文档,我昨天就头脑风暴如何支持您的用例进行了头脑风暴。如果$group
在投影期间(除了正在处理的文档之外)公开访问其累加器值,我们也许可以使用$push
来收集投影数组中的先前值,然后在用于计算这些“命中”差距的投影。或者,如果有一些工具可以访问我们的桶$group
遇到的先前文档(即组密钥),这可以让我们确定差异并计算差距范围。
我与在框架上工作的Mathias分享了这些想法,他解释说虽然所有这些都可能用于单个服务器(实现了功能),但它在分片基础设施上根本不起作用。 $group
和$sort
操作已分发。它不是一个便携式解决方案。
我认为您最好的选择是使用您拥有的$project
运行聚合,然后使用您的应用程序语言处理这些结果。