Доступ к ассоциативному массиву / объекту в MongoDB MapReduce - PullRequest
1 голос
/ 26 января 2012

Я пытаюсь собрать имена всех пользователей блога, которые ответили друг другу. У меня есть записи следующим образом:

{
    "_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 }
    } 
}

Этот код работает для каждой записи, в которой есть дочерний элемент только с одним дочерним элементом, но не более:

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

Для любой записи (например, в приведенном примере) с более чем одним дочерним элементом имена авторов не найдены, и я получаю сокращенную запись, например, такую ​​(N.B. Была другая запись от kilny с дочерним DarkKnight3657):

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

У кого-нибудь есть идеи, почему имя автора не читается с объекта?

Спасибо

Ответы [ 2 ]

0 голосов
/ 27 января 2012

Как предположил Крис, решение, которое я использовал, состояло в том, чтобы преобразовать объект в массив:

    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
    }
}
0 голосов
/ 26 января 2012

Я думаю, проблема в том, что вы не определяете connections как массив в маппере - вы определяете его как элемент. Вне моей головы, кажется, что это должно читаться:

var connect = [{'name':c['author'], 'appears':1}];
emit(m_author, {'author':m_author, 'connections':connect});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...