инвертированный индекс hadoop без повторения имен файлов

что у меня есть на выходе:

слово , файл ----- ------ wordx Doc2, Doc1, Doc1, Doc1, Doc1, Doc1, Doc1, Doc1

что я хочу:

слово, файл ----- ------ wordx Doc2, Doc1

public static class LineIndexMapper extends MapReduceBase
        implements Mapper<LongWritable, Text, Text, Text> {

    private final static Text word = new Text();
    private final static Text location = new Text();

    public void map(LongWritable key, Text val,
            OutputCollector<Text, Text> output, Reporter reporter)
            throws IOException {
        FileSplit fileSplit = (FileSplit) reporter.getInputSplit();
        String fileName = fileSplit.getPath().getName();
        location.set(fileName);

        String line = val.toString();
        StringTokenizer itr = new StringTokenizer(line.toLowerCase());
        while (itr.hasMoreTokens()) {
            word.set(itr.nextToken());
            output.collect(word, location);
        }
    }
}

public static class LineIndexReducer extends MapReduceBase
        implements Reducer<Text, Text, Text, Text> {

    public void reduce(Text key, Iterator<Text> values,
            OutputCollector<Text, Text> output, Reporter reporter)
            throws IOException {

        boolean first = true;
        StringBuilder toReturn = new StringBuilder();
        while (values.hasNext()) {
            if (!first) {
                toReturn.append(", ");
            }
            first = false;
            toReturn.append(values.next().toString());
        }

        output.collect(key, new Text(toReturn.toString()));
    }
}

для лучшей производительности - где я должен пропустить повторяющееся имя файла? карта, уменьшить или оба? ps: я новичок в написании задач MR, а также пытаюсь понять логику программирования с моим вопросом.


person likeaprogrammer    schedule 24.04.2012    source источник


Ответы (2)


Вы сможете удалить дубликаты только в Reducer. Для этого вы можете использовать набор, который не допускает дублирования.

public void reduce(Text key, Iterator<Text> values,
        OutputCollector<Text, Text> output, Reporter reporter)
        throws IOException {

    // Text's equals() method should be overloaded to make this work
    Set<Text> outputValues = new HashSet<Text>();

    while (values.hasNext()) {
      // make a new Object because Hadoop may mess with original
      Text value = new Text(values.next());

      // takes care of removing duplicates
      outputValues.add(value);
    }

    boolean first = true;
    StringBuilder toReturn = new StringBuilder();
    Iterator<Text> outputIter = outputValues.iter();
    while (outputIter.hasNext()) {
        if (!first) {
            toReturn.append(", ");
        }
        first = false;
        toReturn.append(outputIter.next().toString());
    }

    output.collect(key, new Text(toReturn.toString()));
}

Изменить: добавляет копию значения в набор согласно комментарию Криса.

person Matt D    schedule 24.04.2012

Вы можете повысить производительность, выполнив локальную агрегацию карт и внедрив объединитель - в основном вы хотите уменьшить объем данных, передаваемых между вашими картографами и редюсерами.

Агрегация локальной карты — это концепция, при которой вы поддерживаете LRU, подобную карте (или набору), выходных пар. В вашем случае набор слов для текущего документа картографа (при условии, что у вас есть один документ на карту). Таким образом, вы можете искать слово в наборе и выводить пару K, V только в том случае, если набор еще не содержит этого слова (указывая, что вы еще не вывели для него запись). Если набор не содержит слова, выведите слово, пару docid и обновите набор словом.

Если набор становится слишком большим (скажем, 5000 или 10000 записей), очистите его и начните сначала. Таким образом, вы увидите количество значений, выводимых из преобразователя, значительно (если ваша область значений или набор значений невелики, хорошим примером для этого являются слова).

Вы также можете ввести свою логику редуктора на этапе объединения.

Последнее предупреждение - будьте осторожны при добавлении объектов Key/Value в наборы (как в ответе Мэтта Д.), Hadoop повторно использует объекты под капотом, поэтому не удивляйтесь, если вы получите неожиданные результаты, если добавите ссылки - всегда создавайте копию объекта.

Есть статья о локальной агрегации карт (для примера подсчета слов), которая может оказаться полезной:

person Chris White    schedule 24.04.2012