随笔分类 -  Lucene原理与代码分析

摘要:2.4、搜索查询对象 2.4.1.2、创建Weight对象树 BooleanQuery.createWeight(Searcher) 最终返回return new BooleanWeight(searcher),BooleanWeight构造函数的具体实现如下: public BooleanWeight(Searcher searcher) { this.similarity = getSimilarity(searcher); weights = new ArrayList<Weight>(clauses.size()); //也是一个递归的过程,沿着新的Query对象树一... 阅读全文
posted @ 2010-04-04 17:53 刘超觉先 阅读(5777) 评论(4) 推荐(0) 编辑
摘要:2.3、QueryParser解析查询语句生成查询对象代码为:QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, "contents", new StandardAnalyzer(Version.LUCENE_CURRENT)); Query query = parser.parse("+(+apple* -boy) (cat* dog) -(eat~ foods)");此过程相对复杂,涉及JavaCC,QueryParser,分词器,查询语法等,本章不会详细论述,会在后面的章节中一一 阅读全文
posted @ 2010-04-04 17:40 刘超觉先 阅读(7006) 评论(3) 推荐(1) 编辑
摘要:二、Lucene搜索详细过程 为了解析Lucene对索引文件搜索的过程,预先写入索引了如下几个文件: file01.txt: apple apples cat dog file02.txt: apple boy cat category file03.txt: apply dog eat etc file04.txt: apply cat foods 2.1、打开IndexReader指向索引文件夹 代码为: IndexReader reader = IndexReader.open(FSDirectory.open(indexDir)); 其实是调用了DirectoryReader.open 阅读全文
posted @ 2010-04-04 17:31 刘超觉先 阅读(7789) 评论(0) 推荐(0) 编辑
摘要:一、Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程。 其可用如下图示: 总共包括以下几个过程: IndexReader打开索引文件,读取并打开指向索引文件的流。 用户输入查询语句 将查询语句转换为查询对象Query对象树 构造Weight对象树,用于计算词的权重Term Weight,也即计算打分公式中与仅与搜索语句相关与文档无关的部分(红色部分)。 构造Scorer对象树,用于计算打分(TermScorer.score())。 在构造Scorer对象树的过程中,其叶子节点... 阅读全文
posted @ 2010-04-04 17:27 刘超觉先 阅读(8910) 评论(1) 推荐(1) 编辑
摘要:在进行Lucene的搜索过程解析之前,有必要单独的一张把Lucene score公式的推导,各部分的意义阐述一下。因为Lucene的搜索过程,很重要的一个步骤就是逐步的计算各部分的分数。 Lucene的打分公式非常复杂,如下: 在推导之前,先逐个介绍每部分的意义: t:Term,这里的Term是指包含域信息的Term,也即title:hello和content:hello是不同的Term coord(q,d):一次搜索可能包含多个搜索词,而一篇文档中也可能包含多个搜索词,此项表示,当一篇文档中包含的搜索词越多,则此文档则打分越高。 queryNorm(q):计算每个查询条目的方差和,... 阅读全文
posted @ 2010-03-07 00:18 刘超觉先 阅读(18188) 评论(10) 推荐(7) 编辑
摘要:一、段合并过程总论 IndexWriter中与段合并有关的成员变量有: HashSet<SegmentInfo> mergingSegments = new HashSet<SegmentInfo>(); //保存正在合并的段,以防止合并期间再次选中被合并。 MergePolicy mergePolicy = new LogByteSizeMergePolicy(this);//合并策略,也即选取哪些段来进行合并。 MergeScheduler mergeScheduler = new ConcurrentMergeScheduler();//段合并器,背后有一个线程负 阅读全文
posted @ 2010-03-06 00:49 刘超觉先 阅读(15008) 评论(1) 推荐(3) 编辑
摘要:本系列文章将详细描述几乎最新版本的Lucene的基本原理和代码分析。其中总体架构和索引文件格式是Lucene 2.9的,索引过程分析是Lucene 3.0的。鉴于索引文件格式没有太大变化,因而原文没有更新,原理和架构的文章中引用了前辈的一些图,可能属于早期的Lucene,但不影响对原理和架构的理解。本系列文章尚在撰写之中,将会有分词器,段合并,QueryParser,查询语句与查询对象,搜索过程,打分公式的推导等章节。提前给大家分享,希望大家批评指正。Lucene学习总结之一:全文检索的基本原理http://www.cnblogs.com/forfuture1978/archive/2009/ 阅读全文
posted @ 2010-02-22 20:25 刘超觉先 阅读(8975) 评论(8) 推荐(7) 编辑
摘要:在索引阶段设置Document Boost和Field Boost,存储在(.nrm)文件中。 如果希望某些文档和某些域比其他的域更重要,如果此文档和此域包含所要查询的词则应该得分较高,则可以在索引阶段设定文档的boost和域的boost值。 这些值是在索引阶段就写入索引文件的,存储在标准化因子(.nrm)文件中,一旦设定,除非删除此文档,否则无法改变。 如果不进行设定,则Document Boost和Field Boost默认为1。 Document Boost及FieldBoost的设定方式如下: Document doc = new Document(); Field f = n... 阅读全文
posted @ 2010-02-08 23:44 刘超觉先 阅读(5421) 评论(2) 推荐(0) 编辑
摘要:问题: 在你的文章中提到了: 于是我们把所有此文档中词(term)的权重(term weight) 看作一个向量。 Document = {term1, term2, …… ,term N} Document Vector = {weight1, weight2, …… ,weight N} 同样我们把查询语句看作一个简单的文档,也用向量来表示。 Query = {term1, term 2, …… , term N} Query Vector = {weight1, weight2, …… , weight N} 于是我们把所有此文档中词(term)的权重(term weight... 阅读全文
posted @ 2010-02-06 13:05 刘超觉先 阅读(5214) 评论(0) 推荐(1) 编辑
摘要:问题: 我试验了一下文章中提到的 stemming 和 lemmatization 将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming。 将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization。 试验没有成功 代码如下: public class TestNorms { public void createIndex() throws IOException { Directory d = new SimpleFSDirectory(new File("d:/falconTest/lucene3/... 阅读全文
posted @ 2010-02-06 13:04 刘超觉先 阅读(6049) 评论(1) 推荐(0) 编辑
摘要:6、关闭IndexWriter对象 代码: writer.close(); --> IndexWriter.closeInternal(boolean) --> (1) 将索引信息由内存写入磁盘: flush(waitForMerges, true, true); --> (2) 进行段合并: mergeScheduler.merge(this); 对段的合并将在后面的章节进行讨论,此处仅仅讨论将索引信息由写入磁盘的过程。 代码: IndexWriter.flush(boolean triggerMerge, boolean flushDocStores, boole... 阅读全文
posted @ 2010-02-02 02:02 刘超觉先 阅读(6268) 评论(5) 推荐(3) 编辑
摘要:5、DocumentsWriter对CharBlockPool,ByteBlockPool,IntBlockPool的缓存管理 在索引的过程中,DocumentsWriter将词信息(term)存储在CharBlockPool中,将文档号(doc ID),词频(freq)和位置(prox)信息存储在ByteBlockPool中。 在ByteBlockPool中,缓存是分块(slice)分配的,块(slice)是分层次的,层次越高,此层的块越大,每一层的块大小事相同的。 nextLevelArray表示的是当前层的下一层是第几层,可见第9层的下一层还是第9层,也就是说最高有9层。 le... 阅读全文
posted @ 2010-02-02 02:01 刘超觉先 阅读(6475) 评论(1) 推荐(2) 编辑
摘要:3、将文档加入IndexWriter 代码: writer.addDocument(doc); -->IndexWriter.addDocument(Document doc, Analyzer analyzer) -->doFlush = docWriter.addDocument(doc, analyzer); --> DocumentsWriter.updateDocument(Document, Analyzer, Term) 注:--> 代表一级函数调用 IndexWriter继而调用DocumentsWriter.addDocument,其又调用Docume 阅读全文
posted @ 2010-02-02 01:59 刘超觉先 阅读(10868) 评论(1) 推荐(2) 编辑
摘要:对于Lucene的索引过程,除了将词(Term)写入倒排表并最终写入Lucene的索引文件外,还包括分词(Analyzer)和合并段(merge segments)的过程,本次不包括这两部分,将在以后的文章中进行分析。 Lucene的索引过程,很多的博客,文章都有介绍,推荐大家上网搜一篇文章:《Annotated Lucene》,好像中文名称叫《Lucene源码剖析》是很不错的。 想要真正了解Lucene索引文件过程,最好的办法是跟进代码调试,对着文章看代码,这样不但能够最详细准确的掌握索引过程(描述都是有偏差的,而代码是不会骗你的),而且还能够学习Lucene的一些优秀的实现,能够在以后的工 阅读全文
posted @ 2010-02-02 01:58 刘超觉先 阅读(20859) 评论(3) 推荐(2) 编辑
摘要:四、具体格式 4.2. 反向信息 反向信息是索引文件的核心,也即反向索引。 反向索引包括两部分,左面是词典(Term Dictionary),右面是倒排表(Posting List)。 在Lucene中,这两部分是分文件存储的,词典是存储在tii,tis中的,倒排表又包括两部分,一部分是文档号及词频,保存在frq中,一部分是词的位置信息,保存在prx中。 Term Dictionary (tii, tis) –> Frequencies (.frq) –> Positions (.prx) 4.2.1. 词典(tis)及词典索引(tii)信息 在词典中,所有的词是按照字典顺序... 阅读全文
posted @ 2010-02-02 01:43 刘超觉先 阅读(15297) 评论(2) 推荐(3) 编辑
摘要:四、具体格式 上面曾经交代过,Lucene保存了从Index到Segment到Document到Field一直到Term的正向信息,也包括了从Term到Document映射的反向信息,还有其他一些Lucene特有的信息。下面对这三种信息一一介绍。 4.1. 正向信息 Index –> Segments (segments.gen, segments_N) –> Field(fnm, fdx, fdt) –> Term (tvx, tvd, tvf) 上面的层次结构不是十分的准确,因为segments.gen和segments_N保存的是段(segment)的元数据信息(met 阅读全文
posted @ 2009-12-14 12:35 刘超觉先 阅读(26428) 评论(4) 推荐(5) 编辑
摘要:Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙。 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程,就是按照全文检索的基本过程,将倒排表写成此文件格式的过程。 Lucene的搜索过程,就是按照此文件格式将索引进去的信息读出来,然后计算每篇文档打分(score)的过程。 本文详细解读了Apache Lucene - Index File Formats(http://lucene.apache.org/java/2_9_0/fileformats.html) 这篇文章。 一、基本概念 下图... 阅读全文
posted @ 2009-12-14 12:34 刘超觉先 阅读(56199) 评论(9) 推荐(12) 编辑
摘要:Lucene总的来说是: 一个高效的,可扩展的,全文检索库。 全部用Java实现,无须配置。 仅支持纯文本文件的索引(Indexing)和搜索(Search)。 不负责由其他格式的文件抽取纯文本文件,或从网络中抓取文件的过程。 在Lucene in action中,Lucene 的构架和过程如下图, 说明Lucene是有索引和搜索的两个过程,包含索引创建,索引,搜索三个要点。 让我们更细一些看Lucene的各组件: 被索引的文档用Document对象表示。 IndexWriter通过函数addDocument将文档添加到索引中,实现创建索引的过程。 Lucene的... 阅读全文
posted @ 2009-12-14 12:32 刘超觉先 阅读(27496) 评论(4) 推荐(13) 编辑
摘要:全文检索大体分两个过程,索引创建(Indexing)和搜索索引(Search)。 * 索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。 * 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。 于是全文检索就存在三个重要问题: 1. 索引里面究竟存些什么?(Index) 2. 如何创建索引?(Indexing) 3. 如何对索引进行搜索?(Search) 阅读全文
posted @ 2009-12-14 12:31 刘超觉先 阅读(71003) 评论(55) 推荐(56) 编辑