最近在了解 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 入门相关推荐

  1. 全文检索工具Lucene入门教程

    目录 1.什么是Lucene 1.1什么是全文检索 1.2 全文检索的应用场景 1.3. 如何实现全文检索 2.Lucene实现全文检索的流程 2.1. 创建索引和搜索流程图 2.2. 创建索引 2. ...

  2. 全文检索技术Lucene入门和学习、与数据库数据结合的demo实现

    首先,要非常感谢 博客园的 "觉先"先生的分享, 他的博客带我进入了Lucene的大门 :http://www.cnblogs.com/forfuture1978/category ...

  3. 双向最大匹配算法思想详解,分词器及全文检索工具及Lucene框架简介

    一.中文分词理论描述 前言 这篇将使用Java实现基于规则的中文分词算法,一个中文词典将实现准确率高达85%的分词结果.使用经典算法:正向最大匹配和反向最大匹配算法,然后双剑合璧,双向最大匹配. 根据 ...

  4. Lucene入门之全文检索基本介绍

    1.什么是全文检索 1.1 数据分类 我们生活中的数据总体分为两种:结构化数据和非结构化数据. 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等. 非结构化数据:指不定长或无固定格式的数 ...

  5. 全文检索(一) -- Lucene

    1. 前言 1.1 为什么要用Lucene 原来的方式实现搜索功能,我们的搜索流程如下图:如果用户比较少而且数据库的数据量比较小,那么这种方式实现搜索功能在企业中是比较常见的. 现在的方案(使用Luc ...

  6. 阿翔编程学-Lucene入门与使用

    Lucene入门与使用 本文主要面向具体使用,适用于已熟悉java编程的lucene初学者. 1. Lucene的简介 1.1 Lucene 历史 org.apache.lucene包是纯java语言 ...

  7. 全文检索工具elasticsearch:第一章:理论知识

    搜索 什么是搜索, 计算机根据用户输入的关键词进行匹配,从已有的数据库中摘录出相关的记录反馈给用户. 常见的全网搜索引擎,像百度.谷歌这样的.但是除此以外,搜索技术在垂直领域也有广泛的使用,比如淘宝. ...

  8. 开发自己的搜索引擎读书笔记——搜索引擎与信息检索、Lucene入门

    这部分是在读<开发自己的搜索引擎>第二版,邱哲.符滔滔.王学松编著,人民邮电出版社,的随手笔记与猜想.若有不足之处还请不吝赐教,以不断完善之. 搜索引擎与信息检索 信息检索的过程: 构建文 ...

  9. Lucene 入门教程

    了解搜索技术 什么是搜索 简单的说,搜索就是搜寻.查找,在IT行业中就是指用户输入关键字,通过相应的算法,查询并返回用户所需要的信息. 普通的数据库搜索 类似:select * from 表名 whe ...

最新文章

  1. 面试90%都会翻车的高可用+高并发+负载均衡架构设计 !
  2. .net里鼠标选中的text数据怎么获取_怎么利用Excel设置当天生日提醒功能
  3. [UVa10296]Jogging Trails
  4. 【Python学习教程】:装饰器的详细教程,通俗易懂
  5. Codeforces Round #433 (Div. 2, based on Olympiad of Metropolises)
  6. 微服务 第六章 springboot 通过Spring-data-jpa 配置Oracle数据源(简单步骤)
  7. EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因
  8. 今天,送你一份交通行业最全数据集(共享单车、自动驾驶、网约出租车、交通信号识别)
  9. SpringAOP xml 方式和注解简单实现日志处理
  10. 马桶怎么清洗才干净无异味?
  11. OC 方法,继承,特殊方法
  12. 重学C---------第五节:常量
  13. jquery serialize 和 console 漫谈
  14. STM32F103C8T6系统板
  15. 诺奖经济大师,数学天才赌徒,和“神秘的股市财富公式”
  16. linux挂载VMFS硬盘,挂载ESXi服务器VMFS存储卷
  17. 一个web前端专科生面试后的感概
  18. 转发:上海软件公司排行 (估计是2008年的吧)
  19. 五子棋智能算法——决策树编程实现(三)
  20. mac os之监听触摸板(捏合、旋转、三指)

热门文章

  1. 国产ThinkJS 项目构建 Docker 镜像制作与log日志问题
  2. (十)CMake链接已有的动态库
  3. 北京、上海家庭年收入情况统计 (zz)
  4. Android 多屏显示
  5. 零基础无实物一步一步学PLCS7-1200仿真(九)-八位流水灯/跑马灯
  6. java收费学java,讷河学java编程,讷河java编程学习的学校,讷河java编程学习一般怎么收费...
  7. 挡土墙lisp程序_基于Visual LISP与C#的水工挡土墙计算软件开发
  8. Mathematica12 免费安装教程
  9. 1450种时尚排版包装LOGO标题字幕条转场背景图形元素动画V3预设AE脚本PR预设 Motion Bro脚本预设包
  10. 中国营销人的第6项修炼