前段时间在GitHub克隆了一个SSM的博客的项目,上面用到了Lucene。觉得以后用到的地方可能比较多,于是花了点时间大致了解了一下,总结一下了解的。
Lucene是apache的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
上面是百度百科的简介,简单的说,Lucene是一个开放源代码的全文检索引擎工具包。
使用Lucene之前,先来了解一下数据的分类,一般数据分为两类:
针对两种不同的数据,也有两种搜索方式:
由于Lucene的是非结构化数据,所以讲一下非结构化搜索使用的方法,一般也是两种:
参考这篇博客。
将原文档传给分词组件(Tokenizer):分词组件(Tokenizer)会做以下几件事情( 此过程称为Tokenize) :
1.将文档分成一个一个单独的单词。
2.去除标点符号。
3.去除停词(Stop word) 。
所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,英语中停词如:“the”,“a”,“this”等。经过分词(Tokenizer) 后得到的结果称为词元(Token) 。
在我们的例子中,得到以下词元(Token):
文档一:[Tom] [lives] [Shanghai] [I] [live] [Shanghai]
文档二:[My] [friends] [very] [friendly] [me]
将得到的词元(Token)传给语言处理组件(Linguistic Processor):语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处理。对于英语,语言处理组件(Linguistic Processor) 一般做以下几点:
文档一:[tom] [live] [shanghai] [i] [live] [shanghai]
文档二:[my] [friend] [very] [friendly] [me]
最后,将得到的词(Term)传给索引组件(Indexer),索引组件(Indexer)主要做以下几件事情:
在这幅图中,对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),从而词(Term)后面的文档链表总共有两项,第一项表示包含“allow”的第一篇文档,即1号文档,此文档中,“allow”出现了2次,第二项表示包含“allow”的第二个文档,是2号文档,此文档中,“allow”出现了1次。
以上就是全文检索使用的原理。Lucene也就是使用这个。
可以通过查看官方文档来了解各个包的使用,这里我借用了别人对于包的介绍。
借用了这个博客的内容,因为解释的比较详细,且对于每个类需要的都说的很清楚。
Field 一个Document可以包含多个信息域,比如一篇文章可以包含“标题”、“正文”等信息域,这些信息域就是通过Field在Document中存储的。
是否分析: 是否对域的内容进行分词处理;
是否索引: 将 Field 分析后的词或整个 Field 值进行索引,只有建立索引,才能搜索到;
是否存储: 存储在文档中的 Field 才可以从 Document 中获取;
Field有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个Field进行存储;通过索引属性你可以控制是否对该Field进行索引。这看起来似乎有些废话,事实上对这两个属性的正确组合很重要,假设有一篇文章,我们需要对标题和正文进行全文搜索,所以我们要把索引属性设置为true,同时我们希望能直接从搜索结果中提取文章标题,所以我们把标题域的存储属性设置为true,但是由于正文域太大了,我们为了缩小索引文件大小,将正文域的存储属性设置为false,当需要时再直接读取文件;我们只是希望能从搜索结果中提取最后修改时间,不需要对它进行搜索,所以我们把最后修改时间域的存储属性设置为true,索引属性设置为false。上面的三个域涵盖了两个属性的三种组合,还有一种全为false的没有用到,事实上Field不允许你那么设置,因为既不存储又不索引的域是没有意义的。
IndexSearcher 是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具。
一般是:
下面给出代码,首先使用maven导入所需要的jar包。
<dependencies>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-coreartifactId>
<version>5.3.1version>
dependency>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-queryparserartifactId>
<version>5.3.1version>
dependency>
<dependency>
<groupId>org.apache.lucenegroupId>
<artifactId>lucene-analyzers-commonartifactId>
<version>5.3.1version>
dependency>
dependencies>
下面是代码:
public class IndexingTest1 {
private Directory dir; //存放索引的位置
//准备用来测试的数据
private String ids[] = {"1", "2", "3"}; //用来标识文档
private String dates[] = {"yesterday", "today", "tomorrow"};
private String descs[] = {
"It was a rainy day yesterday",
"It's cloudy today",
"Tomorrow is sunny."};
//生成索引
@Test
public void index() throws Exception{
IndexWriter writer = getWriter();
for(int i = 0; i < ids.length; i++){
Document document = new Document();
document.add(new StringField("id", ids[i], Field.Store.YES));
document.add(new StringField("date", dates[i], Field.Store.YES));
document.add(new TextField("desc", descs[i], Field.Store.YES));
writer.addDocument(document);
}
writer.close(); //close了才真正写到文档中
}
//获取IndexWriter实例
public IndexWriter getWriter() throws Exception{
dir = FSDirectory.open(Paths.get("D:\\resource"));
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
IndexWriter writer = new IndexWriter(dir,config);
return writer;
}
}
以上是,认识Lucene以及简单创建索引的过程。
希望对你有帮助,如有疑问或见解,欢迎提出,共同进步。