【问题标题】:MongoDB - Aggregation Framework, PHP and averagesMongoDB - 聚合框架、PHP 和平均值
【发布时间】:2013-06-25 09:43:36
【问题描述】:

第一次来 - 请放轻松... ;)

我第一次开始使用 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(我认为这是正确的方法),我试图计算出一个数字在再次出现之前没有出现在集合中(在 numbers 数组中)的平均次数. 例如,上例中没有出现数字 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 是否需要参与其中?

收到任何帮助/建议/指针!

【问题讨论】:

  • 当前版本做不到。

标签: php mongodb aggregation-framework


【解决方案1】:

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

鉴于聚合框架确实按排序顺序处理文档,我昨天在集思广益,讨论它如何支持您的用例。如果$group 在投影期间暴露了对其累加器值的访问(除了正在处理的文档之外),我们也许可以使用$push 来收集投影数组中的先前值,然后在投影期间检查它们以计算这些“击中”差距。或者,如果有一些工具可以访问 $group 为我们的存储桶(即组密钥)遇到的先前文档,这可以让我们确定差异并计算间隙跨度。

我与从事框架工作的 Mathias 分享了这些想法,他解释说,虽然所有这些对于单个服务器来说都是可能的(如果实现了功能),但它根本无法在分片基础架构上运行,其中$group$sort 操作是分布式的。这不是一个可移植的解决方案。

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

【讨论】:

  • jmikola,是的,我在按照你的思路思考——你提到的问题是获取以前的值。无论如何,我最终计算出了应用程序方面的平均值——我还将在分片基础设施上实现这一点。感谢您考虑一下!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
相关资源
最近更新 更多