Расчет рейтинга страницы в mongodb

Я пытаюсь запустить pagerank, используя mapreduce в mongodb.

Мои документы в таком формате:

{
        "_id" : "u: 10000",
        "value" : [
                [
                        "u: 10000",
                        "s: 985272",
                        1
                ],
                [
                        "s: 985272",
                        "u: 10000",
                        1
                ],
                [
                        "u: 10000",
                        "s: 303770",
                        1
                ],
                [
                        "s: 303770",
                        "u: 10000",
                        1
                ]
        ]
}

Теперь думаю первым делом собрать ссылки по ключу. Однако у меня есть несколько исходящих ссылок на документ. (Все они являются двунаправленными).

Вот моя карта и функции сокращения:

m = function () {
    for (var i = 0; i < this.value.length; i++){
        var out = {};
        out.out = this.value[i][1];
        out.weight = this.value[i][2];
        emit(this.value[i][0], [out]);
    }
}

r = function(key, values){
    var result = {
      value: [] 
    };
    values.forEach(function(val) {
    result.value.push({out: val.out, weight: val.weight});
    });
    return result;
}

Проблема в том, что я не уверен, что эмиссия производит несколько эмиссий на документ. Когда я получаю такие результаты, как:

{
        "_id" : "s: 1000082",
        "value" : [
                {
                        "out" : "u: 37317",
                        "weight" : 1
                }
        ]
}

Когда я ожидал бы несколько элементов в документе.

У кого-нибудь есть идеи? Помощь приветствуется!

РЕДАКТИРОВАТЬ:

Я не полностью удовлетворен, например, как это работает?. Результат сокращения совсем не похож на вывод излучателя.


person toofarsideways    schedule 01.07.2012    source источник
comment
не могли бы вы уточнить, какие значения полей? что такое s и u и т.д.?   -  person Asya Kamsky    schedule 02.07.2012
comment
Это просто разные типы документов (веб-страниц) с сопровождающими идентификаторами...   -  person toofarsideways    schedule 02.07.2012
comment
приведенный ниже ответ правильный - если у вас возникли проблемы с добавлением дополнительных полей к испускаемому значению, я бы предложил начать новый вопрос.   -  person Asya Kamsky    schedule 03.07.2012
comment
Я добавил некоторые разъяснения в ответ, но я описываю именно то, как работает пример, на который вы ссылаетесь, поэтому я не уверен, с чем связано ваше недовольство. В этом примере карта выдает автора в качестве ключа и {votes: this.votes} в качестве значения. При уменьшении он возвращает {голоса: сумма}, что в точности соответствует структуре значения.   -  person Asya Kamsky    schedule 04.07.2012
comment
Извините, день вдали от этого делает это намного яснее. Спасибо за помощь.   -  person toofarsideways    schedule 05.07.2012


Ответы (1)


Проблема в том, что вы не отображаете массив, но ваше сокращение пытается нажать на массив.

Если вы хотите, чтобы каждая клавиша сопоставлялась с массивом пар «out» и «weight», вам нужно создать массив, содержащий это, и в вашем уменьшении вам нужно объединить массивы вместе.

Помните, что структура объекта, возвращаемого функцией сокращения, должна быть идентична структуре испускаемое значение функции карты.

Это означает, что когда ваша карта испускает (ключ, значение), структура «значения» должна быть идентична структуре того, что возвращает ваша функция сокращения в результате.

Если вы измените свою функцию карты на это, чтобы это значение было документом с полем «значение», которое представляет собой массив документов, каждый из которых имеет поле «вне» и поле «вес»:

function () {
    for (var i = 0; i < this.value.length; i++) {
        key = this.value[i][0];
        value = {value:[{out:this.value[i][1], weight:this.value[i][2]}]};
        emit(key, value);
    }
}

и ваша функция сокращения к этому, которая создает результат, чтобы иметь структуру, идентичную значению, которое вы испускаете выше (поскольку оно просто объединяет то, что передается для каждого ключа):

function (key, values) {
    result = {value:[]};
    for (var i in values) {
        result.value = values[i].value.concat(result.value);
    }
    return result;
}

тогда вы получите то, что вы ожидаете обратно.

{
    "_id" : "s: 303770",
    "value" : {
        "value" : [
            {
                "out" : "u: 10000",
                "weight" : 1
            }
        ]
    }
}
{
    "_id" : "s: 985272",
    "value" : {
        "value" : [
            {
                "out" : "u: 10000",
                "weight" : 1
            }
        ]
    }
}
{
    "_id" : "u: 10000",
    "value" : {
        "value" : [
            {
                "out" : "s: 303770",
                "weight" : 1
            },
            {
                "out" : "s: 985272",
                "weight" : 1
            }
        ]
    }
}
person Asya Kamsky    schedule 01.07.2012
comment
Должен ли каждый документ проходить этап сокращения? Я спрашиваю только потому, что добавил значение ранга в первую карту значений, но оно появляется только в некоторых документах. r = function (key, values) { result = {rank:1.0, value:[]}; for (var i in values) { result.value = values[i].value.concat(result.value); } return result; } - person toofarsideways; 02.07.2012
comment
каждый документ сопоставляется - вы должны испускать из карты тот же формат, который возвращает функция сокращения. - person Asya Kamsky; 02.07.2012
comment
Подождите, тогда как такие вещи работают? -› kylebanker.com/blog/2009/12/mongodb-map -reduce-основы. Результат сокращения совсем не похож на вывод излучателя. - person toofarsideways; 02.07.2012
comment
map выводит пары (ключ, значение) - сокращение должно возвращать тот же формат, что и формат значения - ключевая часть является неявной. - person Asya Kamsky; 03.07.2012
comment
Я предполагаю, что ранг - это то, что вам нужно вычислить на этапе завершения. mongodb.org/display/DOCS/MapReduce#MapReduce-FinalizeFunction, но было бы проще разобрать как отдельный вопрос. Если вы не добавили ранг к тому, какая карта испускается с каждым ключом, маловероятно, что опубликованная вами функция сокращения верна. - person Asya Kamsky; 03.07.2012