1、介绍lucene的功能以及建立索引、搜索单词、搜索词语和搜索句子四个示例实现

编程入门 行业动态 更新时间:2024-10-09 13:21:19

1、介绍lucene的功能以及建立索引、搜索单词、搜索词语和搜索句子四个<a href=https://www.elefans.com/category/jswz/34/1770116.html style=示例实现"/>

1、介绍lucene的功能以及建立索引、搜索单词、搜索词语和搜索句子四个示例实现

Elasticsearch 系列文章

1、介绍lucene的功能以及建立索引、搜索单词、搜索词语和搜索句子四个示例实现
2、Elasticsearch7.6.1基本介绍、2种部署方式及验证、head插件安装、分词器安装及验证
3、Elasticsearch7.6.1信息搜索示例(索引操作、数据操作-添加、删除、导入等、数据搜索及分页)
4、Elasticsearch7.6.1 Java api操作ES(CRUD、两种分页方式、高亮显示)和Elasticsearch SQL详细示例
5、Elasticsearch7.6.1 filebeat介绍及收集kafka日志到es示例
6、Elasticsearch7.6.1、logstash、kibana介绍及综合示例(ELK、grok插件)
7、Elasticsearch7.6.1收集nginx日志及监测指标示例
8、Elasticsearch7.6.1收集mysql慢查询日志及监控
9、Elasticsearch7.6.1 ES与HDFS相互转存数据-ES-Hadoop


文章目录

  • Elasticsearch 系列文章
  • 一、Lucene全文检索库
    • 1、全文检索
    • 2、Lucene简介
  • 二、示例
    • 1、准备测试数据
    • 2、建立索引库
    • 3、实现
      • 1)、maven 依赖
      • 2)、java 实现
    • 4、查询-单字搜索
      • 1)、实现步骤
      • 2)、代码
    • 5、查询-词语搜索
      • 1)、分词器与中文分词器
      • 2)、实现步骤
      • 3)、maven 依赖
      • 4)、代码
      • 5)、验证
    • 6、句子搜索
    • 4、倒排索引结构


本文简单的介绍了 lucene的功能以及四个示例(建立索引、搜索单词、搜索词语和搜索句子),是Elasticsearch的引导篇。
本文分为2个部分,即介绍lucene和使用示例。

一、Lucene全文检索库

1、全文检索

  • 结构化数据与非结构化数据
    结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等
    非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件
  • 搜索结构化数据和非结构化数据
    使用SQL语言专门搜索结构化的数据
    使用ES/Lucene/Solor建立倒排索引,根据关键字就可以搜索一些非结构化的数据
  • 全文检索
    全文检索是指通过一个程序扫描文本中的每一个单词,针对单词建立索引,并保存该单词在文本中的位置、以及出现的次数。用户查询时,通过之前建立好的索引来查询,将索引中单词对应的文本位置、出现的次数返回给用户,因为有了具体文本的位置,所以就可以将具体内容读取出来了,类似于通过字典中的检索字表查字的过程。

2、Lucene简介

Lucene是一种高性能的全文检索库,在2000年开源,最初由Doug Cutting(道格·卡丁)开发
Lucene是Apache的一个顶级开源项目,是一个全文检索引擎工具包。但Lucene不是一个完整的全文检索引擎,它只是提供一个基本的全文检索的架构,还提供了一些基本的文本分词库
Lucene是一个简单易用的工具包,可以方便的实现全文检索的功能

二、示例

通过搜索一个关键字就能够找到哪些文章包含了这些关键字。例如:搜索「hadoop」,就能找到hadoop相关的文章。

1、准备测试数据

自行准备测试数据即可

2、建立索引库

实现步骤

  • 构建分词器(StandardAnalyzer)
  • 构建文档写入器配置(IndexWriterConfig)
  • 构建文档写入器(IndexWriter,注意:需要使用Paths来)
  • 读取所有文件构建文档
  • 文档中添加字段
  • 写入文档
  • 关闭写入器

3、实现

1)、maven 依赖

 <!-- lucene核心类库 --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>8.4.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>8.4.0</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>

2)、java 实现

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;import org.apachemons.io.FileUtils;
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;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;/*** 通过这个类来读取文章的文本文件,建立索引* * @author chenw**/
public class BuildArticleIndex {public static void main(String[] args) throws IOException {// 1. 构建分词器(StandardAnalyzer)Analyzer standardAnalyzer = new StandardAnalyzer();// 2. 构建文档写入器配置(IndexWriterConfig)IndexWriterConfig writerConfig = new IndexWriterConfig(standardAnalyzer);// 3. 构建文档写入器(IndexWriter,注意:需要使用Paths来)IndexWriter indexWriter = new IndexWriter(FSDirectory.open(Paths.get("D:\\workspace\\es\\lucene\\index")), writerConfig);// 4. 读取所有文件构建文档// 读取data目录中的所有文件File dataDir = new File("D:\\workspace\\es\\lucene\\data");File[] fileArray = dataDir.listFiles();// 迭代所有的文本文件,读取文件并建立索引for (File file : fileArray) {// 5. 文档中添加字段// 字段名 类型 说明// file_name TextFiled 文件名字段,需要在索引文档中保存文件名内容// content TextFiled 内容字段,只需要能被检索,但无需在文档中保存// path StoredFiled 路径字段,无需被检索,只需要在文档中保存即可// 在Lucene中都是以Document的形式来存储内容的// Lucene在添加文档的时候就会自动建立索引Document doc = new Document();// 如果需要建立索引,就用TextField,如果不需要就使用StoredFielddoc.add(new TextField("file_name", file.getName(), Field.Store.YES));doc.add(new TextField("content", FileUtils.readFileToString(file), Field.Store.NO));doc.add(new StoredField("path", file.getAbsolutePath()));// 6. 写入文档indexWriter.addDocument(doc);}// 7. 关闭写入器indexWriter.close();}
}

运行完上述程序后的输出如下图

4、查询-单字搜索

该示例只能搜索单字,如果想搜索多字,则需要使用相关分词器

1)、实现步骤

使用DirectoryReader.open构建索引读取器
构建索引查询器(IndexSearcher)
构建词条(Term)和词条查询(TermQuery)
执行查询,获取文档
遍历打印文档(可以使用IndexSearch.doc根据文档ID获取到文档)
关键索引读取器

2)、代码

import java.io.IOException;
import java.nio.file.Paths;import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;public class KeywordSearch {public static void main(String[] args) throws IOException {// 1. 使用DirectoryReader.open构建索引读取器DirectoryReader reader = DirectoryReader.open(FSDirectory.open(Paths.get("D:\\workspace\\es\\lucene\\index")));// 2. 构建索引查询器(IndexSearcher)// 用来搜索关键字的IndexSearcher indexSearcher = new IndexSearcher(reader);// 3. 构建词条(Term)和词条查询(TermQuery)TermQuery termQuery = new TermQuery(new Term("content", "他"));// 4. 执行查询,获取文档TopDocs topDocs = indexSearcher.search(termQuery, 50);// 5. 遍历打印文档(可以使用IndexSearch.doc根据文档ID获取到文档)ScoreDoc[] scoreDocArray = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocArray) {// 在Lucene中,每一个文档都有一个唯一ID// 根据唯一ID就可以获取到文档Document document = indexSearcher.doc(scoreDoc.doc);// 获取文档中的字段System.out.println("-------------");System.out.println("文件名:" + document.get("file_name"));System.out.println("文件路径:" + document.get("path"));//content是否有内容,取决于创建索引时是否存储System.out.println("文件内容:" + document.get("content"));}// 6. 关闭索引读取器reader.close();}}运行结果
-------------
文件名:飞翔的精灵.txt
文件路径:D:\workspace\es\lucene\data\飞翔的精灵.txt
文件内容:null
-------------
文件名:一辈子陪伴.txt
文件路径:D:\workspace\es\lucene\data\一辈子陪伴.txt
文件内容:null
-------------
文件名:永远的坐票.txt
文件路径:D:\workspace\es\lucene\data\永远的坐票.txt
文件内容:null
-------------
文件名:大度也是一种美德.txt
文件路径:D:\workspace\es\lucene\data\大度也是一种美德.txt
文件内容:null

5、查询-词语搜索

1)、分词器与中文分词器

分词器是指将一段文本,分割成为一个个的词语的动作。例如:按照停用词进行分隔(的、地、啊、吧、标点符号等)。之前在代码中使用的分词器是Lucene中自带的分词器。这个分词器对中文很不友好,只是将一个一个字分出来,所以,就会从后出现上面的问题——无法搜索词语。
所以,基于该背景,我们需要使用跟适合中文的分词器。中文分词器也有不少,例如:

  • Jieba分词器

  • IK分词器

  • 庖丁分词器

  • Smarkcn分词器
    等等。此处使用比较好用的IK分词器来进行分词。

  • IK介绍
    IK已经实现好了Lucene的分词器:
    IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的 IKAnalyzer3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。

  • IKAnalyzer3.0特性
    采用了特有的“正向迭代最细粒度切分算法“,支持细粒度和最大词长两种切分模式;具有83万字/秒(1600KB/S)的高速处理能力。
    采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符
    优化的词典存储,更小的内存占用。支持用户词典扩展定义
    针对Lucene全文检索优化的查询分析器IKQueryParser;引入简单搜索表达式,采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。

2)、实现步骤

把之前生成的索引文件删除,然后将之前使用的StandardAnalyzer修改为IKAnalyzer。然后重新生成索引。

  • 构建分词器(IKAnalyzer)
  • 构建文档写入器配置(IndexWriterConfig)
  • 构建文档写入器(IndexWriter,注意:需要使用Paths来)
  • 读取所有文件构建文档
  • 文档中添加字段
  • 写入文档
  • 关闭写入器

3)、maven 依赖

<!-- lucene核心类库 --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>8.4.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>8.4.0</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>com.jianggujin</groupId><artifactId>IKAnalyzer-lucene</artifactId><version>8.0.0</version></dependency>

4)、代码

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;import org.apachemons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;/*** 通过这个类来读取文章的文本文件,建立索引* * @author chenw**/
public class BuildArticleIndex {public static void main(String[] args) throws IOException {// 1. 构建分词器(StandardAnalyzer)Analyzer standardAnalyzer = new IKAnalyzer();// 2. 构建文档写入器配置(IndexWriterConfig)IndexWriterConfig writerConfig = new IndexWriterConfig(standardAnalyzer);// 3. 构建文档写入器(IndexWriter,注意:需要使用Paths来)IndexWriter indexWriter = new IndexWriter(FSDirectory.open(Paths.get("D:\\workspace\\es\\lucene\\index")), writerConfig);// 4. 读取所有文件构建文档// 读取data目录中的所有文件File dataDir = new File("D:\\workspace\\es\\lucene\\data");File[] fileArray = dataDir.listFiles();// 迭代所有的文本文件,读取文件并建立索引for (File file : fileArray) {// 5. 文档中添加字段// 字段名 类型 说明// file_name TextFiled 文件名字段,需要在索引文档中保存文件名内容// content TextFiled 内容字段,只需要能被检索,但无需在文档中保存// path StoredFiled 路径字段,无需被检索,只需要在文档中保存即可// 在Lucene中都是以Document的形式来存储内容的// Lucene在添加文档的时候就会自动建立索引Document doc = new Document();// 如果需要建立索引,就用TextField,如果不需要就使用StoredFielddoc.add(new TextField("file_name", file.getName(), Field.Store.YES));doc.add(new TextField("content", FileUtils.readFileToString(file), Field.Store.NO));doc.add(new StoredField("path", file.getAbsolutePath()));// 6. 写入文档indexWriter.addDocument(doc);}// 7. 关闭写入器indexWriter.close();}
}

5)、验证

采用单字搜索的例子,只是将搜索的字变成一个词语。运行结果如下:

-------------
文件名:永远的坐票.txt
文件路径:D:\workspace\es\lucene\data\永远的坐票.txt
文件内容:null
-------------
文件名:一辈子陪伴.txt
文件路径:D:\workspace\es\lucene\data\一辈子陪伴.txt
文件内容:null

6、句子搜索

要实现搜索句子,是将句子进行分词后,再进行搜索。我们需要使用QueryParser类来实现。通过QueryParser可以指定分词器对要搜索的句子进行分词。

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;import java.io.IOException;
import java.nio.file.Paths;
import java.text.ParseException;/*** @author chenw**/
public class SentenceSearch {public static void main(String[] args) throws IOException, ParseException, org.apache.lucene.queryparser.classic.ParseException {// 1. 构建索引读取器IndexReader indexReader = DirectoryReader.open(FSDirectory.open(Paths.get("D:\\workspace\\es\\lucene\\index")));// 2. 构建索引查询器IndexSearcher indexSearcher = new IndexSearcher(indexReader);// 3. 执行查询,获取文档QueryParser queryParser = new QueryParser("content", new IKAnalyzer());TopDocs topDocs = indexSearcher.search(queryParser.parse("人生是一条河"), 50);ScoreDoc[] scoreDocArrary = topDocs.scoreDocs;// 4. 遍历打印文档for (ScoreDoc scoreDoc : scoreDocArrary) {int docId = scoreDoc.doc;Document document = indexSearcher.doc(docId);System.out.println("文件名:" + document.get("file_name") + " 路径:" + document.get("path"));}indexReader.close();}}
运行结果:加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
文件名:月台.txt 路径:D:\workspace\es\lucene\data\月台.txt
文件名:永远的坐票.txt 路径:D:\workspace\es\lucene\data\永远的坐票.txt
文件名:大度也是一种美德.txt 路径:D:\workspace\es\lucene\data\大度也是一种美德.txt
文件名:一辈子陪伴.txt 路径:D:\workspace\es\lucene\data\一辈子陪伴.txt
文件名:飞翔的精灵.txt 路径:D:\workspace\es\lucene\data\飞翔的精灵.txt

4、倒排索引结构

倒排索引是一种建立索引的方法。是全文检索系统中常用的数据结构。通过倒排索引,就是根据单词快速获取包含这个单词的文档列表。倒排索引通常由两个部分组成:单词词典、文档。

以上,简单的介绍了 lucene的功能以及四个示例(建立索引、搜索单词、搜索词语和搜索句子)。

更多推荐

1、介绍lucene的功能以及建立索引、搜索单词、搜索词语和搜索句子四个示例实现

本文发布于:2024-02-13 20:39:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1760328.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:示例   句子   词语   单词   索引

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!