在MongoDB中对“列”求和

4

在MySQL中,我只需要执行"SELECT sum(pts) FROM table"就可以获得表格中pts列的总和。然而,我正在将此应用程序转换为MongoDB,并且无法找到一种直接的方法来获取集合中公共键"type"的总和。我正在使用PHP,请提供PHP代码以使其工作。

以下是我的数据:

{ "_id" : ObjectId("4f136dab5056f65b61000000"), "p_id" : "3", "g_id" : "1", "type" : "3" }
{ "_id" : ObjectId("4f136dad5056f65760000000"), "p_id" : "8", "g_id" : "1", "type" : "7" }
{ "_id" : ObjectId("4f136daf5056f65860000000"), "p_id" : "6", "g_id" : "1", "type" : "4" }
{ "_id" : ObjectId("4f136db15056f65460000000"), "p_id" : "27", "g_id" : "1", "type" : "2" }

我该如何让$sum等于“type”键的总和?

这个计算需要在查询中完成吗?为什么不能在 PHP 中循环结果呢? - wyqydsyq
7个回答

5

利用MongoDB的新聚合框架

$result = $db->command(array(

    'aggregate' => 'COLLECTION_NAME',

    'pipeline'  => array(
        // Match:
        // We can skip this in case that we don't need to filter 
        // documents in order to perform the aggregation
        array('$match' => array(
            // Criteria to match against
        )),

        // Group:
        array('$group'  => array(
            // Groupby fields:
            '_id'       => "$fieldname1, $fieldname2, $or_empty, $etc",
            // Count:
            'count'     => array('$sum' => 1),
            // Sum:
            'type_sum'  => array('$sum' => '$type'),
        ))

        // Other aggregations may go here as it's really a PIPE :p

    ),
));

3

MongoDB没有一个简单的查询来执行求和操作。

在MongoDB中,您需要运行一个特殊的命令来执行此操作。您有三个选项。

  1. 使用Map/Reduce。这是在数据集中执行求和、计数、平均值等操作的一般方法。这不是简单的,您需要阅读文档以了解其工作原理。
  2. Aggregation。这是一个特殊的框架,用于执行“mini-Map/Reduce”作业。 group示例清楚地演示了如何执行“按类型求和”。您只需要将命令转换为PHP即可。
  3. Aggregation Framework。这目前只在不稳定的版本(2.1.0)中。这将比选项#2更好,但它只能在2.1+上工作。

...所以请提供PHP代码使其工作

这里没有简单的PHP代码片段,聚合实际上是MongoDB中的一个复杂主题。

首先,您必须选择其中一种方法(#1,#2,#3),然后必须决定您计划如何处理输出。例如,#1 Map/Reduce可以创建一个新的集合来聚合,或者它可以在一行中返回值,但只能返回10k个值。选项#2将串行运行,并且在分片服务器上速度非常慢。选项#3仍处于“beta”状态,并最终将替换#2。

无论如何,在选择攻击计划之前,所有选项都需要进一步阅读。


2
这可以通过以下的MapReduce函数来实现:
var map = function () {
    emit("total", {sum:this.type}) 
    }

var reduce = function (key, values) {
    var result = {sum:0};
    values.forEach(function (value) {result.sum += value.type;});
    return result;
    }

db.table.mapReduce(map, reduce, {out : "type_totals"})

或者在PHP中:

$db->table->mapReduce( array( 
   'map' =>
   'function () {
      emit("total", {sum:this.type});
 }' 
,'reduce' =>
   'function (key, values) {
      var result = {sum:0};
      values.forEach(function (value) {result.sum += value.type;});
      return result;
     }'));

你确定 PHP 语法正确吗?我怀疑 MongoCollection 在 PHP 中是否有 mapReduce 方法。如果我错了,请纠正我。 - kehers

1
$mongo = new Mongo();

$map = new MongoCode("function() { emit('total', this.type); }");
$reduce = new MongoCode("function(k, vals) {
    var sum = 0;
    for(i in vals) {
        sum += vals[i];
    }

    return sum;
}");

$sumtotal = $mongo->db->command(array(
    'mapreduce' => 'tableName',
    'map' => $map,
    'reduce' => $reduce,
    // 'query' => array('col' => 'value'),
    'out' => array('merge' => 'tableName_sum')
));

$result = $mongo->db->selectCollection($sumtotal['result'])->findOne();
$sum = $result['value'];

1
另一个解决方案是在数据库中创建一个脚本,它将汇总所需的数据并返回结果,类似于以下内容:

脚本

function sum() {
   var sum = 0;
   for (var query = db.collection.find({}, {type: 1, _id:0}); query.hasNext();) {
      sum += query.next();
   }
   return sum;
}

PHP

在 PHP 中,连接数据库后的代码通常如下:

$toexec = 'function(x, y) { return sum() }';
$response = $database->execute($toexec, array());

请查看本教程,了解如何使用PHP在Mongo中编写脚本。

http://pointbeing.net/weblog/2010/08/getting-started-with-stored-procedures-in-mongodb.html


1

其他答案已经提供了很多资源。这里只回答所问的问题:

db.YOUR_COLLECTTION.aggregate([ { 
    $group: { 
        _id: null, 
        total: { 
            $sum: "$type" 
        } 
    } 
} ] )

0
Try:
$m = new MongoClient();
$con = $m->selectDB("dbName")->selectCollection("collectionName");
$cond = array(
    array(
        '$group' => array(
            '_id' => null,
           'total' => array('$sum' => '$type'),
        ),
    )
);

$out = $con->aggregate($cond);
print_r($out);

更多细节请点击这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接