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(); } }
来源:https://www.cnblogs.com/roadlandscape/p/12547143.html