我在java上完成了这段代码,它收集有关照片的各种信息并将结果提取到文本文件中。我想将这个程序转换为与MapReduce模型一起使用的功能。我是MapReduce编程的新手。任何帮助将不胜感激!!谢谢
import java.io.*;
import java.util.*;
import java.net.*;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import com.aetrion.flickr.people.User;
import com.aetrion.flickr.photos.Photo;
import com.aetrion.flickr.photos.PhotoList;
import com.aetrion.flickr.photos.PhotosInterface;
import com.aetrion.flickr.photos.SearchParameters;
import com.aetrion.flickr.photosets.PhotosetsInterface;
import com.aetrion.flickr.test.TestInterface;
import com.aetrion.flickr.people.PeopleInterface;
import com.aetrion.flickr.groups.*;
import com.aetrion.flickr.groups.pools.*;
import com.aetrion.flickr.*;
public class example2{
public example2() {
}
/**
* @param args
* @throws FlickrException
* @throws SAXException
* @throws IOException
* @throws ParserConfigurationException
*/
@SuppressWarnings("deprecation")
public static void main(String[] args) throws IOException, SAXException, FlickrException, ParserConfigurationException { // TODO Auto-generated method stub
FileWriter out = new FileWriter("photos.txt");
//Set api key
String key="apikey";
String svr="www.flickr.com";
REST rest=new REST();
rest.setHost(svr);
//initialize Flickr object with key and rest
Flickr flickr=new Flickr(key,rest);
Flickr.debugStream=false;
//initialize SearchParameter object, this object stores the search keyword
SearchParameters searchParams=new SearchParameters();
searchParams.setSort(SearchParameters.INTERESTINGNESS_DESC);
searchParams.setGroupId("group_id");
//Initialize PhotosInterface object
PhotosInterface photosInterface=flickr.getPhotosInterface();
//Execute search with entered tags
PhotoList photoList=photosInterface.search(searchParams,500,1);
if(photoList!=null){
//Get search result and check the size of photo result
for(int i=0;i<photoList.size();i++){
//get photo object
Photo photo=(Photo)photoList.get(i);
System.out.print(photo.getId()+"t");
out.write(photo.getId()+"t");
System.out.print(photo.getOwner().getId()+"t");
out.write(photo.getOwner().getId()+"t");
Photo photo1=photosInterface.getPhoto(photo.getId());
if(photo1.getGeoData() != null ){
System.out.print("latitute="+photo1.getGeoData().getLatitude()+"t");
out.write(photo1.getGeoData().getLatitude()+"t");
System.out.print("longitude="+photo1.getGeoData().getLongitude()+"t");
out.write(photo1.getGeoData().getLongitude()+"t");
}
else {System.out.print(photo1.getGeoData()+"t");
out.write(photo1.getGeoData()+"tt"+photo1.getGeoData());}
System.out.println("");
out.write("n");
}
out.close();
}
}}
我不确定这是Hadoop的一个好用例,除非你有大量的搜索结果要处理,并且处理占整个程序的很大一部分。搜索本身不能并行执行:只能执行 for 循环中的处理。
如果要在Hadoop中并行处理一个搜索,则首先必须在Hadoop**之外执行搜索,并将结果输出到文本文件(例如ID列表)中。然后,编写一个映射器,该映射器获取 ID,获取照片,并执行您当前在 for 循环中执行的处理,发出带有获取属性的字符串(您当前正在打印到 System.out
)。Hadoop 将为结果列表中的每个 ID 单独运行此映射器。
我认为这是不值得的,除非你计划做一些其他处理。需要考虑的一些替代方案:
使用 map-reduce 并行执行许多不同的搜索。你的程序基本上是不变的——它只是在map函数中运行,而不是main()循环。或者,您的搜索可能发生在映射器中,发出结果,而您的处理可能会在化简器中进行。您的输入将是搜索词列表。
忘记map-reduce,只需使用线程池并行运行处理。查看
java.util.concurrent
的各种Executors
。
** 另一种让整个事情"在"Hadoop内部"运行的黑客方法是在map函数中运行搜索,一个接一个地发出结果。使用具有一行文本(虚拟值)的输入文件,以便映射器只运行一次。然后在化简器而不是映射器中获取图像。
更新:
如果要搜索一堆不同的组 ID,则可以使用第一种"替代"方法。
如您所建议的,使用组 ID 和 API 密钥作为输入。在每行上放一个,用制表符或可以轻松解析的内容分隔。如果您希望它们在不同的映射器中运行,您还必须将它们拆分为不同的文件。如果组 ID 与节点一样多,则可能只想在每个文件中放置一行。将TextInputFormat
用于您的 Hadoop 作业。带有组 ID 和 API 密钥的行将是值 - 使用value.toString().split("t")
将其分成两部分。
然后,在映射器中运行整个搜索。对于每个结果,请使用 context.write(key, value)
(或 output.collect(key, value)
,具体取决于您的版本)将带照片的 ID 作为键,并将带有属性的字符串作为值写入。这两者都必须转换为Hadoop的Text
对象。
我不打算为此提供批发代码 - 改编Hadoop MapReduce教程应该很容易。唯一真正的区别:
使用
job.setOutputValueClass(Text)
,并更改它在IntWritable
中显示的位置映射器类签名:public static class Map extends Mapper<LongWritable, Text, Text, Text> {
只需禁用减速器即可。取出减速器类,并更改此内容:
job.setMapperClass(Map.class); job.setCombinerClass(Reduce.class); job.setReducerClass(Reduce.class);
进入这个:
job.setMapperClass(Map.class); job.setNumReduceTasks(0);
如果您对使其工作有具体问题,请随时提出。不过,请先投入一些研究工作。
我不同意蒂姆·耶茨的回答。您的搜索可以很好地进行对准。我的方法如下:
- 实现一个映射器,它将搜索查询的一部分作为输入(你必须自己对它们进行分块,因为这些东西不是序列文件),然后执行查询并将结果写入文件系统。键是 ID,值是您的附加信息。
- 实现一个reduce,使任何你想要的数据(第一步的输出)。
我已经用YouTube API做了这件事,所以它工作得很好。但是您必须注意配额限制。你可以很好地处理它们Thread.sleep(PERIOD_OF_TIME)
。这仅适用于你有一堆搜索查询的情况,如果你有一个用户将输入一个搜索字符串,MapReduce不是(最佳)方式。