介绍一款全文搜索引擎–lucene

今天我想给大家介绍的,是一款叫做lucene的开源搜索引擎。它是基于java环境下的,一款全文搜索引擎。如果你需要对超级多的文档进行搜索,可以思考使用它。

介绍一款全文搜索引擎--lucene
lucene进行搜索

1. 通过对目标文档的处理,得到一个新的处理好的index。

这些index是长成这个样子的:

介绍一款全文搜索引擎--lucene

在这里,lucene 所做的事情实则是把这些文档中的话先进行预处理。列如lucene会把”BitTiger” 转换成”bitgtiger” 也就是全部小写化。之后呢,lucene 会为你的文档建立一个matrix。这里我直接开始举例说明。

doc1 : “I love programming”;

doc2: “programming is necessary skills and you should love it “

lucene 会建立如下的索引结构:

term docs location

I 1 1.0

love 1,2 1.2->2.47

programming 1,2 1.7->2.00

skills 2 2.26

and 2 —

you 2 —

it 2 —

is 2 —

term 代表出目前文档中的一个一个词语,docs代表的是这个文档的编号,lcoation代表的是词语出目前文档中的某个位置。在lucene当中,词语的位置是用一个linkedlist 串联起来的。

如果你要对一段文档进行索引,在API,你要做的事情很简单,我在这里直接贴代码

String path = “XXXXX”; ———– 你文档的路径

final Path docDirs = Paths.get(Path);

// 你建立索引的路径

Directory dic_siwei = FSDirectory.open(Paths.get(“你建立一个大索引的路径”));

Analyzer analyzer = new StandardAnalyzer(); —— 构建分析器,它的作用是对文档语言进行处理

//配置索引writer和建立一个索引

IndexWriterConfig conf = new IndexWriterConfig(analyzer);

IndexWriter writer = new IndexWriter(dic_siwei,conf);

Document docs = new Document();

这里docDir是单独一个文件的路径,我省略了之前的一个方法,大家知道就行

InputStream stream = Files.newInputStream(docDir);

doc.add(new TextField(“contents”, new BufferedReader(newInputStreamReader(stream, StandardCharsets.UTF_8))));

writer.close();

这之后,你们就可以创建好一份索引。在这里你会问,如果我的添加了一个新的索引,那么我需不需要重新跑一次我的程序,去建立一个新的索引。在这里,lucene处理的很好。当你有新的文件需要进行处理,lucene提供了一个”updata” 接口可以将你的新内容加入到原来的索引文件中。

2.建立好索引之后如何进行搜索?

我觉得在这里,我想谈谈lucene的打分机制。列如我搜索“dota ti5”,我希望第一个搜索的结果文档叫做”dota2″而不是“英雄联盟(LOL)”.那么lucene是如何做的呢?

lucene 默认的搜索算法叫做TF/IDF 算法。

2.1(TF/IDF 算法)

TF-IDF算法全称为term frequency–inverse document frequency。TF就是term frequency的缩写,意为词频。IDF则是inverse document frequency的缩写,意为逆文档频率。

该算法在信息处理中一般用来抽取关键词。列如,对一个文章提取关键词作为搜索词,就可以采用TF-IDF算法。

要找出一篇文章中的关键词,一般的思路就是,就是找到出现次数最多的词。如果某个词很重大,它应该在这篇文章中多次出现。于是,我们进行”词频”(Term Frequency,缩写为TF)统计。

但是一般,一篇中文的文章中,都会有许多没有实际意义的词,列如“的”,“是”,“了”,这类词是最常用的词,称为停用词,称它们为停用词是由于在文本处理过程中如果遇到它们,则立即停止处理,将其扔掉。将这些词扔掉减少了索引量,增加了检索效率,并且一般都会提高检索的效果。停用词主要包括英文字符、数字、数学字符、标点符号及使用频率特高的单汉字等。

当过滤掉所有的停用词后,剩下的都是实际意义的词,但也不能简单的认为那个词出现的次数多就是关键词。列如在一篇如何组装电脑的文章中,出现“CPU”,“主板”等关键词和出现“说明书”的次数一样多,但很显然,CPU,主板等关键词,更能确定这个文章的特性。也就是说,“CPU”,“主板”等关键词比“说明书”这个关键词更重大,需要排在前面。所以我们就需要一个权重系数,用来调整各个关键词的重大性。如果一个词很少见,但是它在某个文章中反复出现多次,那么可以认为这个词反应了这个文章的特性,可以把它作为关键词。在信息检索中,这个权重超级重大,它决定了关键词的重大度,这个权重叫做”逆文档频率”(Inverse Document Frequency,缩写为IDF),它的大小与一个词的常见程度成反比。

在知道了词频和权重之后,两者相乘,就得到一个词的TF-IDF值,某个词对文章的重大性越高,它的TF-IDF值就越大。所以,排在最前面的几个词,就是这篇文章的关键词。

因此TF-IDF算法的主要工作就是计算出TF*IDF值最大的那几个词,作为文章的关键词。

可是,TF-IDF算法的优点是简单快速,结果比较符合实际情况。缺点是,单纯以”词频”衡量一个词的重大性,不够全面,有时重大的词可能出现次数并不多。而且,这种算法无法体现词的位置信息,出现位置靠前的词与出现位置靠后的词,都被视为重大性一样,这是不正确的。(一种解决方法是,对全文的第一段和每一段的第一句话,给予较大的权重。)

当通过TF-IDF算法找出文章的关键字后,可以运用到一些具体的场景。列如:根据关键字找出类似的文章。

2.2 代码怎么写?

//配置搜索器

IndexReader reade=DirectoryReader.open(FSDirectory.open(Paths.get(“你刚才建立索引的文件夹”)));

IndexSearcher searcher = new IndexSearcher(reader);

Analyzer analyzer = new StandardAnalyzer();

QueryParser parser = new QueryParser(field, analyzer);

Query query = parser.parse(“你要搜索的内容”);

// topDocs 就是就是你要得到的10个评分最高的文档

TopDocs results = searcher.search(query, 10);

2.3 其他算法扩展

如果你认为lucene本身的算法不够好,那么你可以思考去实现其他的算法。列如BM25和BM25F算法。在lucene当中,如果你想更改原本的算法,那么你需要extends原来的Similarity类,然后将它配置到你的索引writer的配置中。如果你需要更好的索引。那么你可能需要为lucene重写许多代码,包括权重包(Weight),Query包(查询),Score包(打分)。

3.小小的展望

这是博主第一次写博客,真的第一次都献给了BitTiger啊有木有!博主表明如果文章写的不好,请见谅啊!

作者:污妖王, 编辑:王思维

更多精彩内容,欢迎访问官网 BitTiger.io 或关注 “论码农的自我修养” 微信公众号:bit_tiger

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容