Hadoop 2.7.3 mapreduce (4) 역 색인 실현

1. 후진 색인 안내
역 배열 색인 은 문서 검색 시스템 에서 가장 자주 사용 되 는 데이터 구조 로 전문 검색엔진 에 널리 사용 된다.이것 은 주로 어떤 단어 (또는 어구) 를 문서 나 문서 의 저장 위치 에 저장 하 는 데 사 용 됩 니 다. 즉, 내용 에 따라 문 서 를 찾 는 방식 을 제공 합 니 다.문서 에 포 함 된 내용 을 문서 에 따라 확인 하 는 것 이 아니 라 상 반 된 작업 (키워드 에 따라 문 서 를 찾 음) 을 했 기 때문에 역 색인 (Inverted Index) 이 라 고 합 니 다.
2. 지도 과정
먼저 기본 TextInputFormat 클래스 를 사용 하여 입력 파일 을 처리 하고 텍스트 의 줄 마다 편 이 량 과 내용 을 얻 습 니 다.분명 한 것 은 Map 과정 에서 먼저 입력 한 < key, value > 쌍 을 분석 하고 후진 색인 에 필요 한 세 가지 정 보 를 얻어 야 합 니 다. 단어, 문서 URI 와 단어 주파 수 를 얻 을 수 있 습 니 다.여기에 두 가지 문제 가 존재 한다.
첫째, < key, value > 는 두 개의 값 만 있 을 수 있 습 니 다. hadop 사용자 정의 데이터 형식 을 사용 하지 않 은 상태 에서 상황 에 따라 두 개의 값 을 하나의 값 으로 합 쳐 key 또는 value 값 으로 해 야 합 니 다.
둘째, 하나의 Reduce 과정 을 통 해 주파수 통계 와 문서 목록 을 동시에 완성 할 수 없 기 때문에 Combine 과정 을 추가 하여 주파수 통 계 를 완성 해 야 합 니 다.
여기 서 단어 와 URI 를 Key 값 (예 를 들 어 'MapReduce: 1. txt') 으로 구성 하고 단어의 주파 수 를 value 로 한다. 이렇게 하면 MapReduce 프레임 워 크 가 자체 적 으로 가지 고 있 는 Map 단 을 이용 하여 정렬 하고 같은 문서 의 같은 단어의 주파 수 를 목록 으로 구성 하여 Combine 과정 에 전달 하여 WordCount 와 유사 한 기능 을 실현 할 수 있다 는 장점 이 있다.
package com.yc.hadoop.mapreduce.demo06;

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;

public class InvertedIndexMapper extends Mapper {

	public static final Text ONE = new Text("1");

	@Override
	protected void map(LongWritable key, Text value, Mapper.Context context)
			throws IOException, InterruptedException {

		//          
		String[] words = value.toString().split("\\s+"); //      
		FileSplit fs = (FileSplit) context.getInputSplit();//       
		String temp = fs.getPath().getName();//       
		String fileName = temp.substring(0, temp.lastIndexOf(".")); //      

		Text keyValue = new Text();

		for (String word : words) {
			keyValue.set(word + ":" + fileName); //              key
			context.write(keyValue, ONE);
		}
	}

}

3. 결합 과정
map 방법 으로 처리 한 후에 Combine 과정 에서 key 값 과 같은 value 값 을 누적 하여 문서 에 있 는 단어의 주파 수 를 얻 을 수 있 습 니 다.Map 의 출력 결 과 를 Reduce 프로 세 스 의 입력 으로 직접 입력 하면 Shuffle 프로 세 스 에서 문제 가 발생 합 니 다. 같은 단 어 를 가 진 모든 기록 (단어, URI, 단어 주파수 로 구성) 은 같은 Reduce 에 맡 겨 야 하지만 현재 key 값 은 이 를 보장 할 수 없습니다. key 값 과 value 값 을 수정 해 야 합 니 다.이번 에는 단 어 를 key 값 으로, URI 와 주파 수 를 value 값 으로 합 니 다.이렇게 하면 MapReduce 프레임 워 크 의 기본 HashPartitioner 류 를 이용 하여 Shuffle 과정 을 완성 하고 같은 단어의 모든 기록 을 같은 Reducer 에 보 낼 수 있다 는 장점 이 있다.
package com.yc.hadoop.mapreduce.demo06;

import java.io.IOException;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class InvertedIndexCombiner extends Reducer {

	@Override
	protected void reduce(Text key, Iterable values, Reducer.Context context)
			throws IOException, InterruptedException {
		String[] wf = key.toString().split(":");	//  key     
		int count = 0;
		for (Text v : values) {
			count += Integer.parseInt(v.toString());	//    1      1
		}
		context.write(new Text(wf[0]), new Text(wf[1] + ":" + count));
	}

}

4. 감소 과정
상기 두 과정 을 거 친 후 Reduce 과정 은 같은 key 값 의 value 값 을 역 배열 색인 파일 에 필요 한 형식 으로 조합 하면 되 고 나머지 일 은 MapReduce 프레임 워 크 에 직접 맡 길 수 있다.
package com.yc.hadoop.mapreduce.demo06;

import java.io.IOException;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class InvertedIndexReducer extends Reducer {

	@Override
	protected void reduce(Text key, Iterable values, Reducer.Context context)
			throws IOException, InterruptedException {
		StringBuilder sb = new StringBuilder();
		for (Text v : values) {
			sb.append(v + ";");
		}
		Text value = new Text(sb.substring(0, sb.length() - 1));
		context.write(key, value);
	}

}

5. 구동 실현
package com.yc.hadoop.mapreduce.demo06;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 *     
 * 
 * @author S3
 *
 */
public class InvertedIndexDemo {

	public static void main(String[] args) throws Exception {

		Configuration conf = new Configuration();
		Job job = Job.getInstance(conf, "ReverseIndexDemo");
		job.setJarByClass(InvertedIndexDemo.class);

		// map
		job.setMapperClass(InvertedIndexMapper.class);
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(Text.class);

		// combiner
		job.setCombinerClass(InvertedIndexCombiner.class); //     

		// reduce
		job.setReducerClass(InvertedIndexReducer.class); //     

		Path inPath = new Path("/hadoop_data/data/text*.txt");
		Path outPath = new Path("/hadoop_data/out");
		
		FileSystem fs = outPath.getFileSystem(conf);
		if (fs.exists(outPath)) {
			fs.delete(outPath, true);
		}
		FileInputFormat.setInputPaths(job, inPath);
		FileOutputFormat.setOutputPath(job, outPath);
		System.out.println(job.waitForCompletion(true) ? 0 : 1);
	}
}

운행 결과
(1) map 결과:
key:Hello:text1, value:1 key:world:text1, value:1 key:Hello:text1, value:1 key:haddop:text1, value:1 key:Hello:text1, value:1 key:java:text1, value:1
key:Hello:text2, value:1 key:codeFarmer:text2, value:1 key:Hello:text2, value:1 key:yc:text2, value:1
(2) combine 결과:
key:Hello:text1, value:3 key:haddop:text1, value:1 key:java:text1, value:1 key:world:text1, value:1
key:Hello:text2, value:2 key:codeFarmer:text2, value:1 key:yc:text2, value:1
(3) reduce 결과:
key:Hello, value:text2:2;text1:3 key:codeFarmer, value:text2:1 key:haddop, value:text1:1 key:java, value:text1:1 key:world, value:text1:1 key:yc, value:text2:1
(4) 출력 텍스트:
Hello    text2:2;text1:3 codeFarmer    text2:1 haddop    text1:1 java    text1:1 world    text1:1 yc    text2:1
참고: [Hadoop 기초 튜 토리 얼] 9. Hadoop 의 후진 색인

좋은 웹페이지 즐겨찾기