Lucene入门

最后都变了- 提交于 2020-03-22 18:15:28

Lucene快速入门:

  搭建环境

    1.创建工程,引入坐标(springboot工程)

<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>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
</parent>

<dependencies>
    <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.47</version>
    </dependency>

    <!-- IK中文分词器 -->
    <dependency>
        <groupId>com.github.magese</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.56</version>
    </dependency>
</dependencies>

    2.创建数据库,准备百万条数据

      ..........

    3.在磁盘创建Lucene索引文件和文档文件的存放目录(索引库)

      

  索引流程

    1.数据采集

      在电商网站中,全文检索的数据源在数据库中,需要通过jdbc访问数据库中 sku 表的内容。

      创建pojo对象:

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;

    /********* get/set方法 *********/
}

      创建DAO:

public class SkuDao {

    public List<Sku> querySkuList() {
        // 数据库链接
        Connection connection = null;
        // 预编译statement
        PreparedStatement preparedStatement = null;
        // 结果集
        ResultSet resultSet = null;
        // 商品列表
        List<Sku> list = new ArrayList<Sku>();

        try {
            // 加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 连接数据库
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/lucene", "root", "root");
            // SQL语句
            String sql = "SELECT * FROM tb_sku";
            // 创建preparedStatement
            preparedStatement = connection.prepareStatement(sql);
            // 获取结果集
            resultSet = preparedStatement.executeQuery();
            // 结果集解析
            while (resultSet.next()) {
                Sku sku = new Sku();
                sku.setId(resultSet.getString("id"));
                sku.setName(resultSet.getString("name"));
                sku.setSpec(resultSet.getString("spec"));
                sku.setBrandName(resultSet.getString("brand_name"));
                sku.setCategoryName(resultSet.getString("category_name"));
                sku.setImage(resultSet.getString("image"));
                sku.setNum(resultSet.getInt("num"));
                sku.setPrice(resultSet.getInt("price"));
                sku.setSaleNum(resultSet.getInt("sale_num"));
                list.add(sku);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }
}

    2.实现索引流程

/**
 * 索引库维护
 */
public class IndexManagerTest {

    /**
     * 创建索引库
     */
    @Test
    public void testCreateIndex() throws IOException {
        // 1. 采集数据
        SkuDao skuDao = new SkuDao();
        List<Sku> skus = skuDao.querySkuList();

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

            // 创建域对象,并且放入文档对象中
            document.add(new TextField("id", sku.getId(), TextField.Store.YES));
            document.add(new TextField("name", sku.getName(), TextField.Store.YES));
            document.add(new TextField("price", String.valueOf(sku.getPrice()), TextField.Store.YES));
            document.add(new TextField("image", sku.getImage(), TextField.Store.YES));
            document.add(new TextField("categoryName", sku.getCategoryName(), TextField.Store.YES));
            document.add(new TextField("brandName", sku.getBrandName(), TextField.Store.YES));

            // 将文档对象放入到文档集合中
            docList.add(document);
        }
        // 3. 创建分析器(分词器) StandardAnalyzer标准分词器,对英文分词效果好,对中文是单字分词
        Analyzer analyzer = new StandardAnalyzer();
        // 4. 创建IndexWriterConfig配置信息类,指定切分词使用的分词器
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        // 5. 创建Directory对象,声明索引库存储位置
        Directory dir = FSDirectory.open(Paths.get("D:\\lucene"));
        // 6. 创建IndexWriter写入对象,指定写入的位置和使用的config初始化对象
        IndexWriter indexWriter = new IndexWriter(dir, config);
        // 7. 把Document写入到索引库中
        for (Document document : docList) {
            indexWriter.addDocument(document);
        }
        // 8. 释放资源
        indexWriter.close();
    }
}

    3.执行效果:在文件夹中出现了以下文件,表示创建索引成功

      

  使用Luke查看索引:

    

 

 

     

 

 

     

 

 

   搜索流程:

    IndexSearcher搜索方法如下:

      

/**
 * 测试搜索过程
 */
public class SearchTest {

    @Test
    public void testSearch() throws ParseException, IOException {
        // 1.创建分词器(对搜索的关键词进行分词使用,分词器要和创建索引的时候使用的分词器一样)
        Analyzer analyzer = new StandardAnalyzer();
        // 2.创建Query搜索对象
        QueryParser queryParser = new QueryParser("name", analyzer);
        // 3.设置搜索关键词
        // Query query = queryParser.parse("华为手机");// 默认在name域中查
        Query query = queryParser.parse("brandName:生机谷");
        // 4.创建Directory目录对象,指定索引库位置
        Directory dir = FSDirectory.open(Paths.get("D:\\lucene"));
        // 5.创建输入流对象
        IndexReader indexReader = DirectoryReader.open(dir);
        // 6.创建索引搜索对象IndexSearcher
        IndexSearcher searcher = new IndexSearcher(indexReader);
        // 7.使用索引搜索对象,执行搜索,返回结果集TopDocs
        // 第二个参数表示返回多少条数据用于展示,分页使用
        TopDocs topDocs = searcher.search(query, 10);
        // 获取查询到的结果集总数
        long total = topDocs.totalHits;
        System.out.println(total);
        // 8.获取结果集
        ScoreDoc[] docs = topDocs.scoreDocs;
        // 9.解析结果集
        if(docs != null) {
            for (ScoreDoc scoreDoc : docs) {
                // 获取查询到的文档唯一标识,文档id,这个id是Lucene在创建文档的时候自动分配的
                int docID = scoreDoc.doc;
                // 通过文档id读取文档
                Document doc = searcher.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("categoryName:" + doc.get("categoryName"));
                System.out.println("brandName:" + doc.get("brandName"));
            }
        }
        // 10.释放资源
        indexReader.close();
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!