Lucene简介

Lucent:Apache软件基金会Jakarta项目组的一个子项目,Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。 —— [ 百度百科 ]

数据库索引和Lucene检索对比

比较项 Lucene检索 数据库检索
数据检索 从Lucene的索引文件中检出 由数据库索引检索记录
索引结构 Document(文档) Record(记录)
全文检索 支持 不支持
模糊查询 支持 不支持
结果排序 支持排序 不能排序

Lucene搜索的API类主要有4个 IndexSearch,Query,QueryParser,Hits

Lucene搜索过程

Lucene的索引结构是文档(Document)形式的,下面简单介绍一下Lucene搜索的过程

(1)将文档传给分词组件(Tokenizer),分词组件根据标点符号和停词将文档分成词元(Token),并将标点符号和停词去掉。

停词是指没有特别意思的词。英语的是指比如a、the等等单词

文章1内容:Tom favorite fruit is apple.

经过分词处理后,变成[Tom][facorite][fruit][apple]

(2)再将词元传给语言处理组件(Linguistic Processor)

英语的单词经过语言处理组件处理后,字母变为小写,词元会变成最基本的词根形式,比如likes变成like

经过分词处理后,变成[tom][favorite][fruit][apple]

(3) 然后得到的词元传给索引组件(Indexer),索引组件处理得到索引结构,得到关键字、出现频率、出现位置分别作为词典文件(Term Dictionary)、频率文件(frequencies)和位置文件(positions)保存起来,然后通过二元搜索算法快速查找关键字

关键字 文章号[出现频率] 出现位置
tom 1[1] 1
favorite 1[2] 2
fruit 1[3] 3
[apple 1[4] 4

Lucene简单实例

创建一个Maven项目,在pom.xml加入Lucene所需的jar

<dependencies>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>

创建索引的简单实例

package com.demo.lucene;

import java.io.IOException;
import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer;
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.IntField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; /**
* <pre>
* Lucene创建索引服务类
* </pre>
*
* @author nicky
* @version 1.00.00
*
* <pre>
* 修改记录
* 修改后版本: 修改人: 修改日期:2018年04月18日 修改内容:
* </pre>
*/
@Component
public class LuceneIndexer { private volatile static LuceneIndexer instance; private final static String INDEX_DIR = "D:\\lucene"; private static class SingletonHolder{
private final static LuceneIndexer instance=new LuceneIndexer();
} public static LuceneIndexer getInstance(){
return SingletonHolder.instance;
} public boolean createIndex(String indexDir) throws IOException{
//加点测试的静态数据
Integer ids[] = {1 , 2 , 3};
String titles[] = {"标题1" , "标题2" , "标题3"};
String tcontents[] = {
"内容1内容啊哈哈哈",
"内容2内容啊哈哈哈",
"内容3内容啊哈哈哈"
}; long startTime = System.currentTimeMillis();//记录索引开始时间 Analyzer analyzer = new SmartChineseAnalyzer();
Directory directory = FSDirectory.open(Paths.get(indexDir));
IndexWriterConfig config = new IndexWriterConfig(analyzer); IndexWriter indexWriter = new IndexWriter(directory, config); for(int i = 0; i < ids.length;i++){
Document doc = new Document();
//添加字段
doc.add(new IntField("id", ids[i],Field.Store.YES)); //添加内容
doc.add(new TextField("title", titles[i], Field.Store.YES)); //添加文件名,并把这个字段存到索引文件里
doc.add(new TextField("tcontent", tcontents[i], Field.Store.YES)); //添加文件路径
indexWriter.addDocument(doc);
} indexWriter.commit();
System.out.println("共索引了"+indexWriter.numDocs()+"个文件");
indexWriter.close();
System.out.println("创建索引所用时间:"+(System.currentTimeMillis()-startTime)+"毫秒"); return true;
} public static void main(String[] args) {
try {
boolean r = LuceneIndexer.getInstance().createIndex(INDEX_DIR);
if(r){
System.out.println("索引创建成功!");
}else{
System.out.println("索引创建失败!");
}
} catch (IOException e) {
e.printStackTrace();
} } }

全局搜索索引

package com.demo.lucene;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory; import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Paths; /**
* <pre>
* Lucene全局搜索服务类
* </pre>
*
* @author nicky
* @version 1.00.00
*
* <pre>
* 修改记录
* 修改后版本: 修改人: 修改日期:2018年04月18日 修改内容:
* </pre>
*/
public class SearchBuilder { public static void doSearch(String indexDir , String queryStr) throws IOException, ParseException, InvalidTokenOffsetsException {
Directory directory = FSDirectory.open(Paths.get(indexDir));
DirectoryReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new SmartChineseAnalyzer();
QueryParser parser = new QueryParser("tcontent",analyzer);
Query query = parser.parse(queryStr); long startTime = System.currentTimeMillis();
TopDocs docs = searcher.search(query,10); System.out.println("查找"+queryStr+"所用时间:"+(System.currentTimeMillis()-startTime));
System.out.println("查询到"+docs.totalHits+"条记录"); //遍历查询结果
for(ScoreDoc scoreDoc : docs.scoreDocs){
Document doc = searcher.doc(scoreDoc.doc);
String tcontent = doc.get("tcontent");
if(tcontent != null){
TokenStream tokenStream = analyzer.tokenStream("tcontent", new StringReader(tcontent));
String summary = highlighter.getBestFragment(tokenStream, tcontent);
System.out.println(summary);
}
}
reader.close();
} public static void main(String[] args){
String indexDir = "D:\\lucene";
String q = "内容"; //查询这个字符串
try {
doSearch(indexDir, q);
} catch (Exception e) {
e.printStackTrace();
}
}
}

加入高亮显示:

public class SearchBuilder {

    public static void doSearch(String indexDir , String queryStr) throws IOException, ParseException, InvalidTokenOffsetsException {
Directory directory = FSDirectory.open(Paths.get(indexDir));
DirectoryReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new SmartChineseAnalyzer();
QueryParser parser = new QueryParser("tcontent",analyzer);
Query query = parser.parse(queryStr); long startTime = System.currentTimeMillis();
TopDocs docs = searcher.search(query,10); System.out.println("查找"+queryStr+"所用时间:"+(System.currentTimeMillis()-startTime));
System.out.println("查询到"+docs.totalHits+"条记录"); //加入高亮显示的
SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<b><font color=red>","</font></b>");
QueryScorer scorer = new QueryScorer(query);//计算查询结果最高的得分
Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);//根据得分算出一个片段
Highlighter highlighter = new Highlighter(simpleHTMLFormatter,scorer);
highlighter.setTextFragmenter(fragmenter);//设置显示高亮的片段 //遍历查询结果
for(ScoreDoc scoreDoc : docs.scoreDocs){
Document doc = searcher.doc(scoreDoc.doc);
String tcontent = doc.get("tcontent");
if(tcontent != null){
TokenStream tokenStream = analyzer.tokenStream("tcontent", new StringReader(tcontent));
String summary = highlighter.getBestFragment(tokenStream, tcontent);
System.out.println(summary);
}
}
reader.close();
} public static void main(String[] args){
String indexDir = "D:\\lucene";
String q = "内容"; //查询这个字符串
try {
doSearch(indexDir, q);
} catch (Exception e) {
e.printStackTrace();
}
}
}

查找内容1所用时间:404

查询到3条记录

内容1内容啊哈哈哈

内容2内容啊哈哈哈

内容3内容啊哈哈哈

Lucene重要类解释

IndexWriter:lucene 中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。



Analyzer:分析器,主要用于分析搜索引擎遇到的各种文本。常用的有

StandardAnalyzer

分析器,StopAnalyzer 分析器,WhitespaceAnalyzer 分析器等。



Directory:索引存放的位置;lucene 提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene 提供了FSDirectory 和RAMDirectory 两个类。



Document:文档;Document 相当于一个要进行索引的单元,任何可以想要被索引的文件都

必须转化为Document 对象才能进行索引。



Field:字段。



IndexSearcher:是lucene 中最基本的检索工具,所有的检索都会用到IndexSearcher工具;



Query:查询,lucene 中支持模糊查询,语义查询,短语查询,组合查询等等,如有

TermQuery,BooleanQuery,RangeQuery,WildcardQuery 等一些类。



QueryParser:是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。



Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene 中,搜索的结果的集合是用Hits 类的实例来表示的。

附录

Lucene个版本下载url

Lucene易百教程

Lucene4.x系列教程

Lucene全文搜索教程

Apache Lucene全局搜索引擎入门教程的更多相关文章

  1. Flask+elasticsearch实现搜索引擎入门教程+Curl调试

    前几天,在github上看到了一个关于elasticsearch的小项目,有点小兴趣,于是就结合着Flask,研究了一下,分享给大家. 准备资料: 1.安装elasticsearch 参考教程:htt ...

  2. Apache CXF实现WebService入门教程(附完整源码)

    Apache CXF实现WebService非常简单实用,只需要几步就可以实现一个简单的web service. 首先我们需要新建一个maven项目,在pom中添加依赖和jetty作为测试的web s ...

  3. Apache Flink 零基础入门(转)

    这是一份很好的 Apache Flink 零基础入门教程. Apache Flink 零基础入门(一&二):基础概念解析 Apache Flink 零基础入门(三):开发环境搭建和应用的配置. ...

  4. Lucene入门教程(转载)

    http://blog.csdn.net/tianlincao/article/details/6867127 Lucene教程 1 lucene简介 1.1 什么是lucene     Lucene ...

  5. Apache Solr入门教程(初学者之旅)

    Apache Solr入门教程(初学者之旅) 写在前面:本文涉及solr入门的各方面,建议边思考边实践,相信能帮助你对solr有个清晰全面的了解并能简单实用. 在Apache Solr初学者教程的这个 ...

  6. Lucene搜索引擎入门

    一.什么是全文检索?            就是在检索数据,数据的分类:                在计算机当中,比如说存在磁盘的文本文档,HTML页面,Word文档等等......       ...

  7. Apache搭建http网站服务器入门教程

    Apache搭建http网站服务器入门教程 准备工具 一台带有Linux系统的主机,这里使用CentOS 7.1 64位系统 一个备案过的域名,这里使用www.hellopage.cn 一台可以访问网 ...

  8. Apache Lucene 4.5 发布,Java 搜索引擎

    Apache Lucene 4.5 发布了,该版本提供基于磁盘的文档值以及改进了过滤器的缓存.Lucene 4.5 的文档请看这里. Lucene 是apache软件基金会一个开放源代码的全文检索引擎 ...

  9. Apache Commons IO入门教程(转)

    Apache Commons IO是Apache基金会创建并维护的Java函数库.它提供了许多类使得开发者的常见任务变得简单,同时减少重复(boiler-plate)代码,这些代码可能遍布于每个独立的 ...

随机推荐

  1. spring boot利用controller来测试写的类

    我们在开发spring boot应用程序的时候,往往需要测试某个写好的类,但是在测试的时候发现不太好测试,用Junit等测试框架,总是会报一些问题,大致是找不到配置文件以及无法利用spring创建的对 ...

  2. Heartbeat详解

    转自:http://blog.sina.com.cn/s/blog_7b6fc4c901012om0.html 配置主节点的Heartbeat Heartbeat的主要配置文件有ha.cf.hares ...

  3. Python学习:经典编程例题

    九九乘法表 ,): ,i+): print(i,'*',j,'=',i*j,end='\t') print() 水仙花数问题描述:100-999之间每个数的立方相加等于原数例如:153=1 ^ 3 + ...

  4. 摹客iDoc的PS插件全新改版!—— 智能检测不对应的设计稿

    一.简洁美观——iDoc的PS插件全新界面 iDoc对PS插件的界面进行了全新设计,无论是登录.上传.还是设置界面,都变得更精致.简洁美观,功能分布也非常明确,是一款轻巧且实用的小插件. 二.同步上传 ...

  5. faster-rcnn 笔记

    2019-02-18,15点00 ''' 下面是别人写的原始的笔记,我在上面自己补充了一些. ''' #https://www.cnblogs.com/the-home-of-123/p/974796 ...

  6. 从阿里巴巴面试题到java类加载机制

    首先很经典的阿里巴巴面试题 加上我自己的一些疑惑代码 public class Text { public static int k = 0; public final int k1 = 3; //自 ...

  7. SCUCTF2018web部分wp

    [签到] Web部分的签到题,打开连接后F12审查元素 可以看到有被隐藏起来的JSFuck密码,解码运行后可得flag [计算器] 打开后界面如上图,要求简单来说就是回答20道数学题目,每道题最多3s ...

  8. jsp中的四个作用域,九个内置对象分别是什么?

    九大内置对象: 内置对象(又叫隐含对象),就是在jsp中,不需要创建(由服务器<容器>来创建),可以直接使用的对象. 对象 含义 类 作用域 request 请求对象 类型 javax.s ...

  9. CodeForces - 939A,解题报告

    题意:给出一个n个点有向图,问是否存在三个点,这三个点构成一个回路.n<=5000 模拟即可. 注意是必须三个点 多了居然不行. import java.util.*; public class ...

  10. 别人的Linux私房菜(15)磁盘配额与高级文件系统管理

    磁盘配额在网站.邮件.文件等服务器常见,主要有针对用户.用户组.限制某一目录的的最大磁盘配额. ext文件系统进能针对整个文件系统配额,xfs可以针对目录配额.配额和文件系统有关. 内核必须支持磁盘配 ...