大家好,欢迎来到IT知识分享网。
Lucene:全文检索技术
概念:先创建索引,然后再对索引搜索的过程就是全文检索技术;
索引一次创建多次使用,表现为每次的查询速度很快。
索引:一个为了提高查询速度,创建某种数据结构的集合。
- 数据的分类:
- 结构化数据:格式、长度、数据类型固定
- 例如数据库的数据,
- 非结构化数据:格式、长度、数据类型不固定
- word文档、pdf文档等等
- 结构化数据:格式、长度、数据类型固定
- 数据的查询
- 结构化数据的查询:sql语句
- 简单、查询速度快
- 非结构化数据:查询某个关键字?
- 条件复杂,查询难度大
- 顺序扫描法
- 字符串匹配(顺序扫描)
- 使非结构化的数据变为结构化的数据便于查询
- 条件复杂,查询难度大
- 结构化数据的查询:sql语句
全文检索的应用场景
- 搜索引擎
- :百度、谷歌、搜索等等
- 站内搜索
- 论坛搜索,微博搜索,文章搜索
- 电商搜索
- jd,tb搜索
什么是Lucene:
Lucene是一个基于java开发全文检索工具包,提供了查询引擎和索引引擎
如何实现全文检索:
可以使用Lucene实现全文检索。Lucene是apache下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
Lucene实现全文检索的流程:
配置开发环境
Lucene官网下载:
luck
IKAnalyzer
链接:https://pan.baidu.com/s/1cCZktGtdAPV-rv9IRLm3Og
提取码:kisq
最低要jdk1.8
java工程和jar包
lucene-core
lucene-analyzers-common
commons-io
junit
入门案例:
步骤:
创建索引库
- 创建一个Directory对象,指定索引库保存的位置 Directory directory = FS 一般保存在磁盘上
- 基于Directory对象,创建一个IndexWriter对象 IndexWriter indexwrite = new IndexWriter(directory ,new IndexWirterConfig());
- 读取磁盘上的文件,对应每一个文件一个文档对象
- 向文档对象中添加域
- 把文档对象写入索引库
- 关闭IndexWriter对象
Directory directory = FSDirectory.open(new File("路径").toPath());//设定索引库存放位置 IndexWirter indexwriter = new IndexWirter(directory,new IndexWirterConfig());//索引写入对象,使用此对象来讲文档写入索引库 File dir = new File("路径"); //获取需要创建索引的文件的路径 File[] files = dir.listFiles();//获取此路径下所有的文件 for(File file:files){ //得到文件信息,建立并写入到域对象中去 //文件信息 此处获取的是文件的名字、路径、大小、内容信息 String fileName = file.getName(); String fileSize = FileUtils.sizeof(file); String fileContent = FileUtils.readFileToString(file); String filePath = file.getPath(); //创建域对象 Field fieldName = new TextField("name",fileName,Field.Store.YES); Field fieldPath = new TextField("path",filePath,Field.Store.YES); Field fieldSize = new TextField("size",fileSize,Field.Store.YES); Field fieldContent = new TextField("content",fileContent,Field.Store.YES); Document document = new Document();//创建文件对象 一个文件对应一个文档对象 //向文档对象里面添加域对象 document.add(fieldPath); document.add(fieldSize); document.add(fieldContent); document.add(fieldName); //使用索引写入对象将文档写入索引库 indexWirter.addDocument(document); //释放资源 indexWirter.close(); }
使用Luke工具查询索引库:
上面使用的是Lucene是7.4.0版本的,若使用Luke工具的版本是和此对应的,就可以打开Lucene创建的索引库,需要注意的是此版本的Luke工具是JKD9编译的。
总的来说就是根据不同版本的Lucene而选择对应的Luke工具的版本,否则将打不开索引库。
当然创建索引库就是为了查询:下面给出查询步骤:
查询索引库
- 创建一个Directory对象,指定索引库的位置
- 创建一个IndexReader对象
- 创建一个IndexSearcher对象构造方法为IndexReader对象
- 创建一个Query对象,tremQuery创建,并且设置需要查询的域对象和查询的关键字
- 执行查询,得到一个TopDocs对象
- 取查询结果的总记录条数
- 取文档列表
Directory directory = FSDirectory.open(new File("路径").toPath());//获取到索引库的位置 IndexReader indexreader = DirectorReader.open(dirctor);//基于directory创建一个索引读取对象 IndexSeacher indexreacher = new IndexSeacher(indexreader);//基于索引读取对象获取索引查询对象 Query query = new TremQuery(new Term("title","Lucene"));//创建查询对象query,Query是一个抽象类,需要他的视线类TremQuery创建 TopDocs topdocs = indexSearcher.search(query,10);//使用indexSearcher对象进行查询,并且设置每次查询的数量 System.out.println("总记录数"+topdcs.totalHits(););//获取击中的所有数量总和 ScopeDoc[] ScopeDoc = topDocs.scoreDocs;//使用此方法scoreDocs可以获取到文档列表是一个数组,然后对数组进行查询 for(ScopeDoc doc:ScopeDoc){ int DocID = doc.doc; Doucment document = indexSearcher.doc(docId);//获取文档ID System.out.println(document.get("name")); System.out.println(document.get("path")); System.out.println(document.get("content")); System.out.println(document.get("size")); } //释放资源 indexReader.close();
分析器的分析过程
标准分析器
默认使用标准分析器StandarAnalyzer 使用标准分析器,会将汉语关键字拆分为一个汉字一个汉字的形式
查看分析器的分析效果
使用Analyzer对象的tokenStream方法返回一个TokenStream对象,此对象中包含了最终的分词结果
步骤:
- 创建一个Analyzer对象,StandarAnalyzer对象
- 使用分析器对象的tokenStream方法获取TokenStream对象
- 向TokenStream对象设置一个引用,相当于一个指针
- 调用TokenStream对象的rest方法,如果不调用就抛异常
- 循环TokenStream对象
- 关闭TokenStream对象
Analyzer analyzer = new StandarAnalyzer();//使用一个标准分析器 TokenStream tokenstream = analyzer.tokenStream("xxxxx");// CharTermAttribute charTermAttribute = tokenstream.addAttribute(CharTermAttribute.Class); tokenstream.reset(); while(tokenstream.incrementToken()){ sout(charTermAttribute.ToString()); } tokenStream.close();
中文分析器:
- jar包
- 配置文件和扩展词典
- 扩展词典禁止使用Windows的记事本打开,一定要保证文件的编码格式为utf-8
- 扩展词典:添加一点新词
- 停用词词典:无意义的词和敏感词汇
代码中使用:换一个IndexConfig的构造方法就行
new IndexWriterConfig(new IKAnalyzer())//使用IkAnalyzer中文分析器
索引库维护
每一个域的属性:是否索引、是否分析、是否存储
- 添加文档 :根据不同的数据类型来使用不同的域的类型去操作
//创建IndexWirter对象存入磁盘中并且设置中文解析器 IndexWrirter indexwirter = new IndexWriter(new FSDocument.open(new File("路径")),new IndexWirterCongif(new IKAnalyzer())); //创建文档对象 Document document = new Document(); //文档中加入域对象 document.add(new Field("name","新的",Field.STORE.YES)); indexwriter.addDocument(document); indexwriter.close();
删除文档
- 全部删除
IndexWriter.deleteAll(); IndexWriter.close();
查询删除 针对性的删除
IndexWriter.deleteDecutments(new Term("name","apache")); IndexWriter.close();
修改文档:原理是先删除后添加
Document document = new Document(); document.add(new Field("name","新的",Field.STORE.YES)); //更新操作 indexwriter.updateDocument(new Field("name","原来的",document)); indexwriter.close();
索引库查询
Directory directory = FSDirectory.open(new File("路径").toPath()); IndexReader indexReader = new Indexreader(directory); IndexSearcher indexSearcher = new IndexReader(indexreader); Query query = new TermQuery(new Term("content","Lucene"));//使用TermQuery查询 TopDocs topDocs = indexSearcher.search(query,10); ScoreDoc[] scoreDocs = topDocs.scorcDocs; int sum = topDocs.titalHits; for(ScoreDoc scoreDoc:scoreDocs){ int DocId = scoreDoc.doc; Document document = new Document();//获取文档对象的ID 根据域名称拿到值 document = insearch.doc(DocId); document.get("content");//获取 ..... } indexSearcher.close(); indexReader.close();
RangeQuery:范围查询
Query query = LongPoint.newRangeQuery("size", 0l, 100l);//其他都一样
QueryPaser:根据查询内容先分词后查询
- jar包
Directory directory = FSDirectory.open(new File("path").toPath()); IndexReader indexReader = new IndexReader(directory); IndexSearcher indexSearcher = new IndexReacher(indexReader); QueryParser queryParser = new QueryParser(Version.LUCENE_8_7_0,"name",new IkAnalyzer());//Lucene的版本 查询的域 解析器类型 TopDocs topDocs = indexSearcher.search(queryParser,10); ScoreDoc[] scoreDocs = topDocs.scoreDoc; int sum = topDocs.totalHits; for(ScoreDoc scoreDoc:scoreDocs){ Doucument document = indexSearcher.doc(scoreDoc.doc); document.get("content");//获取 ..... } indexSearcher.close(); indexReader.close();
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134503.html