我需要使用mapReduce和/或聚合进行此分析:

DBCollection coll = db.getCollection("documents");
DBCursor cursor = coll.find();
Map<String,Integer> map = new HashMap<String,Integer>();
while(cursor.hasNext()){
    DBObject obj = cursor.next();
    BasicDBList list = (BasicDBList)obj.get("cats");
    for(int i=0;i<list.size();i++){
        String cat = list.get(i).toString();
        int hits   = 0;
        if(map.containsKey(cat)){
            hits = map.get(cat);
        }
        hits++;
        map.put(cat, hits);
    }
}


有人可以给我一个关于如何使用mapReduce和聚合实现我所需要的东西的正确示例吗?

谢谢!

最佳答案

您似乎正在计算数组中元素的唯一出现次数。无论内容是什么,都没有关系,因为您只是在映射中转换为字符串键。但这是一个示例:

{ "cats" : [ 1, 2, 3, 4, 5 ] }
{ "cats" : [ 2, 4 ] }
{ "cats" : [ 1, 5 ] }
{ "cats" : [ 4, 5 ] }


聚合框架是最快的:

db.cats.aggregate([
    { "$unwind": "$cats" },
    { "$group": {
        "_id": "$cats",
        "count": { "$sum": 1 }
    }}
])


产生:

{ "_id" : 5, "count" : 3 }
{ "_id" : 4, "count" : 3 }
{ "_id" : 3, "count" : 1 }
{ "_id" : 2, "count" : 2 }
{ "_id" : 1, "count" : 2 }


Map reduce大致相同,但速度较慢:

db.cats.mapreduce(
    function() {
        this.cats.forEach(function(cat) {
            emit( cat, 1 );
        });
    },
    function(key,values) {
        return Array.sum( values );
    },
    { "out": { "inline": 1 } }
)

07-28 11:54