Lucene介绍及入门程序

1.数据分类
结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件
2.非结构化数据查询方法
(1)顺序扫描法:
所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢
(2)全文检索
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
这种先建立索引,在对索引进行搜索的过程就叫全文检索。
3.如何实现全文检索
可以使用Lucene实现全文检索。Lucene是apache下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
4.索引和搜索流程图
(1)索引过程,对要搜索的原始内容进行索引构建一个索引库,索引过程包括:
确定原始内容即要搜索的内容采集文档创建文档分析文档索引文档
(2)搜索过程,从索引库中搜索内容,搜索过程包括:用户通过搜索界面创建查询执行搜索,从索引库搜索渲染搜索结果
5.创建文档对象
在索引前需要将原始内容创建成文档,文档中包括一个一个的域(field),域中存储内容。
这里我们可以将磁盘上的一个文件当成一个document,Document中包括一些Field(file_name文件名称、file_path文件路径、file_size文件大小、file_content文件内容)

注意:每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以有相同的Field(域名和域值都相同)

每个文档都有一个唯一的编号,就是文档id.

6.分析文档
将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析,分析的过程是经过对原始文档提取单词、将字母转为小写、去除标点符号、去除停用词等过程生成最终的语汇单元,可以将语汇单元理解为一个一个的单词。
每个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的term。term中包含两部分一部分是文档的域名,另一部分是单词的内容
7.创建索引的步骤
第一步:创建一个java工程,并导入jar包。
第二步:创建一个indexwriter对象。
1)指定索引库的存放位置Directory对象
2)指定一个分析器,对文档内容进行分析。
第二步:创建document对象。
第三步:创建field对象,将field添加到document对象中。
第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
第五步:关闭IndexWriter对象。
8.Field域的属性
是否分析:是否对域的内容进行分词处理,前提是我们要对域的 内容进行查询
是否索引:将Field分析后的词进行索引,只有索引方可所搜到
是否存储:将Field值存在文档中,存储在文档中的Field才可以从Document中获取

9.创建索引的代码(需要导包)

public class FirstLucene {
@Test
	public void testIndex() throws Exception{
	Directory directory=FSDirectory.open(new File("D:\\资料\\index"));
	Analyzer analyzer=new StandardAnalyzer();//官方推荐分析器
	IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
	IndexWriter indexWriter=new IndexWriter(directory,config);
	//创建四个域对象(文件名,文件大小,文件内容,文件路径)
	//先把文件读到内存中使用IO流
	File f=new File("D:\\资料\\searchsource");
	File[] listFiles=f.listFiles();
	for(File file:listFiles){
		//创建文档对象
		Document document=new Document();
		//文件名字
		String file_name=file.getName();
		Field fileNameField=new TextField("fileName",file_name,Store.YES);
		
		//文件大小
		long file_size=FileUtils.sizeOf(file);
		Field fileSizeField=new LongField("fileSize",file_size,Store.YES);
		//文件路径
		String file_path=file.getPath();
		Field filePathField=new StoredField("filePath",file_path);
		//文件内容
		String file_content=FileUtils.readFileToString(file);
		Field fileContentField=new TextField("fileContent",file_content,Store.NO);
		//将域对象放到文档对象
		document.add(fileNameField);
		document.add(fileSizeField);
		document.add(filePathField);
		document.add(fileContentField);
		//使用indexwriter对象将document对象写入索引库,此过程进行索引创建,并将索引和document对象放入索引库
		indexWriter.addDocument(document);
	}
	//关闭IndexWriter对象
	indexWriter.close();
}
10.查询索引步骤
第一步:创建一个Directory对象,也就是索引库存放的位置。
第二步:创建一个indexReader对象,需要指定Directory对象。
第三步:创建一个indexsearcher对象,需要指定IndexReader对象
第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
第五步:执行查询。
第六步:返回查询结果。遍历查询结果并输出。
第七步:关闭IndexReader对象

11.查询索引代码实现

@Test
	public void testSearch()throws Exception{
		//创建一个Directory对象,也就是索引库位置
	Directory directory=FSDirectory.open(new File("D:\\资料\\index"));
	//创建一个IndexReader对象,需要指定directory对象
	IndexReader indexReader=DirectoryReader.open(directory);
	//创建一个IndexSearch对象,需要指定indexReader对象
	IndexSearcher indexSearch=new IndexSearcher(indexReader);
	//创建一个TermQuery对象,指定查询的域和查询的关键词
	Query query=new TermQuery(new Term("fileName","apache"));
	//执行查询
	TopDocs topDocs=indexSearch.search(query, 2);
	//返回查询结果,遍历查询结果并返回
	ScoreDoc[] scoreDocs=topDocs.scoreDocs;
	for(ScoreDoc scoreDoc:scoreDocs){
		int doc=scoreDoc.doc;
		Document document=indexSearch.doc(doc);
		//文件名称
		String fileName=document.get("fileName");
		System.out.println(fileName);
		//文件内容
		String fileContent=document.get("fileContent");
		System.out.println(fileContent);
		//文件大小
		String fileSize=document.get("fileSize");
		System.out.println(fileSize);
		//文件路径
		String filePath=document.get("filePath");
		System.out.println(filePath);

	}
	//关闭流
	indexReader.close();
}
13.分析器
从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语汇单元Tokens。
要看分析器的分析效果,只需要看Tokenstream中的内容就可以了。每个分析器都有一个方法tokenStream,返回一个tokenStream对象。

14.分析器的分词效果

@Test
public void testTokenStream() throws Exception {
	//创建一个标准分析器对象
	//Analyzer analyzer = new StandardAnalyzer();
	//Analyzer analyzer = new SmartChineseAnalyzer();
	Analyzer analyzer = new IKAnalyzer();
	//获得tokenStream对象
	//第一个参数:域名,可以随便给一个
	//第二个参数:要分析的文本内容
	TokenStream tokenStream = analyzer.tokenStream("test", "The Spring Framework provides a comprehensive programming 

and configuration model.");
	//添加一个引用,可以获得每个关键词
	CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
	//添加一个偏移量的引用,记录了关键词的开始位置以及结束位置
	OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
	//将指针调整到列表的头部
	tokenStream.reset();
	//遍历关键词列表,通过incrementToken方法判断列表是否结束
	while(tokenStream.incrementToken()) {
		//关键词的起始位置
		System.out.println("start->" + offsetAttribute.startOffset());
		//取关键词
		System.out.println(charTermAttribute);
		//结束位置
		System.out.println("end->" + offsetAttribute.endOffset());
	}
	tokenStream.close();
}

猜你喜欢

转载自blog.csdn.net/qq_36594703/article/details/80465029