全文检索工具 Lucene 入门
最近在了解 Halo 博客后端源码,而全文检索是 Halo 做的比较差的一块内容,仅通过数据库的模糊查询来实现文章检索。对于搜索引擎之前了解的也不多,所以开始入门 Lucene
检索引擎,如果可以的话准备将该引擎应用于 Halo 之上。
整体而言全文检索是一件很费资源的事。
一、Deam 案例
这里举例一个用 Lucene
实现文章查询的例子。
Maven
配置如下:
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>7.2.0</version>
</dependency>
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>7.2.0</version>
</dependency>
<!--中文分词器-->
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-smartcn</artifactId><version>7.2.0</version>
</dependency>
<!--对分词索引查询解析-->
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>7.2.0</version>
</dependency>
<!--检索关键字高亮显示-->
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-highlighter</artifactId><version>7.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.janeluo/ikanalyzer -->
<dependency><groupId>com.janeluo</groupId><artifactId>ikanalyzer</artifactId><version>2012_u6</version>
</dependency>
代码实现:
package com.nineya.lucene;import com.nineya.lucene.entity.Post;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class LuceneMain {private static final List<Post> POSTS = new ArrayList<>();// 索引存储位置private static final String INDEX_PATH = "./data/lucene/indexData";/*** 创建数据*/private static void buildData() {POSTS.add(new Post(1L, "Dream 主题之 Halo 2.0 适配,以及适配前后的一些异同", "我的项目",new String[]{"dream"}, "经过一段时间的适配,目前 Dream 已经发布了基于 Halo 2.x 的第一个预发版本。"));POSTS.add(new Post(2L, "互联网新理念,对于WEB 3.0 你怎么看?", "生活",new String[]{"IDEA", "区块链"}, "WEB 3.0 这个名词走进大众视野已经有一段时间了,也曾在各个圈子里火热一时,至今各大互联网企业任旧在 WEB 3.0 上不断探索。"));POSTS.add(new Post(3L, "GCC编译环境升级部署", "运维",new String[]{"应用部署"}, "近期经常遇到使用源码编译的部署方式进行应用部署,在 GCC 编译环境上遇到各种问题,本文对升级部署 GCC 编译环境的流程以及遇到的一些问题进行记录。"));POSTS.add(new Post(4L, "有一片草原", "生活",new String[]{"故事"}, "从前,有一片广阔无垠的大草原,和风旭日,青草芳美。"));}// 创建索引public static void createIndex() {// 创建索引配置IndexWriterConfig config = new IndexWriterConfig(new SmartChineseAnalyzer());// 索引的打开方式:没有则创建,有则打开config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);// 指定目录创建索引try (Directory directory = FSDirectory.open(Paths.get(INDEX_PATH));IndexWriter indexWriter = new IndexWriter(directory, config)) {if (indexWriter.numDocs() != 0) {System.out.println("WARN: 已经初始化过数据");return;}for (Post post : POSTS) {// 将数据转换成文档Document document = new Document();document.add(new TextField("title", post.getTitle(), Field.Store.YES));// StringField 不做分词document.add(new StringField("categories", post.getCategories(), Field.Store.YES));document.add(new TextField("content", post.getContent(), Field.Store.YES));// 加入到索引中indexWriter.addDocument(document);}// 将提交,保存到硬盘indexWriter.commit();} catch (IOException e) {e.printStackTrace();}}/*** 查询* @param keys* @return*/public static void search(String keys, String categories) {try(DirectoryReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(INDEX_PATH)))) {IndexSearcher searcher = new IndexSearcher(reader);System.out.println(searcher.getTopReaderContext().reader().numDocs());// 组合查询BooleanQuery.Builder builder = new BooleanQuery.Builder();// 给所title项指定查询关键词builder.add(new QueryParser("title", new SmartChineseAnalyzer()).parse(keys), BooleanClause.Occur.MUST);if (categories != null) {// 指定文章分类进行查询builder.add(new TermQuery(new Term("categories", categories)), BooleanClause.Occur.MUST);}BooleanQuery query = builder.build();// 获取符合条件的前两条记录TopDocs docs = searcher.search(query, 2);System.out.println("符合条件的条数为:" + docs.totalHits);// 解析查询结果for (ScoreDoc scoreDoc : docs.scoreDocs) {Document doc = searcher.doc(scoreDoc.doc);System.out.println("title = " + doc.get("title"));System.out.println("- categories = " + doc.get("categories"));System.out.println("- content = " + doc.get("content"));}} catch (ParseException | IOException e) {e.printStackTrace();}}public static void main(String[] args) {// 创建数据buildData();// 创建索引createIndex();// 查询Scanner in = new Scanner(System.in);System.out.print("请输入查询关键词:");while (in.hasNext()) {String keys = in.nextLine();String categories = null;if (keys.contains(" ")) {int index = keys.lastIndexOf(" ");categories = keys.substring(index + 1);keys = keys.substring(0, index);}System.out.printf("keys = %s, categories = %s\n", keys, categories);search(keys, categories);System.out.print("请输入查询关键词:");}}
}
二、问题解决
2.1 数据检索不到
需要注意 StringField
是不会做分词的,这个字段就不能通过 QueryParser
进行检索,而需要通过 TermQuery
进行检索。
2.2 IKAnalyzer 报错
报错内容如下,去查了一下,这是 IKAnalyzer
长期没有维护的原因导致的,和 Lucene
版本不兼容,网上有相关的继承 IKAnalyzer
类解决该报错的方案。
xception in thread "main" java.lang.AbstractMethodError: org.apache.lucene.analysis.Analyzer.createComponents(Ljava/lang/String;)Lorg/apache/lucene/analysis/Analyzer$TokenStreamComponents;at org.apache.lucene.analysis.Analyzer.tokenStream(Analyzer.java:198)at org.apache.lucene.document.Field.tokenStream(Field.java:505)at org.apache.lucene.index.DefaultIndexingChain$PerField.invert(DefaultIndexingChain.java:730)at org.apache.lucene.index.DefaultIndexingChain.processField(DefaultIndexingChain.java:430)at org.apache.lucene.index.DefaultIndexingChain.processDocument(DefaultIndexingChain.java:392)at org.apache.lucene.index.DocumentsWriterPerThread.updateDocument(DocumentsWriterPerThread.java:240)at org.apache.lucene.index.DocumentsWriter.updateDocument(DocumentsWriter.java:496)at org.apache.lucene.index.IndexWriter.updateDocument(IndexWriter.java:1729)at org.apache.lucene.index.IndexWriter.addDocument(IndexWriter.java:1464)at com.nineya.lucene.LuceneMain.createIndex(LuceneMain.java:69)at com.nineya.lucene.LuceneMain.main(LuceneMain.java:116)
全文检索工具 Lucene 入门相关推荐
- 全文检索工具Lucene入门教程
目录 1.什么是Lucene 1.1什么是全文检索 1.2 全文检索的应用场景 1.3. 如何实现全文检索 2.Lucene实现全文检索的流程 2.1. 创建索引和搜索流程图 2.2. 创建索引 2. ...
- 全文检索技术Lucene入门和学习、与数据库数据结合的demo实现
首先,要非常感谢 博客园的 "觉先"先生的分享, 他的博客带我进入了Lucene的大门 :http://www.cnblogs.com/forfuture1978/category ...
- 双向最大匹配算法思想详解,分词器及全文检索工具及Lucene框架简介
一.中文分词理论描述 前言 这篇将使用Java实现基于规则的中文分词算法,一个中文词典将实现准确率高达85%的分词结果.使用经典算法:正向最大匹配和反向最大匹配算法,然后双剑合璧,双向最大匹配. 根据 ...
- Lucene入门之全文检索基本介绍
1.什么是全文检索 1.1 数据分类 我们生活中的数据总体分为两种:结构化数据和非结构化数据. 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等. 非结构化数据:指不定长或无固定格式的数 ...
- 全文检索(一) -- Lucene
1. 前言 1.1 为什么要用Lucene 原来的方式实现搜索功能,我们的搜索流程如下图:如果用户比较少而且数据库的数据量比较小,那么这种方式实现搜索功能在企业中是比较常见的. 现在的方案(使用Luc ...
- 阿翔编程学-Lucene入门与使用
Lucene入门与使用 本文主要面向具体使用,适用于已熟悉java编程的lucene初学者. 1. Lucene的简介 1.1 Lucene 历史 org.apache.lucene包是纯java语言 ...
- 全文检索工具elasticsearch:第一章:理论知识
搜索 什么是搜索, 计算机根据用户输入的关键词进行匹配,从已有的数据库中摘录出相关的记录反馈给用户. 常见的全网搜索引擎,像百度.谷歌这样的.但是除此以外,搜索技术在垂直领域也有广泛的使用,比如淘宝. ...
- 开发自己的搜索引擎读书笔记——搜索引擎与信息检索、Lucene入门
这部分是在读<开发自己的搜索引擎>第二版,邱哲.符滔滔.王学松编著,人民邮电出版社,的随手笔记与猜想.若有不足之处还请不吝赐教,以不断完善之. 搜索引擎与信息检索 信息检索的过程: 构建文 ...
- Lucene 入门教程
了解搜索技术 什么是搜索 简单的说,搜索就是搜寻.查找,在IT行业中就是指用户输入关键字,通过相应的算法,查询并返回用户所需要的信息. 普通的数据库搜索 类似:select * from 表名 whe ...
最新文章
- 面试90%都会翻车的高可用+高并发+负载均衡架构设计 !
- .net里鼠标选中的text数据怎么获取_怎么利用Excel设置当天生日提醒功能
- [UVa10296]Jogging Trails
- 【Python学习教程】:装饰器的详细教程,通俗易懂
- Codeforces Round #433 (Div. 2, based on Olympiad of Metropolises)
- 微服务 第六章 springboot 通过Spring-data-jpa 配置Oracle数据源(简单步骤)
- EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因
- 今天,送你一份交通行业最全数据集(共享单车、自动驾驶、网约出租车、交通信号识别)
- SpringAOP xml 方式和注解简单实现日志处理
- 马桶怎么清洗才干净无异味?
- OC 方法,继承,特殊方法
- 重学C---------第五节:常量
- jquery serialize 和 console 漫谈
- STM32F103C8T6系统板
- 诺奖经济大师,数学天才赌徒,和“神秘的股市财富公式”
- linux挂载VMFS硬盘,挂载ESXi服务器VMFS存储卷
- 一个web前端专科生面试后的感概
- 转发:上海软件公司排行 (估计是2008年的吧)
- 五子棋智能算法——决策树编程实现(三)
- mac os之监听触摸板(捏合、旋转、三指)
热门文章
- 国产ThinkJS 项目构建 Docker 镜像制作与log日志问题
- (十)CMake链接已有的动态库
- 北京、上海家庭年收入情况统计 (zz)
- Android 多屏显示
- 零基础无实物一步一步学PLCS7-1200仿真(九)-八位流水灯/跑马灯
- java收费学java,讷河学java编程,讷河java编程学习的学校,讷河java编程学习一般怎么收费...
- 挡土墙lisp程序_基于Visual LISP与C#的水工挡土墙计算软件开发
- Mathematica12 免费安装教程
- 1450种时尚排版包装LOGO标题字幕条转场背景图形元素动画V3预设AE脚本PR预设 Motion Bro脚本预设包
- 中国营销人的第6项修炼