转载请务必注明,原创地址,谢谢配合!
http://qindongliang1922.iteye.com/blog/2090121
散仙,在上篇文章,已经写了如何将Lucene索引写入Hadoop1.x的HDFS系统,本篇散仙将介绍上将索引写在Hadoop2.x的HDFS上,写入2.x的Hadoop相对1.x的Hadoop来说要简单的说了,因为默认solr(4.4之后的版本)里面自带的HDFSDirectory就是支持2.x的而不支持1.x的,使用2.x的Hadoop平台,可以直接把solr的corejar包拷贝到工程里面,即可使用建索引,散仙,是在eclipse上使用eclipse插件来运行hadoop程序,具体要用到的jar包,除了需要用到hadoop2.2的所有jar包外,还需增加lucene和solr的部分jar包,截图如下,散仙本次使用的是Lucene4.8.1的版本:
具体的代码如下:
package com.mapreduceindex;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
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;
import org.apache.solr.store.hdfs.HdfsDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;
/**
*
* 将索引存储在Hadoop2.2的HDFS上
*
* @author qindongliang
* QQ技术交流群:
* 1号群: 324714439 如果满员了请加2号群
* 2号群: 206247899
*
*
* **/
public class MyIndex {
public static void createFile()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(conf);
Path p =new Path("hdfs://192.168.46.32:9000/root/abc.txt");
fs.createNewFile(p);
//fs.create(p);
fs.close();//释放资源
System.out.println("创建文件成功.....");
}
public static void main(String[] args)throws Exception {
//createFile();
//long a=System.currentTimeMillis();
// add();
// long b=System.currentTimeMillis();
// System.out.println("耗时: "+(b-a)+"毫秒");
query("8");
//delete("3");//删除指定ID的数据
}
/***
* 得到HDFS的writer
*
* **/
public static IndexWriter getIndexWriter() throws Exception{
Analyzer analyzer=new IKAnalyzer(true);
IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_48, analyzer);
Configuration conf=new Configuration();
conf.set("fs.defaultFS","hdfs://192.168.46.32:9000/");
//conf.set("mapreduce.framework.name", "yarn");
//conf.set("yarn.resourcemanager.address", "192.168.46.32:8032");
//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.46.32:9000/qin/myindex");
//HdfsDirectory directory=new HdfsDirectory(path, conf);
HdfsDirectory directory=new HdfsDirectory(path, conf);
IndexWriter writer=new IndexWriter(directory, config);
return writer;
}
public static void add()throws Exception{
IndexWriter writer=getIndexWriter();
// Document doc=new Document();
// 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();
// doc2.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("索引3条数据添加成功!");
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();
conf.set("fs.defaultFS","hdfs://192.168.46.32:9000/");
//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.46.32:9000/qin/myindex");
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_48, "content", new IKAnalyzer(true));
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("检索完毕...............");
}
}
使用IK的分词器,建立索引完毕后,在HDFS上的索引如下截图:
检索数据时,第一次检索往往比较慢,第一次之后因为有了Block Cache,所以第二次,检索的速度非常快,当然这也跟你机器的配置有关系:
本次检索内容: 8
WARN - NativeCodeLoader.<clinit>(62) | Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
总数据量: 9994
本次命中结果: 1 条
评分: 4.7582965 id : 8 name: lucene是一款非常优秀的全文检索框架8 字段内容: 今天发工资了吗8
第一次耗时:261 毫秒
============================================
本次命中结果: 1 条
评分: 4.7582965 id : 8 name: lucene是一款非常优秀的全文检索框架8 字段内容: 今天发工资了吗8
第二次耗时:6 毫秒
INFO - HdfsDirectory.close(97) | Closing hdfs directory hdfs://192.168.46.32:9000/qin/myindex
检索完毕...............
为什么要使用Hadoop建索引? 使用Hadoop建索引可以利用MapReduce分布式计算能力从而大大提升建索引的速度,这一点优势很明显,但美中不足的是在Hadoop上做检索,性能却不怎么好,虽然有了块缓存,但是如果索引被按64M的块被切分到不同的节点上,那么检索的时候,就需要跨机器从各个块上扫描,拉取命中数据,这一点是很耗时的,目前,据散仙所知,还没有比较好的部署在Hadoop上的分布式检索方案,但毫无疑问的是建索引的能力,确实很给力,后面散仙会写如何使用MapReduce来并行构建Lucene索引,其实既然单机版的都可以完成,那么稍微改造下变成MapReduce作业,也很简单,大家可以先尝试尝试,有什么问题,欢迎与散仙沟通和交流!
转载请务必注明,原创地址,谢谢配合!
http://qindongliang1922.iteye.com/blog/2090121
- 大小: 188.7 KB
- 大小: 150.3 KB
分享到:
相关推荐
标题 "如何将Lucene索引写入Hadoop" 指涉的是在大数据处理场景下,如何利用Apache Lucene的全文检索功能与Apache Hadoop的分布式计算能力相结合,实现高效的数据检索。Apache Lucene是一个高性能、全文本搜索库,而...
本文将深入探讨标题为“hadoop.contrib/lucene源码”的主题,即如何在Hadoop MapReduce框架下利用Lucene来构建倒排索引。 Hadoop是Apache软件基金会开发的一个分布式计算框架,它主要由HDFS(Hadoop Distributed ...
4. **将Luncen集成到Hadoop**:集成过程包括创建Lucene索引,然后使用Hadoop的API(如HDFS API)将索引写入HDFS。在Java代码中,你需要创建一个Hadoop Configuration对象,设置HDFS的相关参数,然后使用FileSystem...
- 开发者需要理解 Lucene 的基本概念,如 Document(文档)、Field(字段)、Analyzer(分析器)和 IndexWriter(索引写入器)等。 - 使用 IKAnalyzer 替换默认的分析器,以适应中文环境。 - Commons IO 类库可以...
2. **HDFS API**:项目会使用Hadoop的文件系统接口来读取、写入和操作HDFS中的数据。 3. **Lucene索引分布**:每个HDFS节点上的数据都会被本地化的Lucene实例进行索引,确保索引与数据的物理位置相对应,减少网络...
2. Elasticsearch:Elasticsearch是一个基于Lucene的搜索服务器,提供了实时、分布式的搜索和分析能力,非常适合大规模数据的实时分析。 3. Avro:Avro是Hadoop项目的一部分,提供了一种紧凑、快速、可跨语言的数据...
3. 索引写入(IndexWriter):负责构建倒排索引,将文档字段中的关键词与文档ID关联起来。倒排索引是Lucene搜索速度的关键,它允许快速定位到包含特定关键词的文档。 三、搜索过程 1. 查询解析器(QueryParser):...
本文将通过代码实例展示如何利用Lucene和Java进行基本的数据索引和搜索,以及如何在HDFS(Hadoop分布式文件系统)上创建和搜索索引。开发环境包括Java 1.6、Eclipse 3.4.2、Lucene 2.4.0和运行在Windows XP SP3上的...
文件系统是最基本的数据存储方式,直接将日志写入文件,通过 grep 或 Lucene 进行查询。这种方案的优势在于存储速度快,但随着文件数量的增加,查询变得困难。Lucene 可以构建索引以提升查询效率,但会占用大量存储...
使用Lucene 6.5.0进行开发时,需要理解其基本组件,如Analyzer(分析器)、Document(文档)、IndexWriter(索引写入者)和Searcher(搜索器)。开发者还需要掌握如何创建和维护索引,如何编写查询,并对结果进行...
1. **创建索引器**:首先需要创建一个 IndexWriter 对象,用于管理索引的写入操作。 2. **文档解析**:将要索引的文档转换为 Document 对象,每个文档包含多个 Field。 3. **添加文档**:通过 IndexWriter 添加文档...
首先,Mdrill改变了Lucene创建索引的方式,使得索引能够在HDFS(Hadoop分布式文件系统)上构建。原本Lucene由于依赖本地硬盘的随机写操作,无法直接在HDFS上创建索引。Mdrill通过分析源码,发现Lucene的随机写主要用...
- **Indexer**:遍历所有 segments,将 parseData 序列化为 ParseData 类,从中提取信息并使用插件进行索引,最后由 OutputFormat 类完成索引写入。 如果你只想使用 Nutch 的爬虫功能而不涉及索引,可以参照 ...
通过将Lucene的索引与Blur的块缓存相结合,用户可以享受更快的搜索速度和更高效的内存管理。 项目的"lucene-hdfs-directory-master"目录可能包含了源代码、构建脚本、文档以及示例,供开发者研究和应用。这使得开发...
3. **索引与搜索**:索引过程将文档转换为倒排索引,加速查询速度。Elasticsearch提供了丰富的查询语法,包括全文搜索、范围查询、布尔查询等。 二、数据模型 1. **类型(Type)**:在早期版本中,Elasticsearch...
1. **数据导入**:Spark可以通过`es.read.format("org.elasticsearch.spark.sql")`将DataFrame写入Elasticsearch,这使得从Hadoop、Hive或其他数据源处理后的结果可以直接导入到ES索引中。 2. **数据导出**:反之,...
2. **通过MapReduce批量创建索引**:SolrCloud集成Hadoop MapReduce框架,允许用户利用该框架进行大规模索引构建工作,极大地提高了创建索引的速度和效率。 3. **强大的RESTful API**:SolrCloud提供了一套全面的...