2

我想构建一个 hadoop 应用程序,它可以从一个文件中读取单词并在另一个文件中搜索。

如果单词存在 - 它必须写入一个输出文件 如果单词不存在 - 它必须写入另一个输出文件

我在hadoop中尝试了一些例子。我有两个问题

两个文件每个大约 200MB。检查另一个文件中的每个单词可能会导致内存不足。有没有其他方法可以做到这一点?

由于hadoop的reduce阶段的输出只写入一个文件,如何将数据写入不同的文件。是否可以有一个减少阶段的过滤器来将数据写入不同的输出文件?

谢谢你。

4

3 回答 3

8

我会怎么做:

  1. 用单词分割'map'中的值,发出 (<word>, <source>) (*1)
  2. 你会得到'reduce': (<word>, <list of sources>)
  3. 检查源列表(对于两个/所有源都可能很长)
  4. 如果不是所有来源都在列表中,则每次都发出 (<missingsource>, <word>)
  5. job2: job.setNumReduceTasks(<numberofsources>)
  6. job2:在“地图”中发射(<missingsource>,<word>)
  7. job2:为“reduce”中的每个 <missingsource> 发出所有(null,<word>)

您最终会得到与不同 <missingsources> 一样多的 reduce-outputs,每个都包含文档的缺失词。您可以在 'reduce' 的开头写出 <missingsource> ONCE 来标记文件。

(*1) 如何在地图 (0.20) 中找出来源:

private String localname;
private Text outkey = new Text();   
private Text outvalue = new Text();
...
public void setup(Context context) throws InterruptedException, IOException {
    super.setup(context);

    localname = ((FileSplit)context.getInputSplit()).getPath().toString();
}

public void map(Object key, Text value, Context context)
    throws IOException, InterruptedException {
...
    outkey.set(...);
    outvalue.set(localname);
    context.write(outkey, outvalue);
}
于 2010-01-25T09:43:24.767 回答
1

您是否出于特定原因使用 Hadoop/MapReduce 来解决此问题?这听起来比 Hadoop更适合基于Lucene的应用程序。

如果你必须使用 Hadoop,我有一些建议:

  1. 您的“文档”需要采用 MapReduce 可以处理的格式。最容易使用的格式是基于 CSV 的文件,文档中的每个单词都位于一行。拥有 PDF 等将不起作用。

  2. 要将一组单词作为 MapReduce 作业的输入以与 MapReduce 处理的数据进行比较,您可以使用分布式缓存使每个映射器能够构建一组您想要在输入中找到的单词。但是,如果您的单词列表发现它很大(您提到 200MB),我怀疑这会起作用。但是,此方法是您可以在 MapReduce 中进行连接的主要方法之一。

这里另一个答案中提到的索引方法也提供了可能性。尽管如此,索引文档的术语只是让我想到 Lucene 而不是 hadoop。如果您确实使用了此方法,则需要确保键值包含文档标识符以及单词,以便您拥有每个文档中包含的单词计数。

我认为我从未从 MapReduce 作业中生成多个输出文件。您需要编写一些(并且非常简单)代码来将索引输出处理成多个文件。

于 2010-01-24T23:06:42.993 回答
0

在我看来,您需要分两个阶段执行此操作。对两个初始文档运行 wordcount 程序(包含在 hadoop 示例 jar 中),这将为您提供两个文件,每个文件都包含每个文档中单词的唯一列表(带有计数)。从那里开始,而不是使用 hadoop 对应该回答您的问题的两个文件进行简单的比较,

于 2010-01-24T18:39:57.317 回答