欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

02.全文检索lucene创建索引库

程序员文章站 2022-07-09 12:40:10
...

全文检索lucene创建索引库

一、环境搭建

1). 下载Lucene

http://lucene.apach.org

2). 核心jar包

jdk版本要求 1.8+

  1. lucene-analyzers-common-7.4.0.jar
  2. lucene-core-7.4.0.jar
  3. commons-io.jar

3). maven依赖

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>7.4.0</version>
</dependency>
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-analyzers-common</artifactId>
    <version>7.4.0</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

二、步骤

1). 创建索引库

//1. 创建一个Director对象,指定索引库保存的位置。
/*   把索引库保存在内存中 了解即可 实际项目中不需要使用
     Directory directory = new RAMDirectory();
*/
// 将索引库保存在磁盘指定的位置
Directory directory = FSDirectory.open(new File("E:\\lucene_repository\\rep_01").toPath());

//2. 基于Directory对象创建一个IndexWriter对象,
/** 使用 IndexWriterConfig 默认配置 (无参构造创建的为 标准的分析器 StandardAnalyzer ) 。
    IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
*/

// 使用中文的分词器配置创建索引库【还需要安装第三方包和配置文件,详见文章末尾介绍!】
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
IndexWriter indexWriter = new IndexWriter(directory, config);

//3. 读取磁盘上的文件,对应每个文件创建一个文档对象。
File dir = new File("F:\\03Web开发\\03_lucene\\02.参考资料\\searchsource");
File[] files = dir.listFiles();
for (File file : files) {
    // 取文件名
    String fileName = file.getName();

    // 文件的路径
    String filePath = file.getPath();

    // 文件的内容
    String fileContent = FileUtils.readFileToString(file, "UTF-8");

    // 文件的大小
    long fileSize = FileUtils.sizeOf(file);

    // 创建Field 【lucene包】下的Field对象
    /* 参数1:域的名称; 参数2:域的内容; 参数3:是否存储:
       域 field 的区别(TextField/StoredField等) 在后面的文章中详解
     */
    // fieldName文件名 分析 索引 存储
    Field fieldName = new TextField("name", fileName, Field.Store.YES);

    // fieldPath文件路径 存储
    Field fieldPath = new StoredField("path", filePath);

    Field fieldContent = new TextField("content", fileContent, Field.Store.YES);

    // fieldSizeValue文件大小值 分析 索引
    Field fieldSizeValue = new LongPoint("size", fileSize);
    // fieldSizeStore 存储 【size域有两个域属性】
    Field fieldSizeStore = new StoredField("size", fileSize + "");


    // 创建文档对象
    Document document = new Document();

    //4. 向文档对象中添加域
    document.add(fieldName);
    document.add(fieldPath);
    document.add(fieldContent);
    document.add(fieldSize);

    //5. 把文档对象写入索引库
    indexWriter.addDocument(document);
}
//6. 关闭indexWriter对象。
indexWriter.close();

使用luck工具可以查看索引库中的信息

2). 查询索引库

//1. 创建一个Director对象,指定索引库的位置
Directory directory = FSDirectory.open(new File("E:\\lucene_repository\\rep_01").toPath());

//2. 创建一个IndexReader对象
IndexReader indexReader = DirectoryReader.open(directory);

//3. 创建一个IndexSearcher对象,构造方法中的参数indexReader对象。
IndexSearcher indexSearcher = new IndexSearcher(indexReader);

//4. 创建一个Query对象,TermQuery, 第一个为域,第二个为查询的内容
Query query = new TermQuery(new Term("content", "spring"));

//5. 执行查询,得到一个TopDocs对象
// 参数1: 查询对象; 参数2:限制查询结果返回的最大记录数,
TopDocs topDocs = indexSearcher.search(query, 10);

//6. 取查询结果的总记录数
System.out.println("查询的总记录数:" + topDocs.totalHits);

//7. 取文档列表
ScoreDoc[] scoreDocs = topDocs.scoreDocs;

//8. 打印文档中的内容
for (ScoreDoc doc : scoreDocs) {
    // 取文档id
    int docId = doc.doc;

    // 根据id获取文档对象
    Document document = indexSearcher.doc(docId);
    System.out.println(document.get("name"));
    System.out.println(document.get("path"));
    System.out.println(document.get("size"));
    //System.out.println(document.get("content"));
    System.out.println("--------------------------------");
}

//9. 关闭IndexReader对象。
indexReader.close();

三、分析器

默认使用为标准分析器 StandardAnalyzer

1). 查看默认分词器的分词效果,就是过滤的最终效果

任何分词器都继承了Analyzer抽象类,使用tokenStream方法返回一个TokenStream对象。词对象中包含了最终分词的结果。
标准分词器分析英文绰绰有余,但是中文,呵呵。。

// 1. 创建一个lucene包下的Analyzer对象,这里使用标准的StandardAnalyzer对象,
Analyzer analyzer = new StandardAnalyzer();

// 2. 使用分词对象的tokenStream方法获得一个TokenStream对象。
// 第一个参数为 fieldName,此案例不需要使用
TokenStream tokenStream = analyzer.tokenStream("", "The Spring Framework provides a comprehensive programming and configuration model.");

// 3. 向TokenStream对象中设置一个引用,相当于一个指针,然后进行分析
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);

// 4. 调用TokenStream对象的rest方法,重置引用的位置,方便接下来打印输出
tokenStream.reset();

// 5. 使用while循环遍历TokenStream对象
while (tokenStream.incrementToken()) {
    System.out.println(charTermAttribute.toString());
}

// 6. 关闭TokenStream对象
tokenStream.close();

2). 中文分词器 IKAnalyze的使用方法

  1. 把IKAnalyzer的jar包 IK-Analyzer-1.0-SNAPSHOT.jar 添加到工程中;或者将jar包安装到本地maven仓库,或者私服
  2. 将配置文件和扩展词典添加到工程的classpath下 (resources目录)
    • hotword.dic: 扩展词典 (格式就是每行一个词语,可以根据业务需求添加,utf-8)
    • stopword.dic: 停用词典 (格式就是每行一个词语,可以根据业务需求添加,utf-8)
    • IKAnalyzer.cfg.xml: 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 扩展配置</comment>
    <!--用户可以在这里配置自己的扩展字典,可配置多个 -->
    <entry key="ext_dict">hotword.dic;</entry>

    <!--用户可以在这里配置自己的扩展停止词字典,可配置多个-->
    <entry key="ext_stopwords">stopword.dic;</entry>

</properties>
  1. 注意:
    1. 扩展字典严禁使用win的记事本打开编辑,必须得保证编码为utf-8
    2. 扩展词典可以添加一个新词
    3. 停用词典:无意义的词或者是敏感词汇

案例演示

Analyzer analyzer = new IKAnalyzer();
TokenStream tokenStream = analyzer.tokenStream("",
        "我是一个兵\n来自老百姓\n打败了日本狗强盗\n消灭了蒋匪军\n我是一个兵\n爱国爱人民\n革命战争考验了我\n立场更坚定");
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
tokenStream.reset();
while (tokenStream.incrementToken()) {
    System.out.println(charTermAttribute.toString());
}
tokenStream.close();

3). 中文分词器 IKAnalyze 的使用方法

代码部分详见 【二、步骤】 -> 【1). 创建索引库】