首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我需要一个地图减少函数在mongo使用php

我需要一个地图减少函数在mongo使用php
EN

Stack Overflow用户
提问于 2012-06-11 19:11:22
回答 2查看 3.7K关注 0票数 0

我需要一个由php的mongo地图减少功能

这是我的mongo结构

代码语言:javascript
运行
复制
[_id] => MongoId Object (
    [$id] => 4fcf2f2313cfcd2454500000d
)
[id] => 454
[table] => people
[news] => Array (
    [03-06-2012] => 2
    [04-06-2012] => 3
    [05-06-2012] => 5
    [06-06-2012] => 4
)

在这里,我尝试用下面的代码对数组消息求和,

代码语言:javascript
运行
复制
    $map = new MongoCode('function() { emit(this.news, 1); }');
    $reduce = new MongoCode('function(previous, current) {
                    var count = 0;
                    for (index in current) {
                        count = count + current[index];
                    }
                    return count;
                }');

    $sales = $db->command(array(
        'mapreduce' => 'mycollection',
        'map' => $map,
        'reduce' => $reduce,
        'query' => array('table' => 'people'),
        'out'  => 'news'
    ));

    //pr($sales);exit;

    $users = $db->selectCollection($sales['result'])->find();

    foreach ($users as $user) {
        //echo "{$user['_id']} had {$user['value']} sale(s).\n";
        pr($user);
    }

pr($user)

代码语言:javascript
运行
复制
Array
(
    [_id] => Array
    (
        [04-06-2012] => 0
        [08-06-2012] => 2
        [11-06-2012] => 6
    )

    [value] => 39540
)

我期望的值将是8而不是39540。

如何纠正此函数,如何将字段sum作为'news‘的数组sum添加到原始集合(Mycollection)?

我不熟悉mongo中的map reduce函数。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-13 07:45:51

在调用emit()时,第一个参数是要减少的键(本例中为grouping )。第二个参数是为该键发出的值,可以是任何值。对于您的示例,您可能想要发出news字段中所有值的总和,使用文档的ID作为您的键:

代码语言:javascript
运行
复制
var map = function() {
    var total = 0;
    for (count in this.news) {
        total += count;
    }
    emit(this._id, total);
}

在这种情况下,可以使用占位符reduce函数(因为每个发出的键都是唯一的,所以需要做的缩减很少):

代码语言:javascript
运行
复制
var reduce = function(key, values) {
    var total = 0;
    values.forEach(function(v) { total += v; });
    return total;
}

但是,正如我在Google Group post中提到的,使用纯PHP可能会更好:

代码语言:javascript
运行
复制
$cursor = $collection->find(array(), array('news' => 1));
$cursor->snapshot();

foreach ($cursor as $document) {
    $collection->update(
        array('_id' => $document['_id']),
        array('$set' => array('sum' => array_sum($document['news']))),
        array('multiple' => false)
    );
}

使用map/reduce,您仍然必须检查其结果并更新您的记录。这将避免通过Mongo执行JavaScript的需要,并且应该会更有性能。如果您可以在news字段按文档进行修改时利用$inc更新sums,那就更好了。对于初始化整个集合中的sum字段,或者在与每个文档的增量不同步时纠正任何漂移,上面的代码片段仍然很有用。

注意:有关上述示例中该方法调用背后的原因,请参阅文档中的snapshot()

票数 3
EN

Stack Overflow用户

发布于 2012-10-10 19:03:55

而jmikola的回答给了我处理mongo map reduce函数的wright track。

我添加这个答案是为了帮助未来的访问者。

下面的map-reduce函数完全符合我的要求。这会将新闻字段中的所有值相加到在command中通过添加("out" => "news")创建的名为news的新集合。

映射-Reduce函数

代码语言:javascript
运行
复制
$map = new MongoCode('function() {
            var total = 0;
            for (count in this.news) {
            total +=  this.news[count];
            }
            emit(this._id, {id: this.id, total: total});
        }');
$reduce = new MongoCode('function(key, values) {
            var result = {id: null, total: 0};
            values.forEach(function(v) {
            result.id = v.id;
            result.total = v.total;
             });
            return result;
        }');

$sales = $db->command(array(
    'mapreduce' => 'mycollection', // collection name
    'map' => $map,
    'reduce' => $reduce,
    'query' => array('table' => 'people'),
    "out" => "news" // new collection name
));

结果将是news集合,其中total为sum,实际文档为id

输出

代码语言:javascript
运行
复制
[_id] => MongoId Object (
    [$id] => 4fd8993a13cfcd4e42000000
)
[value] => Array (
    [id] => 454
    [total] => 14
)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10978975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档