lucene笔记视频配套笔记.docx
《lucene笔记视频配套笔记.docx》由会员分享,可在线阅读,更多相关《lucene笔记视频配套笔记.docx(30页珍藏版)》请在冰豆网上搜索。
![lucene笔记视频配套笔记.docx](https://file1.bdocx.com/fileroot1/2023-6/4/5626093d-c94d-4d3c-8c45-41c665fce1fc/5626093d-c94d-4d3c-8c45-41c665fce1fc1.gif)
lucene笔记视频配套笔记
lucene笔记-视频配套笔记
传智播客Java学院传智.入云龙
全文检索技术之Lucene
1课程计划
1、什么全文检索
数据类型:
结构化数据和非结构化数据
非结构化数据查询方法
全文检索的概念
2、什么是Lucene
3、Lucene实现全文检索的流程(重点)4、Lucene的入门程序(重点)
5、分析器Analyzer(重点)
7、索引库的维护(重点)
i.索引库的增加索引
ii.删除索引
iii.修改索引
8、索引库的查询(重点)
i.使用Query的子类查询
ii.使用QueryParser查询
8、相关的排序
2什么全文检索
结构化数据:
数据的长度类型是固定的。
数据库中的数据
非结构化数据:
长度不固定格式不固定。
Word文档、excel、pdf、txt。
2.1结构化数据的查询
使用sql语句查询就可以
2.2非结构化数据的查询
需求:
在文件中找出包含java字符的文档。
传智播客Java学院传智.入云龙
2.2.1实现方法
1、目测
2、顺序扫描。
如果文件量大的话比如说20G,顺序扫描会变的很慢。
3、非结构化的数据变结构化
先从文件中找出文件所有的词汇,形成一个列表。
查询的时候直接查询列表,找到关键词后根据这词找到相应的文档。
一次创建多次使用。
2.3全文检索的概念
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-textSearch)。
2.4全文检索应用领域
1、搜索引擎,XX、谷歌
2、站内搜索
a)微博搜索
b)论坛搜索
3、电商搜索,搜索的是商品信息。
3什么是Lucene
3.1Lucene的概念
Lucene是apache下的一个开放源代码的全文检索引擎工具包。
提供了完整的查询引擎和索引引擎,部分文本分析引擎。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
3.2Lucene和搜索引擎的区别
Lucene是一个工具包:
需要进行编程才能实现全文检索的功能呢搜索引擎:
一套独立运行的系统,提供了全文检索功能。
传智播客Java学院传智.入云龙
3.3Lucene的下载
下载地址:
本课程Lucene的版本:
4.10.3
包名功能org.apache.lucene.analysis语言分析器,主要用于的切词
Lucene提供的分析器实现类在:
lucene-analyzers-common-4.10.3.jar
索引存储时的文档结构管理,类似于关系型org.apache.lucene.document
数据库的表结构
传智播客Java学院传智.入云龙
org.apache.lucene.index索引管理,包括索引建立、删除等
查询分析器,实现查询关键词间的运算,如org.apache.lucene.queryParser
与、或、非等,生成查询表达式,org.apache.lucene.search检索管理,根据查询条件,检索得到结果org.apache.lucene.store数据存储管理,包括一些I/O操作org.apache.lucene.util公用类
4Lucene实现全文检索的流程
4.1案例:
我们以一个案例来研究全文检索系统架构:
实现一个文件的搜索功能,通过关键字搜索文件,凡是文件名或文件内容包括关键字的文件都需要找出来。
4.2实现的流程
传智播客Java学院传智.入云龙
4.2.1创建索引
4.2.1.1获得文档
使用文件流读取文档的内容就可以获得文档。
搜索引擎:
使用网络爬虫来获得。
Nutch:
apache的爬虫程序
Heritrix:
爬虫程序
Jsoup:
html分析的工具包
电商网站:
数据库中的表,例如商品表。
数据库中的每一条记录都是一个原始文档。
Solr:
直接从数据库中的表导入到索引库中。
4.2.1.2创建文档对象
每个文件对应一个文档对象Document对象。
Field域。
每个文档对象Document对象中可以有多个域,每个域可以存储文件的相关属性。
传智播客Java学院传智.入云龙
例如:
文件名
文档内容
文件路径
文件的大小
Document
文件名文件内容
文件的路径文件的大小
其他属性。
。
。
不同的文档中域可以不同,同一个文档中可以有相同的域。
4.2.1.3分析文档
主要是分析文档的内容,文件的标题。
目的:
分析出文档中包含的关键词。
1、先根据空格进行字符串的拆分得到词汇列表
2、词汇列表中无意义的词叫做“停用词”。
去除停用词。
例如:
a、the、an
3、去掉标点符号。
4、统一大小写,转换成小写。
最终得到语汇单元流。
注意:
并不是所有域都需要分析,只需要分析指定的域就可以。
4.2.1.4创建索引
将索引和document对象写入索引库。
持久化的过程。
创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构。
传智播客Java学院传智.入云龙
持久就是把索引和document写索引库,索引库包含量部分内容。
索引、和
document
索引库
索引Document1Lucene
SolrDocument2Hadoop
java
Document3
4.2.2查询索引
4.2.2.1用户查询接口
用户输入查询条件的地方
本例中可以硬编码到代码中。
4.2.2.2创建查询
可以使用Query创建查询条件。
需要指定要查询的域和要查询的内容:
传智播客Java学院传智.入云龙
查询语法:
域名:
关键词
例如:
title:
java
查询多个关键字:
Title:
javaANDtitle:
lucene
4.2.2.3执行查询
到索引库中找到指定域,查询指定关键字。
返回一个查询结果。
返回文档列表。
4.2.2.4渲染结果
对关键词进行高亮显示、分页、结果的排序。
传智播客Java学院传智.入云龙
5Lucene的入门程序
5.1创建索引
索引存放的位置可以是内存可以是文件系统。
根据实际的使用场景来决定。
第一步:
指定索引库存放的位置。
Directory对象。
第二步:
需要使用到IndexWriter对象来创建索引。
第三步:
指定创建索引时使用的分析器Analyzer对象。
第四步:
获得原始文档。
使用文件流读取文件内容。
第五步:
创建文档对象。
Document对象,创建文档对象的多个域,文件名、文件内容、文
件的路径、文件的大小。
第六步:
将文档对象使用indexwriter对象写入索引库。
开发环境:
jdk1.7
Eclipse3.7indigo
编码:
1、创建一个java工程
、导入jar包。
2
lucene-core-4.10.3.jar
lucene-analyzers-common-4.10.3.jar
commons-io-2.4.jar
传智播客Java学院传智.入云龙
5.1.1Field域
域有三个属性
是否分析、是否索引、是否存储。
1、是否分析(tokenized)
是:
将Field值分析出语汇单元即作分词处理,将词进行索引
比如:
商品名称、商品简介等,这些内容用户要输入关键字搜索,由于搜索的内容格式大、内容多需要分析后将语汇单元索引。
否:
不作分词处理
比如:
商品id、订单号、身份证号等
2、是否索引(indexed)
是:
将Field分析后的词或整个Field值进行索引,只有索引方可搜索到。
比如:
商品名称、商品简介分析后进行索引,订单号、身份证号不用分析但也要索引,这些将来都要作为查询条件。
否:
不索引无法搜索到
比如:
商品id、文件路径、图片路径等,不用作为查询条件的不用索引。
3、是否存储(stored)
是:
将Field值存储在文档中,存储在文档中的Field才可以从Document中获取比如:
商品名称、订单号,凡是将来要从Document中获取的Field都要存储。
否:
不存储Field值,不存储的Field无法通过Document获取
比如:
商品简介,内容较大不用存储。
如果要向用户展示商品简介可以从系统的关系数据库中获取商品简介。
5.1.2常用的域
IndexedStored数据类AnalyzedField类是否索是否存说明型是否分析引储
这个Field用来构建一个字符串
Field,但是不会进行分析,会将
整个串存储在索引中,比如(订单StringField(FieldName,Y或N字符串NY号,姓名等)FieldValue,Store.YES))
是否存储在文档中用
Store.YES或Store.NO决定
这个Field用来构建一个Long数LongField(FieldName,Y或NLong型YY字型Field,进行分析和索引,比FieldValue,Store.YES)
传智播客Java学院传智.入云龙
如(价格)
是否存储在文档中用
Store.YES或Store.NO决定
这个Field用来构建不同类型重载方StoredField(FieldName,Field法,支持NNY不分析,不索引,但要Field存储在文档FieldValue)多种类型中TextField(FieldName,
FieldValue,Store.NO)如果是一个Reader,lucene猜测字符串或Y或N内容比较多,会采用Unstored的或YYTextField(FieldName,策略.流reader)
5.1.3程序开发
@Test
publicvoidcreateIndex()throwsException{
//指定索引库存放的位置
StringindexPath="D:
\\temp\\yun14\\index";
//将索引库存放到内存中
//Directorydirectory=newRAMDirectory();
//存放到文件系统中
Directorydirectory=FSDirectory.open(newFile(indexPath));
//创建分析器对象
Analyzeranalyzer=newStandardAnalyzer();
//创键IndexWriterconfig对象
//第一个参数:
Lucene使用的版本
//第二个参数:
分析器对象
IndexWriterConfigconfig=newIndexWriterConfig(Version.LATEST,analyzer);
//创建Indexwriter对象
IndexWriterindexWriter=newIndexWriter(directory,config);
//遍历原始文档文件夹下的所有文件将文件内容读取到程序中
Filepath=newFile("D:
\\传智播客\\01.课程\\04.lucene\\01.参考资料\\searchsource");
for(Filefile:
path.listFiles()){
//创建Document对象
Documentdocument=newDocument();
//获得文件名
StringfileName=file.getName();
//获得文件内容
StringfileContent=FileUtils.readFileToString(file);
//文件路径
传智播客Java学院传智.入云龙
StringfilePath=file.getPath();
//文件的大小
longfileSize=FileUtils.sizeOf(file);
//向文档中添加域
//第一个参数:
域名
//第二个参数:
域的值
//第三个参数:
是否存储Store.YES存储Store.NO不存储
FieldfileNameField=newTextField("filename",fileName,Store.YES);
FieldfileContentField=newTextField("content",fileContent,Store.YES);
FieldfilePathField=newStoredField("path",filePath);
FieldfileSizeField=newLongField("size",fileSize,Store.YES);
//添加到文档对象中
document.add(fileNameField);
document.add(fileContentField);
document.add(filePathField);
document.add(fileSizeField);
//将document写入索引库
indexWriter.addDocument(document);
}
indexWriter.close();
}
5.1.4查看结果
传智播客Java学院传智.入云龙
5.2查询索引
5.2.1使用luke查看索引库
同一个字符串出现在不同的域中就是不同的关键词。
关键词在lucene中叫做term
5.2.2查询索引的实现
第一步:
创建一个indexreader对象。
需要指定一个directory,索引库的路径。
第二步:
创建一个indexsearcher对象,需要一个indexreader对象。
第三步:
创建一个查询对象Query。
指定查询的域查询的关键词。
第四步:
执行查询。
第五步:
返回结果并遍历。
5.2.3代码实现
@Test
传智播客Java学院传智.入云龙
publicvoidsearchIndex()throwsException{
//索引库存放的路径
Directorydirectory=FSDirectory.open(newFile("D:
\\temp\\yun14\\index"));
//创建indexreader对象
IndexReaderindexReader=DirectoryReader.open(directory);
//创建indexsearcher
IndexSearcherindexSearcher=newIndexSearcher(indexReader);
//创建查询
Queryquery=newTermQuery(newTerm("content","apache"));
//执行查询
//第一个参数是查询对象
//第二个参数:
返回结果的最大值。
TopDocstopDocs=indexSearcher.search(query,10);
//查询结果的总数量
System.out.println("查询结果的总数量:
"+topDocs.totalHits);
//遍历查询结果
for(ScoreDocscoreDoc:
topDocs.scoreDocs){
//scoreDoc.doc文档的唯一id可以根据这个id取document对象
//使用indexsearcher对象的doc方法从索引库中取document对象,需要document对象的id
Documentdocument=indexSearcher.doc(scoreDoc.doc);
//取文档的属性内容
System.out.println(document.get("filename"));//System.out.println(document.get("content"));
System.out.println(document.get("path"));
System.out.println(document.get("size"));
}
indexReader.close();
}
5.2.4总结
1、返回结果的最大值。
TopDocstopDocs=indexSearcher.search(query,10);2、查询结果的总数量
System.out.println("查询结果的总数量:
"+topDocs.totalHits)
3、文档document对象的id
scoreDoc.doc
传智播客Java学院传智.入云龙
6分析器的研究
6.1分析器的分析过程
从文本流中读取要分析的内容
StringReader
根据空格将文本内容进行拆分,得到一个
词汇列表Tokennizer
在词汇列表基础上过滤
去除标点符号TokenFilter
去除停用词TokenFilter
大小写统一过程,全部转换成小写TokenFilter
最终得到语汇单元流
Tokenstream对象中
每个分析器都有个tokenstream方法,可以返回一个tokenStream对象。
查看分词效果,可以从tokenstream中查看。
6.2Tokenstream第一步:
从Analyzer对象的tokenstream方法获得tokenstream对象。
第二步:
遍历词汇列表
传智播客Java学院传智.入云龙
1)CharTermAttribute,就得到当前的一个词
2)OffSetAttribute,得到该次的偏移量。
6.3测试代码
@Test
//测试分析器的分词效果
publicvoidtestTokenStream()throwsException{
//创建分析器对象
Analyzeranalyzer=newStandardAnalyzer();
//获得tokenstream
TokenStreamtokenStream=analyzer.tokenStream("test","TheSpringFrameworkprovidesa
comprehensiveprogrammingandconfigurationmodel.");
//调整指针至最顶端
tokenStream.reset();
//获得当前词的一个引用
CharTermAttributetermAttribute=tokenStream.addAttribute(CharTermAttribute.class);
//获得当前词的偏移量引用
OffsetAttributeoffsetAttribute=tokenStream.addAttribute(OffsetAttribute.class);
//遍历tokenstream
while(tokenStream.incrementToken()){
//取当前词的开始位置
System.out.println("start->"+offsetAttribute.startOffset());
//取当前词内容
System.out.println(termAttribute);
//当前词的结束位置
System.out.println("end->"+offsetAttribute.endOffset());
}
tokenStream.close();
}
6.4Lucene自带分析器的分词效果StandardAnalyzer:
英文是根据空格分词,中文是一个字一个词。
CJKAnalyzer:
处理中文是两个字一个词。
智能中文分词的分词:
SmartChineseAnalyzer
传智播客Java学院传智.入云龙
可以处理基本的中文内容,但是停用词不能去掉,而且中文中夹杂的英文单词分词后不完整。
6.5第三方中文分析器
paoding:
庖丁解牛最新版在中最多支持Lucene3.0,且最新提交的代码在2008-06-03,在svn中最新也是2010年提交,已经过时,不予考虑。
mmseg4j:
最新版已从移
至,支持Lucene4.10,且在github中最新提交代码是2014年6月,从09年,14年一共有:
18个版本,也就是一年几乎有3个大小版本,有较大的活跃度,用了mmseg算法。
IK-analyzer:
最新版在上,支持Lucene4.10从2006年12月推出1.0版开始,IKAnalyzer已经推出了4个大版本。
最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。
从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。
在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。
但是也就是2012年12月后没有在更新。
ansj_seg:
最新版本在仅有1.1版本,从2012年到2014年更新了大小6次,但是作者本人在2014年10月10日说明:
“可能我以后没有精力来维护ansj_seg了”,现在由”nlp_china”管理。
2014年11月有更新。
并未说明是否支持Lucene,是一个由CRF(条件随机场)算法所做的分词算法。
imdict-chinese-analyzer:
最新版
在,最新更新也在2009年5月,下载源码,不支持Lucene4.10。
是利用HMM(隐马尔科夫链)算法。
Jcseg:
最新版本在4.10,作者有较高的活跃度。
利用mmseg算法。
传智播客Java学院传智.入云龙
6.6IK-Analyzer
6.6.1导入工程中
第一步:
IKAnalyzer2012FF_u1.jar添加到工程中
第二步:
将配置文件和扩展词典和停用词词典复制到classpath下。
注意:
扩展词典和停用词典必须保证编码格式是utf-8。
不能使用notpad编辑文件。
传智播客Java学院传智.入云龙
6.7分析器的应用场景
创建索引时使用
查询索引时使用
7索引库的维护
7.1向索引库添加文档
//向索引库添加文档
@Test
publicvoidaddDocument()throwsException{