访问MongoDB MapReduce中的关联数组/对象

时间:2012-01-26 15:04:21

标签: javascript mongodb mapreduce

我正在尝试聚合博客上彼此回复的所有用户的名称。我的记录如下:

{
    "_id" : ObjectId("4ee9ada4edfb941f3400ba63"),
    "thread" : "Millenium - Niels Arden Oplev",
    "author" : "kilny17",
    "parent_count" : 0,
    "parents" : [ ],
    "child_count" : 2,
    "date" : ISODate("2010-04-20T21:14:00Z"),
    "message" : "I don't think so...",
    "children" : [
            {
                    "date" : ISODate("2010-04-20T21:21:00Z"),
                    "author" : "Kissoon"
            },
            {
                    "date" : ISODate("2010-04-20T21:49:00Z"),
                    "author" : "Twain"
            }
    ]
}

我试图为每个作者返回一个MapReduced对象,例如:

{ "_id" : "kilny17",
"value" : { 
    "author" : "kilny17", 
    "connections" : {
          "Kissoon" : 1, 
          "Twain" : 1 }
    } 
}

此代码适用于每个只包含1个子元素的子元素的记录,但不是更多:

    function mapf()
    {   
        var count = this['child_count'];

        if (count > 0){
            var m_author = this.author;

            this['children'].forEach( function(c){

                    var connect = {'name':c['author'], 'appears':1};
                    emit(m_author, {'author':m_author, 'connections':connect});                   
            });
        };           
    }

    function reducef(key, values)
    {   
        var connects = new Object();          
        var r = {'author':key, 'connections':connects, 'weight':0};

        values.forEach(function(v)
        {   
            c_name = v['connections'].name;
            if (c_name == null)
                c_name = 'Null_name';

            if (r['connections'][c_name] != null)
                r['connections'][c_name] += v['connections']['appears'];
            else
                r['connections'][c_name] = v['connections']['appears'];

        });

       return r;        
    }

对于有超过1个孩子的任何记录(例如给出的例子),找不到作者姓名,我得到一个缩小的记录,如此(N.B.还有一个带有孩子DarkKnight3657的昵称的帖子):

 { "_id" : "kilny17", "value" : { "author" : "kilny17", "connections" : { "DarkKnight3657" : 1, "Null_name" : null } } }

任何人都有任何关于为什么没有从对象中读取作者姓名的想法?

由于

2 个答案:

答案 0 :(得分:0)

我认为问题在于您没有将connections定义为mapper中的数组 - 您将其定义为元素。在我的头顶,它似乎应该读:

var connect = [{'name':c['author'], 'appears':1}];
emit(m_author, {'author':m_author, 'connections':connect});

答案 1 :(得分:0)

正如克里斯所建议的,我使用的解决方案是将对象更改为数组:

    function mapf()
    {   
        if (this['child_count'] > 0){

            var m_author = this.author;
            if ( m_author == '')
                m_author = 'Unknown_author';

            var connect = [];
            var weight = 0;

            for ( c in this['children'] ){
                c_name =  this['children'][c]['author'];
                found = false;
                for (i in connect){
                    if (connect[i]['name'] == c_name){
                        connect[i]['appears'] += 1;
                        found = true;
                    }
                }
                if (found == false){
                   var con = {'name':c_name,'appears':1};
                   connect.push(con);
                }
                weight += 1;
            };       
            emit(m_author, {'author':m_author, 'connections':connect, 'weight':weight});
        };
    }

    function reducef(key, values)
    {   
        var r = {'author':key, 'connections':[], 'weight':0};

        values.forEach(function(v)
        {   
            for ( c in v['connections'] ){
                c_name =  v['connections'][c]['name'];
                found = false;
                for (i in r['connections']){
                    if (r['connections'][i]['name'] == c_name){
                        r['connections'][i]['appears'] += 1;
                        found = true;
                    }
                }
                if (found == false){
                   var con = {'name':c_name,'appears':1};
                   r['connections'].push(con);
                }
            };
            r.weight += v.weight;
        });
       return r;
    }

然后产生了所需类型的记录:

{
    "_id" : "Skaundee",
    "value" : {
            "author" : "Skaundee",
            "connections" : [
                    {
                            "name" : "Carnage",
                            "appears" : 1
                    },
                    {
                            "name" : "Tree",
                            "appears" : 1
                    }
            ],
            "weight" : 2
    }
}