本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
网上搜索了一下关于 Lucene 教程的文章非常多,但是关于 SpringBoot 整合 Lucene 的非常少,可能一些涉及到搜索的项目都比较老,使用 Lucene 的比较少,使用 Solr 和 Elasticsearch 的可能比较多。但是文章少,并不代表没有人用,所以本文我教大家如何把 Lucene 和 SpringBoot 整合到一起。
至于,你们还不懂 Lucene 是什么的,建议看我前面的文章。有详细的教程。
SpringBoot 不论整合什么框架,都是先从 pom.xml 文件开始。同样的整合 Lucene 也需要引入 Lucene 相关的 jar 文件。
<!--对分词索引查询解析--> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>7.1.0</version> </dependency> <!--高亮 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>7.1.0</version> </dependency> <!--smartcn 中文分词器 SmartChineseAnalyzer smartcn分词器 需要lucene依赖 且和lucene版本同步--> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-smartcn</artifactId> <version>7.1.0</version> </dependency> <!--ik-analyzer 中文分词器--> <dependency> <groupId>cn.bestwu</groupId> <artifactId>ik-analyzers</artifactId> <version>5.1.0</version> </dependency> <!--MMSeg4j 分词器--> <dependency> <groupId>com.chenlb.mmseg4j</groupId> <artifactId>mmseg4j-solr</artifactId> <version>2.4.0</version> <exclusions> <exclusion> <groupId>org.apache.solr</groupId> <artifactId>solr-core</artifactId> </exclusion> </exclusions> </dependency>
Lucene 目前还没有提供 SpringBoot 方面的自动配置的 starter,所以引入的 jar 文件可能较多。
实例化 IndexReader 需要加载索引文件,所以实例化它是非常耗资源的。
IndexReader 是线程安全的,通常一个索引目录,我们只实例化一个 IndexReader 就够了。
@Configuration
public class LuceneConfig {
// 创建一个 Analyzer 实例
@Bean
public Analyzer analyzer() {
return new IKAnalyzer(false);
}
// 索引位置
@Bean
public Directory directory() {
return FSDirectory.open(Paths.get("indexDir/"));
}
// 创建 IndexReader
@Bean
public IndexReader indexReader(Directory directory) {
return DirectoryReader.open(directory);
}
// 创建 SearcherManager
@Bean
public SearcherManager searcherManager(Directory directory) throws IOException {
return new SearcherManager(directory, null);
}
// 创建 IndexSearcher
@Bean
public IndexSearcher indexSearcher(IndexReader indexReader){
return new IndexSearcher(indexReader);
}
}
同样的 IndexSearcher 实例一个也就够了。如果不够,可以使用 searcherManager 实例。
searcherManager 实例的用法,一般如下:
@Service
public class XttblogService(){
@Autowired
private SearcherManager searcherManager;
public Set<Map<String, Object>> search(String keyword, int page) {
IndexSearcher searcher = null;
Set<Map<String, Object>> data = newLinkedHashSetWithExpectedSize(DEFAULT_PAGE_SIZE);
try {
searcher = searcherManager.acquire();
BooleanQuery query = ......
......
} catch (IOException e) {
logger.error("acquire beer searcher failed");
logger.error(e.getLocalizedMessage(), e);
} catch (ParseException e) {
logger.error("failed to build query for \"{}\"", keyword);
} finally {
if (searcher != null) {
try {
searcherManager.release(searcher);
} catch (IOException e) {
logger.error("release beer searcher failed");
logger.error(e.getLocalizedMessage(), e);
}
}
}
return data;
}
}
封装好了各个 bean 只有,查询搜索,创建索引,更新,删除索引之类的就非常简单了。
下面看几个贱的查询例子。
**
* 执行查询,并打印查询到的记录数
* @param query
* @throws IOException
*/
public void executeQuery(Query query) throws IOException {
TopDocs topDocs = indexSearcher.search(query, 100);
//打印查询到的记录数
System.out.println("总共查询到" + topDocs.totalHits + "个文档");
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
//取得对应的文档对象
Document document = indexSearcher.doc(scoreDoc.doc);
System.out.println("id:" + document.get("id"));
System.out.println("title:" + document.get("title"));
System.out.println("content:" + document.get("content"));
}
}
/**
* 分词打印
* @param analyzer
* @param text
* @throws IOException
*/
public void printAnalyzerDoc(Analyzer analyzer, String text) throws IOException {
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
try {
tokenStream.reset();
while (tokenStream.incrementToken()) {
System.out.println(charTermAttribute.toString());
}
tokenStream.end();
} finally {
tokenStream.close();
analyzer.close();
}
}
public void indexWriterBook(Book book) throws IOException {
long start = System.currentTimeMillis();
// indexWriterConfig 也可以通过引入的方式来实现
//创建索引写入配置
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
//创建索引写入对象
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
//创建Document对象,存储索引
Document doc = new Document();
int id = 1;
//将字段加入到doc中
doc.add(new IntPoint("id", book.getId()));
doc.add(new StringField("title", book.getTitle(), Field.Store.YES));
doc.add(new TextField("content", book.getContent(), Field.Store.YES));
doc.add(new StoredField("id", book.getId()));
//将doc对象保存到索引库中
indexWriter.addDocument(doc);
indexWriter.commit();
//关闭流
indexWriter.close();
long end = System.currentTimeMillis();
System.out.println("索引花费了" + (end - start) + " 毫秒");
}
public void termQueryTitle(String title) throws IOException {
String searchField = "title";
//这是一个条件查询的api,用于添加条件
TermQuery query = new TermQuery(new Term(searchField, title));
//执行查询,并打印查询到的记录数
executeQuery(query);
}
@Test
public void BooleanQueryTest(String t, String t2) throws IOException {
String searchField1 = "title";
String searchField2 = "content";
Query query1 = new TermQuery(new Term(searchField1, t));
Query query2 = new TermQuery(new Term(searchField2, t2));
BooleanQuery.Builder builder = new BooleanQuery.Builder();
// BooleanClause用于表示布尔查询子句关系的类,
// 包 括:
// BooleanClause.Occur.MUST,
// BooleanClause.Occur.MUST_NOT,
// BooleanClause.Occur.SHOULD。
// 必须包含,不能包含,可以包含三种.有以下6种组合:
//
// 1.MUST和MUST:取得连个查询子句的交集。
// 2.MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。
// 3.SHOULD与MUST_NOT:连用时,功能同MUST和MUST_NOT。
// 4.SHOULD与MUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。
// 5.SHOULD与SHOULD:表示“或”关系,最终检索结果为所有检索子句的并集。
// 6.MUST_NOT和MUST_NOT:无意义,检索无结果。
builder.add(query1, BooleanClause.Occur.SHOULD);
builder.add(query2, BooleanClause.Occur.SHOULD);
BooleanQuery query = builder.build();
//执行查询,并打印查询到的记录数
executeQuery(query);
}
看吧,整合 SpringBoot 也是非常的简单。并没有大家想象的那么难。

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » Lucene 实战教程第十六章 SpringBoot 整合 Lucene