Lucene 的索引排序是使用了倒排序原理。 该结构及相应的生成算法如下: 设有两篇文章1和2 文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too. 文章2的内容为:He once lived in Shanghai. 1. 由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施 a. 我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。 b. 文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义, 这些不代表概念的词可以过滤掉,这个也就是在《Lucene详细分析》中所讲的StopTokens c. 用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。 d. 用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live” e. 文章中的标点符号通常不表示某种概念,也可以过滤掉,在lucene中以上措施由Analyzer类完成,经过上面处理后: 文章1的所有关键词为:[tom] [live] [guangzhou] [live] [guangzhou] 文章2的所有关键词为:[he] [live] [shanghai] 2. 有了关键词后,我们就可以建立倒排索引了 上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。文章1,2经过倒排后变成 <!--[if !supportLineBreakNewLine]--> 关键词 文章号 guangzhou 1 he 2 i 1 live 1,2 shanghai 2 tom 1 通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene中记录的就是这种位置。 加上“出现频率”和“出现位置”信息后,我们的索引结构变为: 关键词 文章号[出现频率] 出现位置 guangzhou 1[2] 3,6 he 2[1] 1 i 1[1] 4 live 1[2],2[1] 2,5,2 shanghai 2[1] 3 tom 1[1] 1 以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。 以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。 实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。 Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。 为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,压缩后保存7(只用一个字节)。 下面我们可以通过对该索引的查询来解释一下为什么要建立索引。 假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。 而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。3.2. Lucene的相关度积分公式 score_d = sum_t(tf_q * idf_t / norm_q * tf_d * idf_t / norm_d_t * boost_t) * coord_q_d 注解: score_d : 该文档d的得分 sum_t : 所有项得分的总和 tf_q : 查询串q中,某个项出项的次数的平方根 tf_d : 文档d中 ,出现某个项的次数的平方根 numDocs : 在这个索引里,找到分数大于0的文档的总数 docFreq_t : 包含项t的文档总数 idf_t : log(numDocs/docFreq+1)+1.0 norm_q : sqrt(sum_t((tf_q*idf_t)^2)) norm_d_t : 在文档d中,与项t相同的域中,所有的项总数的平方根 boost_t : 项t的提升因子,一般为 1.0 coord_q_d : 在文档d中,命中的项数量除以查询q的项总数 3.3. Lucene的其他特性 3.3.1. Boosting特性 luncene对Document和Field提供了一个可以设置的Boosting参数, 这个参数的用处是告诉lucene, 某些记录更重要,在搜索的时候优先考虑他们 比如在搜索的时候你可能觉得几个门户的网页要比垃圾小站更优先考虑 lucene默认的boosting参数是1.0, 如果你觉得这个field重要,你可以把boosting设置为1.5, 1.2....等, 对Document设置boosting相当设定了它的每个Field的基准boosting,到时候实际Field的boosting就是(Document-boosting*Field-boosting)设置了一遍相同的boosting. 似乎在lucene的记分公式里面有boosting参数,不过我估计一般人是不会去研究他的公式的(复杂),而且公式也无法给出最佳值,所以我们所能做的只能是一点一点的改变boosting, 然后在实际检测中观察它对搜索结果起到多大的作用来调整 一般的情况下是没有必要使用boosting的, 因为搞不好你就把搜索给搞乱了, 另外如果是单独对Field来做Bossting, 也可以通过将这个Field提前来起到近似的效果 3.3.2. Indexing Date 日期是lucene需要特殊考虑的地方之一, 因为我们可能需要对日期进行范围搜索, Field.keyword(string,Date)提供了这样的方法,lucene会把这个日期转换为string, 值得注意的是这里的日期是精确到毫秒的,可能会有不必要的性能损失, 所以我们也可以把日期自行转化为YYYYMMDD这样的形势,就不用精确到具体时间了,通过File.keyword(Stirng,String) 来index, 使用PrefixQuery 的YYYY一样能起到简化版的日期范围搜索(小技巧), lucene提到他不能处理1970年以前的时间,似乎是上一代电脑系统遗留下来的毛病 3.3.3. Indexing 数字 如果数字只是简单的数据, 比如中国有56个民族. 那么可以简单的把它当字符处理 如果数字还包含数值的意义,比如价格, 我们会有范围搜索的需要(20元到30元之间的商品),那么我们必须做点小技巧, 比如把3,34,100 这三个数字转化为003,034,100 ,因为这样处理以后, 按照字符排序和按照数值排序是一样的,而lucene内部按照字符排序,003->034->100 NOT(100->3->34) 3.3.4. 排序 Lucene默认按照相关度(score)排序,为了能支持其他的排序方式,比如日期,我们在add Field的时候,必须保证field被Index且不能被tokenized(分词),并且排序的只能是数字,日期,字符三种类型之一 3.3.5. Lucene的IndexWriter调整 IndexWriter提供了一些参数可供设置,列表如下 属性 默认值 说明 mergeFactor org.apache.lucene.mergeFactor 10 控制index的大小和频率,两个作用 maxMergeDocs org.apache.lucene.maxMergeDocs Integer.MAX_ 限制一个段中的document数目 minMergeDocs org.apache.lucene.minMergeDocs 10 缓存在内存中的document数目,超过他以后会写入到磁盘 maxFieldLength 1000 一个Field中最大Term数目,超过部分忽略,不会index到field中,所以自然也就搜索不到 这些参数的的详细说明比较复杂:mergeFactor有双重作用 设置每mergeFactor个document写入一个段,比如每10个document写入一个段 设置每mergeFacotr个小段合并到一个大段,比如10个document的时候合并为1小段,以后有10个小段以后合并到一个大段,有10个大段以后再合并,实际的document数目会是mergeFactor的指数 简单的来说mergeFactor 越大,系统会用更多的内存,更少磁盘处理,如果要打批量的作index,那么把mergeFactor设置大没错, mergeFactor 小了以后, index数目也会增多,searhing的效率会降低, 但是mergeFactor增大一点一点,内存消耗会增大很多(指数关系),所以要留意不要"out of memory" 把maxMergeDocs设置小,可以强制让达到一定数量的document写为一个段,这样可以抵消部分mergeFactor的作用. minMergeDocs相当于设置一个小的cache,第一个这个数目的document会留在内存里面,不写入磁盘。这些参数同样是没有最佳值的, 必须根据实际情况一点点调整。 maxFieldLength可以在任何时刻设置, 设置后,接下来的index的Field会按照新的length截取,之前已经index的部分不会改变。可以设置为Integer.MAX_ 3.3.6. RAMDirectory 和 FSDirectory 转化 RAMDirectory(RAMD)在效率上比FSDirectyr(FSD)高不少, 所以我们可以手动的把RAMD当作FSD的buffer,这样就不用去很费劲的调优FSD那么多参数了,完全可以先用RAM跑好了index, 周期性(或者是别的什么算法)来回写道FSD中。 RAMD完全可以做FSD的buffer。 3.3.7. 为查询优化索引(index) Indexwriter.optimize()方法可以为查询优化索引(index),之前提到的参数调优是为indexing过程本身优化,而这里是为查询优化,优化主要是减少index文件数,这样让查询的时候少打开文件,优化过程中,lucene会拷贝旧的index再合并,合并完成以后删除旧的index,所以在此期间,磁盘占用增加, IO符合也会增加,在优化完成瞬间,磁盘占用会是优化前的2倍,在optimize过程中可以同时作search。 3.3.8. 并发操作Lucene和locking机制 v 所有只读操作都可以并发 v 在index被修改期间,所有只读操作都可以并发 v 对index修改操作不能并发,一个index只能被一个线程占用 v index的优化,合并,添加都是修改操作 v IndexWriter和IndexReader的实例可以被多线程共享,他们内部是实现了同步,所以外面使用不需要同步 3.3.9. Locing lucence内部使用文件来locking, 默认的locking文件放在java.io.tmpdir,可以通过-Dorg.apache.lucene.lockDir=xxx指定新的dir,有write.lock commit.lock两个文件,lock文件用来防止并行操作index,如果并行操作, lucene会抛出异常,可以通过设置-DdisableLuceneLocks=true来禁止locking,这样做一般来说很危险,除非你有操作系统或者物理级别的只读保证,比如把index文件刻盘到CDROM上。
|
- 浏览: 1741257 次
最新评论
-
xinglianxlxl:
有空看看,谢谢
eclipse经常未响应优化 -
code_xiaoke:
我觉得Lucene版本变化太大!! 对于版本的变动 太巨大了 ...
Lucene使用IKAnalyzer分词实例 及 IKAnalyzer扩展词库 -
jayant-xu:
...
BigDecimal加减乘除运算 -
jayant-xu:
[img][/img]大大
BigDecimal加减乘除运算 -
jayant-xu:
[*]案说法是否
BigDecimal加减乘除运算
相关推荐
以上就是关于“Lucene索引的简单使用”的详细介绍,包括其核心概念、创建和查询索引的步骤以及一些高级特性。希望对你理解和应用Lucene有所帮助。在实际开发中,可以根据需求选择合适的Analyzer,优化索引策略,以...
- 使用倒排索引(inverted index)来加速字段值的查找,特别是对于大数据量的场景。 - 在索引构建阶段,预处理排序字段,如将日期转换为整数(如毫秒值),以提高比较效率。 总的来说,理解并掌握 Lucene 自定义...
本文将围绕“lucene索引查看程序及代码”这一主题,详细探讨其工作原理、主要功能以及使用方法。 首先,我们要了解什么是Lucene索引。Lucene的索引是一种倒排索引,它通过分析文档内容,将每个单词映射到包含该单词...
以下是对Lucene索引机制的详细解析: 一、Lucene的索引过程 1. 文档分析:当向Lucene添加文档时,首先会经过一个分词器(Tokenizer),将文本拆分成一系列的词项(Token)。接着,这些词项会被过滤(Filter)和...
**Lucene索引和查询** Lucene是Apache软件基金会的开放源码全文搜索引擎库,它提供了文本检索的核心工具,使得开发者能够快速构建自己的搜索应用。本项目中的代码旨在展示如何利用Lucene对多个文件夹下的数据进行...
创建Lucene索引主要包括以下几个步骤: 1. **创建Analyzer**:Analyzer负责分词,即将输入的文本拆分成一个个有意义的词语。根据语言特性,可以选择不同的Analyzer,如StandardAnalyzer(默认)适用于英文,...
了解这些文件格式后,我们还要知道Lucene索引中使用的基本数据类型,如Byte、UInt32、UInt64和VInt。VInt是一种变长整数类型,它根据数值大小动态占用字节,有效地节省了存储空间。 总的来说,Lucene的索引文件格式...
- 创建索引时,Lucene会分解文本,进行词法分析(如使用CJKAnalyzer针对中日韩语言),并构建索引结构。 **基于索引搜索**: - 使用Lucene提供的类,如`IndexReader`和`IndexSearcher`,可以查询索引。 - 搜索结果...
例如,下面的代码演示如何使用 Lucene 对搜索结果进行排序: ```csharp Sort sort = new Sort(new SortField("name", SortField.STRING)); TopDocs topDocs = searcher.Search(query, sort); ``` 在上面的代码中,...
本资料主要探讨了Lucene中的排序、过滤和分页技术,这些都是构建高效、实用的信息检索系统的重要组成部分。 **排序(Sorting)** 排序是Lucene中的一项核心功能,允许我们根据文档的某个或多个字段来对搜索结果...
《深入理解Lucene排序机制:从关键词...通过理解Lucene的排序原理,我们可以更有效地调整搜索结果的展示,提升用户体验。同时,`pom.xml`文件在项目管理中的角色不容忽视,它是保证代码依赖关系正常运作的关键部分。
7. **倒排索引**:Lucene的核心是倒排索引,它允许快速定位含有特定术语的文档,极大提高了搜索效率。 ### 四、应用示例 例如,假设你正在构建一个博客平台,可以使用Lucene来实现全文检索功能。每个博客文章作为...
**Lucene全文索引原理** Lucene是一款开源的全文搜索引擎库,由Apache软件基金会开发,广泛应用于各种信息检索系统。它的核心功能是构建高效的全文索引,并提供快速的文本搜索能力。Lucene的工作原理主要涉及以下几...
在实际操作中,确保你已经正确地将需要排序的字段在索引时存储下来,因为只有被存储的字段才能在排序时使用。同时,注意优化排序性能,避免全字段回溯,尤其是在处理大量数据时。 最后,了解并掌握`Analyzer`的使用...
**luke-7.1.0:Lucene索引查看工具详解** Luke是Apache Lucene项目的一个重要辅助工具,主要用于查看、分析和测试Lucene创建的索引。这个7.1.0版本提供了对Lucene索引的强大洞察力,帮助开发者、搜索引擎优化者以及...
`索引.ppt`这样的文件可能是对Lucene索引原理的详细讲解,可能包含了PPT演示,涵盖了上述概念并可能提供了实例代码和案例分析。 总之,Lucene是一个强大的全文检索工具,它的索引机制是实现高效搜索的关键。通过...
### Lucene索引过程分析 索引过程涉及多个步骤: 1. **创建IndexWriter对象**:用于管理和控制索引的写入操作。 2. **创建文档和字段**:定义文档结构,包括字段类型和内容。 3. **文档添加**:将文档添加到...
总结起来,Lucene索引数据分析器是开发人员的强大工具,它通过`IndexAPI.dll`提供的接口对文本进行高效索引,使用`IndexReader.exe`进行数据查询,最终以表格形式展示结果,便于开发者理解和利用数据。通过深入理解...
在提供的"lucene4.3"压缩包中,可能包含了一个示例程序,演示了如何设置索引以存储地理位置信息,以及如何执行地理空间查询并按距离排序结果。这个例子可能涵盖了创建`Point`字段,构建查询,计算距离以及设置排序...