Lucene的java库使用

java实现建立索引

在数据库中建一个lucene库,插入一个tb_sku表,内含百万条目级别的数据。

附建表sql下载:

链接:https://pan.baidu.com/s/13FbFc5YmzaTcj0Rxh-O2Bg
提取码:ue7x

新建工程,

pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>luceneDemo</artifactId>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <skipTests>true</skipTests>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>7.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>7.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>7.7.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>

        <!-- IK中文分词器 -->
        <dependency>
            <groupId>org.wltea.ik-analyzer</groupId>
            <artifactId>ik-analyzer</artifactId>
            <version>8.1.0</version>
        </dependency>

        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- Json转换工具 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.51</version>
        </dependency>
    </dependencies>

</project>

实体类:

@Data
public class Sku {
    //商品主键id
    private String id;
    //商品名称
    private String name;
    //价格
    private Integer price;
    //库存数量
    private Integer num;
    //图片
    private String image;
    //分类名称
    private String categoryName;
    //品牌名称
    private String brandName;
    //规格
    private String spec;
    //销量
    private Integer saleNum;

}

新建一个Dao接口及其实现,这里不展示代码

写一个测试类,通过测试方法建立索引:

@Test
public void createIndexTest() throws IOException {
    //1. 采集数据
    SkuDao skuDao = new SkuDaoImpl();
    List<Sku> skuList = skuDao.querySkuList();

    List<Document> docList = new ArrayList<>();
    //2. 创建文档对象
    for (Sku sku : skuList) {
        Document document = new Document();

        //创建域对象
        document.add(new TextField("id", sku.getId(), Field.Store.YES));
        document.add(new TextField("name", sku.getName(), Field.Store.YES));
        document.add(new TextField("price", String.valueOf(sku.getPrice()), Field.Store.YES));
        document.add(new TextField("image", sku.getImage(), Field.Store.YES));
        document.add(new TextField("categoryName", sku.getCategoryName(), Field.Store.YES));
        document.add(new TextField("brandName", sku.getBrandName(), Field.Store.YES));
        //将文档对象放入文档集合中
        docList.add(document);
    }
    //3. 创建分词器,StandardAnalyzer对英文分词效果好,对中文是单字分词
    Analyzer analyzer = new StandardAnalyzer();
    //4. 创建Directory目录对象,表示索引库的位置
    Directory dir = FSDirectory.open(Paths.get("D:\\dir"));
    //5. 创建IndexWriterConfig对象,指定切分词使用的分词器
    IndexWriterConfig config = new IndexWriterConfig(analyzer);
    //6. 创建IndexWriter输出流对象,指定输出的位置和使用的config初始化对象
    IndexWriter indexWriter = new IndexWriter(dir,config);
    //7. 写入文档到索引库
    for (Document document : docList) {
        indexWriter.addDocument(document);
    }
    //8. 释放资源
    indexWriter.close();
}

运行前先建立对应的目录D:\dir,运行后即可在目录下看到许多lucene建立索引后生成的存储文件

Lucene的java库使用

使用Luke工具查看生成的文件内容

打开工具,选择数据文件所在的目录

Lucene的java库使用

在overview标签页可以看到概览信息,包括域数、文档数、词数、词的频数统计

Lucene的java库使用

在document标签页可以看到单个的文档信息

Lucene的java库使用

在search标签页可以进行搜索

Lucene的java库使用

使用java查询数据

@Test
public void testSearch() throws ParseException, IOException {
    //1. 创建分词器(对搜索的文本进行分词)
    //注意;分词器要和创建索引时用的分词器一样
    Analyzer analyzer = new StandardAnalyzer();
    //2. 创建查询对象,第一个参数:默认查询域
    //第二个参数:使用的分词器
    QueryParser queryParser = new QueryParser("name",analyzer);
    //3. 设置搜索关键词
    Query query = queryParser.parse("华为手机");
    //写成queryParser.parse("brandName: 华为手机");又可以指定查询域
    //4. 创建Directory目录对象,指定索引库的位置
    Directory dir = FSDirectory.open(Paths.get("D:\\dir"));
    //5. 创建输入流对象
    IndexReader indexReader = DirectoryReader.open(dir);
    //6. 创建搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    //7. 搜索,并返回结果
    //第二个参数:返回多少条消息,分页使用
    TopDocs topDocs = indexSearcher.search(query, 10);
    System.out.println("count: "+topDocs.totalHits);
    //8. 获取结果集
    ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    //9. 遍历结果集
    if(scoreDocs != null){
        for (ScoreDoc scoreDoc : scoreDocs) {
            //获取查询到的文档唯一标识ID,这个ID是由lucene创建文档的时候分配的
            int docID = scoreDoc.doc;
            //通过ID读取文档
            Document doc = indexSearcher.doc(docID);
            System.out.println("============================");
            //通过域名,从文档中获取域值
            System.out.println("id: "+doc.get("id"));
            System.out.println("name: "+doc.get("name"));
            System.out.println("price: "+doc.get("price"));
            System.out.println("image: "+doc.get("image"));
            System.out.println("brandName: "+doc.get("brandName"));
            System.out.println("categoryName: "+doc.get("categoryName"));
        }
    }
    //10. 关闭流
    indexReader.close();
}

查看输出:

Lucene的java库使用

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/lucene%e7%9a%84java%e5%ba%93%e4%bd%bf%e7%94%a8/