如何将Lucene索引写入Hadoop2.x?

news/2024/7/19 20:45:43 标签: hadoop, lucene, 全文检索, mapreduce, solr
[b][color=red][size=x-large]转载请务必注明,原创地址,谢谢配合!
[url]http://qindongliang1922.iteye.com/blog/2090121[/url]
[/size][/color][/b]
[b][color=olive][size=large]散仙,在上篇文章,已经写了如何将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包外,还需增加lucenesolr的部分jar包,截图如下,散仙本次使用的是Lucene4.8.1的版本:[/size][/color][/b]


[img]http://dl2.iteye.com/upload/attachment/0098/9446/8dc8d5e3-2460-306d-8d7f-f8798f988539.jpg[/img]
[b][color=green][size=large]具体的代码如下: [/size][/color][/b]
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("检索完毕...............");




}




}

[b][color=olive][size=large]使用IK的分词器,建立索引完毕后,在HDFS上的索引如下截图:[/size][/color][/b]

[img]http://dl2.iteye.com/upload/attachment/0098/9459/a84635f8-8e0e-3c7e-9cda-aa7f043a8fce.jpg[/img]
[b][color=olive][size=large]检索数据时,第一次检索往往比较慢,第一次之后因为有了Block Cache,所以第二次,检索的速度非常快,当然这也跟你机器的配置有关系:[/size][/color][/b]
本次检索内容:  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
检索完毕...............

[b][color=green][size=large]

为什么要使用Hadoop建索引? 使用Hadoop建索引可以利用MapReduce分布式计算能力从而大大提升建索引的速度,这一点优势很明显,但美中不足的是在Hadoop上做检索,性能却不怎么好,虽然有了块缓存,但是如果索引被按64M的块被切分到不同的节点上,那么检索的时候,就需要跨机器从各个块上扫描,拉取命中数据,这一点是很耗时的,目前,据散仙所知,还没有比较好的部署在Hadoop上的分布式检索方案,但毫无疑问的是建索引的能力,确实很给力,后面散仙会写如何使用MapReduce来并行构建Lucene索引,其实既然单机版的都可以完成,那么稍微改造下变成MapReduce作业,也很简单,大家可以先尝试尝试,有什么问题,欢迎与散仙沟通和交流! [/size][/color][/b]
[b][color=red][size=x-large]转载请务必注明,原创地址,谢谢配合!
[url]http://qindongliang1922.iteye.com/blog/2090121[/url]
[/size][/color][/b]

http://www.niftyadmin.cn/n/789768.html

相关文章

图解算法面试题之打印1到最大的N位数

本文参考书籍 《剑指offer》 作者何海涛 在面试中经常遇到大数相加问题&#xff0c;所以需要自己需要好好练习下这类型的题目。 01 题目 输入数字n&#xff0c;按顺序打印出从1到最大的n位十进制数。 示例:比如输入3&#xff0c;则打印1&#xff0c;2&#xff0c;3 一直到最…

Hadoop2.2.0集成Hbase0.96报的一个异常

[colorgreen][sizelarge]最近项目抓取的数据&#xff0c;存在Hbase里&#xff0c;所以需要从Hbase里读取数据&#xff0c;创建连接时&#xff0c;发现总是报如下的一个异常:[/size][/color][img]http://dl2.iteye.com/upload/attachment/0099/0648/7a8992ed-bd18-334f-a976-5ac…

Git的分支管理(二)

分支管理策略 git 在合并&#xff08;merge&#xff09;的时候有两种方式&#xff0c;一种是Fast forward模式&#xff0c;这种方式是快速模式&#xff0c;删除分支后&#xff0c;会丢掉分支信息。 另外一种是--no-ff方式&#xff08;禁止Fast forward模式&#xff09;&#xf…

算法题之在O(1)时间内删除链表结点

本文参考书籍 《剑指offer》 作者何海涛 01 题目 给定一个单向链表的头节点和一个指针节点&#xff0c;定义一个函数在o(1)时间内删除该节点。 链表节点和函数节点的定义如下&#xff1a; 注意给的待删除结点是链表中的一个指针节点 02 解题 因为给的结点是链表中的节点&am…

Java连接Hbase0.96异常

[b][colorolive][sizelarge]在Windows上直接使用JAVA API连接Hbase0.96报的一个异常&#xff0c;这个异常在Hbase0.94的版本里是没有的&#xff0c;为什么&#xff1f; 跟你所用的底层的Hadoop有关系&#xff0c;如果是底层hadoop是1.x的版本&#xff0c;那么没有这个问题&…

简单算法题之数值的正数次方

本文参考书籍 《剑指offer》 作者何海涛 01 题目 实现函数 double power(double base, int exponent),求base的exponent次方&#xff0c;不得使用库函数&#xff0c;同时不需要考虑大数问题。 02 解法一 最简单直接的解法, 直接for循环相乘 这种情况当输入的指数为<0就没…

记一次hadoop磁盘空间满的异常

[b][colorgreen][sizelarge]本事故&#xff0c;发生在测试的环境上&#xff0c;虽然不是线上的环境&#xff0c;但也是一次比较有价值的事故。起因&#xff1a;公司里有hadoop的集群&#xff0c;用来跑建索引&#xff0c;PHP使用人员&#xff0c;调用建索引的程序时&#xff0c…

单向链表中倒数第k个值

本文参考书籍 《剑指offer》 作者何海涛 01 题目 输入一个单向链表&#xff0c; 输出该链表中倒数第k个结点。 如一个链表中有6个结点&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff1b; 这个链表的倒数第三个节点是值为4的结点。 …