【问题标题】:How to map-reduce group, sort and count sort values如何映射减少组、排序和计数排序值
【发布时间】:2012-04-02 12:08:45
【问题描述】:

mapreduce 有一些问题。

我想对集合中的一些值进行分组、排序和计数。我有这样的收藏:

----------------------------
| item_id    |    date      |
----------------------------
| 1          | 01/15/2012   | 
----------------------------
| 2          | 01/01/2012   |
---------------------------- 
| 1          | 01/15/2012   |
----------------------------  
| 1          | 01/01/2012   |
----------------------------
| 2          | 01/03/2012   |
----------------------------
| 2          | 01/03/2012   |
----------------------------
| 1          | 01/01/2012   |
----------------------------
| 1          | 01/01/2012   |
----------------------------
| 2          | 01/01/2012   |
----------------------------
| 2          | 01/01/2012   |
----------------------------

我想按item_id 分组并按天计算每个项目的日期并对每个项目的日期进行排序并得到结果,例如:

value: {{item_id:1, date:{01/01/2012:3, 01/15/2012:2 }},{item_id:2, date:{01/01/2012:3, 01/03/2012:2 }}}

我用mapReduce

m=function()
{
   emit(this.item_id, this.date);
}
r=function(key, values)
{
var res={};
values.forEach(function(v)
{
if(typeof res[v]!='undefined') ? res[v]+=1 : res[v]=1;
});
return res;
}

但我没有收到如下结果:

{{item_id:1, date:{01/01/2012:3, 01/15/2012:2 }},{item_id:2, date:{01/01/2012:3, 01/03/2012:2 }}}

有什么想法吗?

【问题讨论】:

    标签: mongodb sorting mapreduce emit


    【解决方案1】:

    给定输入文件的形式:

    > db.dates.findOne()
    { "_id" : 1, "item_id" : 1, "date" : "1/15/2012" }
    > 
    

    以下 map 和 reduce 函数应该会产生您正在寻找的输出:

    var map = function(){
        myDate = this.date;
        var value = {"item_id":this.item_id, "date":{}};
        value.date[myDate] = 1;
        emit(this.item_id, value);
    }
    
    var reduce = function(key, values){
        output = {"item_id":key, "date":{}};
        for(v in values){
            for(thisDate in values[v].date){
                if(output.date[thisDate] == null){
                    output.date[thisDate] = 1;
                }else{
                    output.date[thisDate] += values[v].date[thisDate];
                }
            }
        }
        return output;
    }
    
    > db.runCommand({"mapReduce":"dates", map:map, reduce:reduce, out:{replace:"dates_output"}})
    
    > db.dates_output.find()
    { "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/15/2012" : 2, "1/01/2012" : 3 } } }
    { "_id" : 2, "value" : { "item_id" : 2, "date" : { "1/01/2012" : 3, "1/03/2012" : 2 } } }
    

    希望以上内容能够满足您的需求,或者至少让您指向正确的方向。

    有关在 MongoDB 中使用 Map Reduce 的更多信息,请参阅 Mongo 文档: http://www.mongodb.org/display/DOCS/MapReduce

    MongoDB Cookbook 中有一些额外的 Map Reduce 示例: http://cookbook.mongodb.org/

    有关如何运行 Map Reduce 操作的分步演练,请参阅 MongoDB Cookbook 食谱“使用版本化文档查找最大值和最小值”http://cookbook.mongodb.org/patterns/finding_max_and_min/ 的“附加”部分。

    祝你好运!

    【讨论】:

    • 马克,感谢您的帮助。在此之后,我对排序日期有一些问题。我想要如: { "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/01/2012" : 3, "1/15/2012" : 2 } } } .我将 sort:{date:1} 添加到 db.runCommand({"mapReduce":"dates", map:map, reduce:reduce,sort:{date:1}, out:{replace:"dates_output"}}) .但是在此操作之后,我有: { "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/01/2012" : 1, "1/15/2012" : 1 } } } 日期是排序的,但 cout 总是 1
    • 你好。我很高兴我能够提供帮助! “值”中的嵌入元素以任何被发现的顺序添加。对日期键上的输入进行排序将使嵌入文档中的日期按顺序排列。但是,在此示例中,日期是字符串,并且不能保证具有较晚日期的字符串具有比具有较早值的字符串更大的值。例如(在 js shell 中): > "10/01/2012"
    • 一旦你处理了这个,你应该能够按照你想要的顺序得到结果: > db.runCommand({"mapReduce":"dates", map:map, reduce :reduce, sort:{"date":1}, out:{replace:"dates_output"}}) 如果您收到类似于“异常:无法在 test.dates 上创建光标以进行查询”的错误,请尝试添加索引到输入集合中的“日期”键。
    • 嗨。马克你能帮忙解决一些问题吗?我有一个集合,其中包含字段:id_1(objectID)、id_2(objectID) 和 date(Date)。当我尝试将您的 mapreduce 与 id_1 一起使用时,我得到了很好的结果:{ "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/01/2012" : 3, "1/ 15/2012" : 2 } } },但是当我使用 id_2 时: { "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/01/2012" : 1, " 1/15/2012" : 1 } } } - 日期计数始终为 1。这两个字段没有区别,我不使用任何排序。我可能在哪里弄错了?
    • 如果在集合中只有两个不同的记录 ID,我会遇到这个问题。我的结果如: id_2 : { "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/01/2012" : 1, "1/15/2012" : 1 } } } ,但是如果我要添加一条记录,我的结果 - "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/01/2012" : 3, " 2012 年 1 月 15 日“:2 } } }。我不明白为什么“分组依据”的记录不起作用
    猜你喜欢
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2019-03-24
    • 2020-10-12
    相关资源
    最近更新 更多