在MongoDB中加入“列”的总和

时间:2012-01-16 00:36:26

标签: php math mongodb sum

在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”键的总和?

7 个答案:

答案 0 :(得分:5)

利用MongoDB的新Aggregation Framework

$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

    ),
));

答案 1 :(得分:3)

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

在MongoDB中,您需要为此运行一个特殊命令。你有三个选择。

  1. 使用Map/Reduce。这是在数据集中进行求和,计数,平均等的一般方法。这不是微不足道的,您需要阅读文档以了解其工作原理。
  2. Aggregation。这是执行“迷你地图/减少”工作的特殊框架。 group example清楚地演示了如何“按类型求和”。您只需将命令转换为PHP。
  3. Aggregation Framework。目前仅在不稳定版本(2.1.0)中。这将比选项#2更好,但它只适用于2.1 +。
  4.   

    ...所以请提供PHP代码来完成这项工作

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

    首先,你必须选择其中一种方法(#1,#2,#3)然后你必须决定你打算如何处理输出。例如,#1 Map / Reduce可以使用聚合创建新集合,也可以返回行中的值,但只能返回10k值。选项#2将以串行方式运行,并且在分片服务器上运行速度非常慢。选项#3仍处于“测试阶段”,最终将取代#2。

    在任何情况下,在您选择攻击计划之前,所有选项都需要进一步阅读。

答案 2 :(得分:2)

可以使用以下map reduce函数完成此操作:

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;
     }'));

答案 3 :(得分:1)

另一种解决方案是在数据库中创建一个脚本,该脚本将对需求数据求和并返回结果,如:

剧本

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

PHP

在设置与db的连接之后的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

答案 4 :(得分: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'];

答案 5 :(得分:0)

其他答案已经提供了很多来源。只是回答问题:

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

答案 6 :(得分: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);

更多细节click here