MongoDB - 聚合框架,PHP和平均值

时间:2013-06-25 09:43:36

标签: php mongodb aggregation-framework

第一次来这里 - 请轻松......;)

我首次使用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是否需要涉及某个地方?

任何帮助/建议/指针都非常受欢迎!

1 个答案:

答案 0 :(得分:1)

正如Asya所说,聚合框架不适用于问题的最后部分(平均管道中文档之间“点击”的差距)。 Map / reduce似乎也不适合这项任务,因为你需要按顺序(并按排序顺序)处理文件以进行此计算,并且MR强调并行处理。

鉴于聚合框架以排序的顺序处理处理文档,我昨天就头脑风暴如何支持您的用例进行了头脑风暴。如果$group在投影期间(除了正在处理的文档之外)公开访问其累加器值,我们也许可以使用$push来收集投影数组中的先前值,然后在用于计算这些“命中”差距的投影。或者,如果有一些工具可以访问我们的桶$group遇到的先前文档(即组密钥),这可以让我们确定差异并计算差距范围。

我与在框架上工作的Mathias分享了这些想法,他解释说虽然所有这些都可能用于单个服务器(实现了功能),但它在分片基础设施上根本不起作用。 $group$sort操作已分发。它不是一个便携式解决方案。

我认为您最好的选择是使用您拥有的$project运行聚合,然后使用您的应用程序语言处理这些结果。