全文检索功能(Lucene)

Lucene:全文检索技术

概念:先创建索引,然后再对索引搜索的过程就是全文检索技术;

索引一次创建多次使用,表现为每次的查询速度很快。

索引:一个为了提高查询速度,创建某种数据结构的集合。

  • 数据的分类:
    • 结构化数据:格式、长度、数据类型固定
      • 例如数据库的数据,
    • 非结构化数据:格式、长度、数据类型不固定
      • word文档、pdf文档等等
  • 数据的查询
    • 结构化数据的查询:sql语句
      • 简单、查询速度快
    • 非结构化数据:查询某个关键字?
      • 条件复杂,查询难度大
        • 顺序扫描法
        • 字符串匹配(顺序扫描)
        • 使非结构化的数据变为结构化的数据便于查询
全文检索的应用场景
  • 搜索引擎
    • :百度、谷歌、搜索等等
  • 站内搜索
    • 论坛搜索,微博搜索,文章搜索
  • 电商搜索
    • jd,tb搜索
什么是Lucene:

Lucene是一个基于java开发全文检索工具包,提供了查询引擎和索引引擎

如何实现全文检索:

可以使用Lucene实现全文检索。Lucene是apache下的一个开放源代码的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。

Lucene实现全文检索的流程:

配置开发环境

Lucene官网下载:

​ 链接:https://pan.baidu.com/s/1IUfgnKP35NxZDxyGTbPEkw
​ 提取码:3odb

​ luck

​ 链接:https://pan.baidu.com/s/1loka5YFH7KHxzsG2lVDGfw
​ 提取码:yd91

​ IKAnalyzer

​ 链接:https://pan.baidu.com/s/1cCZktGtdAPV-rv9IRLm3Og

​ 提取码:kisq

​ 最低要jdk1.8

​ java工程和jar包

​ lucene-core

​ lucene-analyzers-common

​ commons-io

​ junit

入门案例:

步骤:

创建索引库

  1. 创建一个Directory对象,指定索引库保存的位置 Directory directory = FS 一般保存在磁盘上
  2. 基于Directory对象,创建一个IndexWriter对象 IndexWriter indexwrite = new IndexWriter(directory ,new IndexWirterConfig());
  3. 读取磁盘上的文件,对应每一个文件一个文档对象
  4. 向文档对象中添加域
  5. 把文档对象写入索引库
  6. 关闭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工具的版本,否则将打不开索引库。

当然创建索引库就是为了查询:下面给出查询步骤:

查询索引库

  1. 创建一个Directory对象,指定索引库的位置
  2. 创建一个IndexReader对象
  3. 创建一个IndexSearcher对象构造方法为IndexReader对象
  4. 创建一个Query对象,tremQuery创建,并且设置需要查询的域对象和查询的关键字
  5. 执行查询,得到一个TopDocs对象
  6. 取查询结果的总记录条数
  7. 取文档列表
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对象,此对象中包含了最终的分词结果

​ 步骤:

  1. 创建一个Analyzer对象,StandarAnalyzer对象
  2. 使用分析器对象的tokenStream方法获取TokenStream对象
  3. 向TokenStream对象设置一个引用,相当于一个指针
  4. 调用TokenStream对象的rest方法,如果不调用就抛异常
  5. 循环TokenStream对象
  6. 关闭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();
中文分析器:
  1. jar包
  2. 配置文件和扩展词典
    1. 扩展词典禁止使用Windows的记事本打开,一定要保证文件的编码格式为utf-8
    2. 扩展词典:添加一点新词
    3. 停用词词典:无意义的词和敏感词汇

代码中使用:换一个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();
索引库查询
  • 使用Query子类查询
    • TermQuery:关键词查询

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();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值