Это похоже на работу для MapReduce ... но я просто не могу понять это - PullRequest
0 голосов
/ 11 декабря 2010

Я боролся с этим уже около 2 дней, и любая помощь будет принята с благодарностью.В настоящее время у меня есть очень большая коллекция MongoDB (более 100 миллионов документов) в следующем формате:

[_id]
[date]
[score]
[meta1]
[text1]
[text2]
[text3]
[text4]
[meta2]

Это не точные данные, я немного запутал их для целей этого поста, но схема идентична, и формат этих данных не может быть изменен, просто так оно и есть.

Там находится ТОННА дублирующихся записей, задание выполняется один раз в день, добавляя деньмиллионы записей в базе данных, которые могут иметь те же данные в текстовых полях, но разные значения для полей Score, meta1 и meta2.Поэтому мне нужно исключить дубликаты и объединить все в одну коллекцию без повторяющихся текстов:

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

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

Так что если у меня естьследующие три документа в моей коллекции сейчас:

[_id] => random mongoid
[date] => 12092010 
[score] => 3
[meta1] => somemetadatahere
[text1] => foo
[text2] => bar
[text3] => foo2
[text4] => bar2
[meta2] => uniquemeta2data

[_id] => random mongoid
[date] => 12092010
[score] => 5
[meta1] => othermetadata
[text1] => foo
[text2] => bar
[text3] => foo2
[text4] => bar2
[meta2] => uniquemeta2data1

[_id] => random mongoid
[date] => 12102010
[score] => 7
[meta1] => somemetadatahere  (same meta1 as the first document)
[text1] => foo
[text2] => bar
[text3] => foo2
[text4] => bar2
[meta2] => uniquemeta2data

Они должны быть сведены к этой коллекции (отступы - это вложенные документы / массивы).Ключи в массиве данных взяты из значений поля meta1 в исходной коллекции:

[_id]=> (md5 hash of all the text fields)
[text1] => foo
[text2] => bar
[text3] => foo2
[text4] => bar2    
[datas]
    [somemetadatahere]
        [meta2] => uniquemeta2data
        [scores]
            [12092010]=>3
            [12102010]=>7
    [othermetadata]
        [meta2] => uniquemeta2data1   
        [scores]
            [12092010]=>3     

Это похоже на идеальный вариант использования для задания MapReduce, но у меня возникают проблемы с обертываниемкак именно это сделать.

Кто-нибудь готов помочь мне разобраться?

Ответы [ 2 ]

1 голос
/ 11 декабря 2010

По сути, это та же проблема, что и известная проблема частоты слов в mapreduce, но вместо слов вы используете хэши (и ссылку на оригинальную запись):

  • Карта: возьмите хэш каждой записи и сопоставьте ее с парой (хэш, 1). (Чтобы получить исходную запись: создайте объект и используйте исходную запись в качестве свойства).
  • Уменьшить: все записи хеша будут собраны в одном ведре посчитать значения для каждой пары (хеш, 1).
  • Вывести хэши, исходную запись (сохраненную в объекте) и счетчик

Аналогия: кот сидел на коврике

Карта:

  • the - (hash (the), 1)
  • cat -> (hash (cat), 1)
  • sat -> (hash (sat), 1)
  • on -> (hash (on), 1)
  • - - (hash (the), 1)
  • mat -> (hash (mat), 1)

Intermediate:

  • - - (hash (the), 1)
  • cat -> (hash (cat), 1)
  • sat -> (hash (sat), 1)
  • on -> (hash (on), 1)
  • - - (hash (the), 1)
  • mat -> (hash (mat), 1)

Сокращение:

  • (hash (the), 2)
  • (hash (cat), 1)
  • (hash (sat), 1)
  • (hash (on), 1)
  • (hash (mat), 1)
0 голосов
/ 11 декабря 2010

Я думаю, что проблема MapReduce кажется прямой, что означает, что я, вероятно, неправильно понимаю вашу проблему.В любом случае, вот как я это вижу.

Разделите исходную коллекцию на основе текстового хэша.Пусть каждый раздел сосредоточится на объединении полученного подмножества.

Вот код из http://www.dashdashverbose.com/2009/01/mapreduce-with-javascript.html

Я постараюсь отредактировать это, чтобы соответствовать вашему вопросу.

function myMapper(key, value) {
 var ret = [];
 var words = normalizeText(value).split(' ');
 for (var i=0; i<words.length; i++) {
  ret.push({key:words[i], value:1});
 }
 return ret;
}

function myReducer(intermediateKey, values) {
 var sum = 0;
 for (var i=0; i<values.length; i++) {
  sum += values[i];
 }
 return {key:intermediateKey, value:sum};
}

function normalizeText(s) {
 s = s.toLowerCase();
 s = s.replace(/[^a-z]+/g, ' ');
 return s;
}

var i = {};
i.atxt = "The quick brown fox jumped over the lazy grey dogs.";
i.btxt = "That's one small step for a man, one giant leap for mankind.";
i.ctxt = "Mary had a little lamb, Its fleece was white as snow; And everywhere that Mary went, The lamb was sure to go.";

var out = mapReduce(i, myMapper, myReducer);
...