`
qindongliang1922
  • 浏览: 2184769 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
7265517b-f87e-3137-b62c-5c6e30e26109
证道Lucene4
浏览量:117556
097be4a0-491e-39c0-89ff-3456fadf8262
证道Hadoop
浏览量:125938
41c37529-f6d8-32e4-8563-3b42b2712a50
证道shell编程
浏览量:59942
43832365-bc15-3f5d-b3cd-c9161722a70c
ELK修真
浏览量:71312
社区版块
存档分类
最新评论

如何将Lucene索引写入Hadoop?

阅读更多
转载请务必注明,原创地址,谢谢配合!
http://qindongliang1922.iteye.com/blog/2088076

Hadoop是Lucene的子项目,现在发展如火如荼,如何利用Hadoop的分布式处理能力,来给Lucene提高建索引的效率呢,如此一来,便能充分利用HDFS的所有优点,但众所周知,HDFS系统,对随机读支持的并不友好,而像Lucene这种全文检索的框架,几乎所有的检索操作,都离不开随机读写的操作,那么如何才能使Lucene结合hadoop完美的工作呢,其实hadoop的版本里,在一个contrib的工具包里面,带了Lucene索引的工具类,不过貌似是用的人很少,散仙没有用过这个,在这里就不多评价了。


在solr4.4之后的项目,里面已经集成了像HDFS写入索引的jar包,如果你是在solr里面,那么很容易就能够,把索引建在HDFS上,只需要在solrconfig.xml里面配置Directory的实现类为HDFSDirectory即可,但是solr4.4里面的jar仅仅支持,最新版的hadoop,也就2.0之后的,直接在1.x的hadoop里使用,会出现异常,这是由于,2.x和1.x的hadoop的API变化,散仙改了部分源码后,可以支持对1.x的hadoop进行索引,查询操作,在文末,散仙会把这几个类,给上传上来,用时,只需把这几个类导入工程即可。

下面看下散仙的测试demo的源码:

package  indexhadoop;

import hdfs.HdfsDirectory;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Version;
 

/**
 * 
 * @author qindongliang
 * 将索引存储在HDFS上的demo
 * 支持hadoop1.x的版本
 * 
 * **/
public class MyIndex {

	
	public static void main(String[] args)throws Exception {
		//long a=System.currentTimeMillis();
	  //add();
	 	// long b=System.currentTimeMillis();
	 	// System.out.println("耗时: "+(b-a)+"毫秒");
		     query("中国");
		//delete("3");//删除指定ID的数据
	}
	
	
	
	/***
	 * 得到HDFS的writer
	 * 
	 * **/
	public static IndexWriter  getIndexWriter() throws Exception{
		
		Analyzer  analyzer=new SmartChineseAnalyzer(Version.LUCENE_46);
 		IndexWriterConfig    config=new IndexWriterConfig(Version.LUCENE_46, analyzer);
 		Configuration conf=new Configuration();
 		//Path p1 =new Path("hdfs://10.2.143.5:9090/root/myfile/my.txt");
 		//Path path=new Path("hdfs://10.2.143.5:9090/root/myfile");
 		Path path=new Path("hdfs://192.168.75.130:9000/root/index");
 		HdfsDirectory directory=new HdfsDirectory(path, conf);
 		IndexWriter writer=new IndexWriter(directory, config);
 		
 		return writer;
		
	}
	
	/**
	 * 建索引的方法
	 * 
	 * **/
	public static void add()throws Exception{
	      
		IndexWriter writer=getIndexWriter();	
		 
		
//		doc.add(new StringField("id", "3", Store.YES));
//		doc.add(new StringField("name", "lucene是一款非常优秀的全文检索框架", Store.YES));
//		doc.add(new TextField("content", "今天发工资了吗", Store.YES));
//		Document doc2=new Document();
//		doc.add(new StringField("id", "4", Store.YES));
//		doc2.add(new StringField("name", "今天天气不错呀", Store.YES));
//		doc2.add(new TextField("content", "钱存储在银行靠谱吗", Store.YES));
//		Document doc3=new Document();
//		doc3.add(new StringField("id", "5", Store.YES));
//		doc3.add(new StringField("name", "没有根的野草,飘忽的命途!", Store.YES));
//		doc3.add(new TextField("content", "你工资多少呀!", Store.YES));
//		 writer.addDocument(doc);
//		 writer.addDocument(doc2);
//		writer.addDocument(doc3);
		for(int i=6;i<10000;i++){
			Document doc=new Document();
			doc.add(new StringField("id", i+"", Store.YES));
			doc.add(new StringField("name", "lucene是一款非常优秀的全文检索框架"+i, Store.YES));
			doc.add(new TextField("content", "今天发工资了吗"+i, Store.YES));
			writer.addDocument(doc);
			if(i%1000==0){
				writer.commit();
			}
		}
		 writer.forceMerge(1);
		writer.commit();
		System.out.println("索引10000条数据添加成功!");
		writer.close();
	}
	
	/***
	 * 添加索引
	 * 
	 * **/
	public static void add(Document d)throws Exception{
      
		IndexWriter writer=getIndexWriter();	
		writer.addDocument(d);
		 writer.forceMerge(1);
		writer.commit();
		System.out.println("索引10000条数据添加成功!");
		writer.close();
	}
	
	/**
	 * 根据指定ID
	 * 删除HDFS上的一些数据
	 * 
	 * 
	 * **/
	public static void delete(String id)throws Exception{
		
		
		IndexWriter writer=getIndexWriter();
		writer.deleteDocuments(new Term("id", id));//删除指定ID的数据
		writer.forceMerge(1);//清除已经删除的索引空间
		writer.commit();//提交变化
		
		System.out.println("id为"+id+"的数据已经删除成功.........");
		
		
	}
	
	/**
	 * 检索的方法 
	 * 
	 * **/
	public static void query(String queryTerm)throws Exception{
		System.out.println("本次检索内容:  "+queryTerm);
		Configuration conf=new Configuration();
 		//Path p1 =new Path("hdfs://10.2.143.5:9090/root/myfile/my.txt");
 	//	Path path=new Path("hdfs://192.168.75.130:9000/root/index");
 		Path path=new Path("hdfs://192.168.75.130:9000/root/output/map1");
		Directory directory=new HdfsDirectory(path, conf);
		IndexReader reader=DirectoryReader.open(directory);
		System.out.println("总数据量: "+reader.numDocs());
		long a=System.currentTimeMillis();
		IndexSearcher searcher=new IndexSearcher(reader);
		QueryParser parse=new QueryParser(Version.LUCENE_46, "city", new SmartChineseAnalyzer(Version.LUCENE_46));
		
		 Query query=parse.parse(queryTerm);
		
		 TopDocs docs=searcher.search(query, 100);
		 
 	 System.out.println("本次命中结果:   "+docs.totalHits+"  条" );
//		 for(ScoreDoc sc:docs.scoreDocs){
//			 
//			 System.out.println("评分:  "+sc.score+"  id : "+searcher.doc(sc.doc).get("id")+"  name:   "+searcher.doc(sc.doc).get("name")+"   字段内容: "+searcher.doc(sc.doc).get("content"));
//			 
//		 }
		long b=System.currentTimeMillis();
		System.out.println("第一次耗时:"+(b-a)+" 毫秒");
		System.out.println("============================================");
		long c=System.currentTimeMillis();
		   query=parse.parse(queryTerm);
			
		   docs=searcher.search(query, 100);
		 System.out.println("本次命中结果:   "+docs.totalHits+"  条" );
//		 for(ScoreDoc sc:docs.scoreDocs){
//			 
//			 System.out.println("评分:  "+sc.score+"  id : "+searcher.doc(sc.doc).get("id")+"  name:   "+searcher.doc(sc.doc).get("name")+"   字段内容: "+searcher.doc(sc.doc).get("content"));
//			 
//		 }
		long d=System.currentTimeMillis();
		System.out.println("第二次耗时:"+(d-c)+" 毫秒");
		
		 reader.close();
		 directory.close();
		 
		 System.out.println("检索完毕...............");
	 
		
		
		
	}
	
	
	
	
}



上面是散仙测试的例子,经测试,对HDFS上的lucene索引的增删改查都没问题,但有一点需要注意,lucene结合hadoop,确实能大大提升建索引的速度,但是在检索上却没有任何优势,虽然也可以检索,但是速度比较慢,目前的存储实现,是利用了block cache的缓存特性,能使得检索性能差强人意,但是数据量大的时候,检索性能非常糟糕,这一点到现在还没有任何比较好的解决方法,除非,以后给lucene,或solr,增加类似Hbase的数据结构,如此以来,检索上可能会好很多。

上面的代码能够将索引,写入1.x的hadoop中,后续,散仙会给出,在hadoop2.x中建索引的例子,以及如何使用MapReduce并行建索引。


转载请务必注明,原创地址,谢谢配合!
http://qindongliang1922.iteye.com/blog/2088076

分享到:
评论
2 楼 qindongliang1922 2015-03-20  
流程可还成 写道
您好可否告知您写这个程序用的lucene版本感激不尽

Lucene4.6
1 楼 流程可还成 2015-03-19  
您好可否告知您写这个程序用的lucene版本感激不尽

相关推荐

    luncen写入hadoop实例

    4. **将Luncen集成到Hadoop**:集成过程包括创建Lucene索引,然后使用Hadoop的API(如HDFS API)将索引写入HDFS。在Java代码中,你需要创建一个Hadoop Configuration对象,设置HDFS的相关参数,然后使用FileSystem...

    hadoop.contrib/lucene源码

    5. **索引写入和存储**:最后,Reducer生成的全局倒排索引被写入HDFS,以便后续的查询操作。 文件名为"Index0.20"可能表示这是一个特定版本的Hadoop与Lucene结合构建的倒排索引,版本号可能是0.20。这个文件包含了...

    基于Lucene和HDFS的PB级数据索引、搜索、存储系统.zip

    3. **Lucene索引分布**:每个HDFS节点上的数据都会被本地化的Lucene实例进行索引,确保索引与数据的物理位置相对应,减少网络传输开销。 4. **Shard和Replication**:Lucene的索引可能会被分成多个碎片(shards),...

    lucene3.5源码

    3. 索引写入(IndexWriter):负责构建倒排索引,将文档字段中的关键词与文档ID关联起来。倒排索引是Lucene搜索速度的关键,它允许快速定位到包含特定关键词的文档。 三、搜索过程 1. 查询解析器(QueryParser):...

    在HDFS上使用Lucene的SourceCode

    本文将通过代码实例展示如何利用Lucene和Java进行基本的数据索引和搜索,以及如何在HDFS(Hadoop分布式文件系统)上创建和搜索索引。开发环境包括Java 1.6、Eclipse 3.4.2、Lucene 2.4.0和运行在Windows XP SP3上的...

    lucene全文检索工具包.zip

    - 开发者需要理解 Lucene 的基本概念,如 Document(文档)、Field(字段)、Analyzer(分析器)和 IndexWriter(索引写入器)等。 - 使用 IKAnalyzer 替换默认的分析器,以适应中文环境。 - Commons IO 类库可以...

    Mdrill项目在lucene的改进上的10点心得1

    首先,Mdrill改变了Lucene创建索引的方式,使得索引能够在HDFS(Hadoop分布式文件系统)上构建。原本Lucene由于依赖本地硬盘的随机写操作,无法直接在HDFS上创建索引。Mdrill通过分析源码,发现Lucene的随机写主要用...

    文件系统、Mongodb、Hadoop_存取方案分析

    文件系统是最基本的数据存储方式,直接将日志写入文件,通过 grep 或 Lucene 进行查询。这种方案的优势在于存储速度快,但随着文件数量的增加,查询变得困难。Lucene 可以构建索引以提升查询效率,但会占用大量存储...

    lucene-6.5.0

    使用Lucene 6.5.0进行开发时,需要理解其基本组件,如Analyzer(分析器)、Document(文档)、IndexWriter(索引写入者)和Searcher(搜索器)。开发者还需要掌握如何创建和维护索引,如何编写查询,并对结果进行...

    java大数据作业_7Flume、Kafka、Sqoop、Lucene

    1. **创建索引器**:首先需要创建一个 IndexWriter 对象,用于管理索引的写入操作。 2. **文档解析**:将要索引的文档转换为 Document 对象,每个文档包含多个 Field。 3. **添加文档**:通过 IndexWriter 添加文档...

    Nutch 0.8笔记NUTCHNUTCH

    - **Indexer**:遍历所有 segments,将 parseData 序列化为 ParseData 类,从中提取信息并使用插件进行索引,最后由 OutputFormat 类完成索引写入。 如果你只想使用 Nutch 的爬虫功能而不涉及索引,可以参照 ...

    qdwizard-3.1.2.zip

    通过将Lucene的索引与Blur的块缓存相结合,用户可以享受更快的搜索速度和更高效的内存管理。 项目的"lucene-hdfs-directory-master"目录可能包含了源代码、构建脚本、文档以及示例,供开发者研究和应用。这使得开发...

    数值预报产品分布式处理与存储系统设计.pdf

    - 系统测试结果表明,产品文件写入Hadoop文件系统的平均速度为MB/s,HBase最快入库速度可达8254条/秒,数据检索结果返回时效达到毫秒级。这说明了该系统可以满足业务应用中对数值预报产品存储和检索时效性的要求。 ...

    Nutch design and tutorial

    6. **索引创建**:索引器将解析后的数据转化为索引条目,并写入HDFS。 7. **搜索服务**:用户通过搜索接口提交查询,Nutch返回相关结果。 **三、Nutch与Big Data的关系** Nutch是大数据应用的一个典型例子,因为...

    Solr介绍文档

    1. **索引存储在HDFS上**:SolrCloud支持将索引文件存储在Hadoop的分布式文件系统(HDFS)中,这对于大规模数据集尤为有用,因为HDFS提供了良好的容错性和扩展性。 2. **通过MapReduce批量创建索引**:SolrCloud集成...

    katta-master.zip

    它通过将索引分片并分布到多个节点上,实现了高可用性和容错性,确保了系统的稳定运行。这使得Katta特别适合那些需要处理大量动态更新的数据并要求快速响应的场景。 Katta的工作机制主要包括以下几个关键部分: 1....

Global site tag (gtag.js) - Google Analytics