Hadoop从另一个文件中的一个文件中搜索单词

时间:2010-01-24 18:33:19

标签: hadoop mapreduce

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

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

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

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

如何将数据写入不同的文件,因为hadoop的reduce阶段的输出只写入一个文件。是否可以使用过滤器来减少相位以将数据写入不同的输出文件?

谢谢。

3 个答案:

答案 0 :(得分:8)

我该怎么做:

  1. 在'map'中按字词拆分值,发出(< word>,< source>)(* 1)
  2. 你会进入'减少':(< word>,<来源列表>)
  3. 检查source-list(两个/所有来源可能很长)
  4. 如果并非所有来源都在列表中,则每次都会发出(< missingsource>,< word>)
  5. job2:job.setNumReduceTasks(< numberofsources>)
  6. job2:在'map'中发出(< missingsource>,< word>)
  7. job2:为每个< missingsource>发出在'reduce'all(null,< word>)
  8. 你最终会得到与不同的< missingsources>一样多的reduce-outputs,每个包含文档的缺失单词。你可以写出< missingsource>在'reduce'开头的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);
    }
    

答案 1 :(得分:1)

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

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

  1. 您的'文档'需要采用MapReduce可以处理的格式。最简单的格式是基于CSV的文件,文档中的每个单词都在一行上。 PDF等不起作用。

  2. 要将一组单词作为输入提供给MapReduce作业,以便与MapReduce处理的数据进行比较,您可以使用Distributed Cache使每个映射器构建一组您想要查找的单词在输入中。但是如果你的单词列表很大(你提到200MB)我怀疑这会起作用。这种方法是您在MapReduce中进行连接的主要方法之一。

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

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

答案 2 :(得分:0)

在我看来,你会分两个阶段来做这件事。对两个初始文档运行wordcount程序(包含在hadoop示例jar中),这将为您提供两个文件,每个文件包含每个文档中单词的唯一列表(带有计数)。从那里,而不是使用hadoop做两个文件的简单差异,应​​该回答你的问题,