注(2007-5-22):最新一次更新的时候,我再次研究了一下Lucene,读完了Lucene In Action,并且实际的使用Lucene构建了一个小型的搜索系统之后,我感觉到很惭愧,因为我一直对Lucene有不满的心理,认为它做的不好(可能受了国内的某些使用Lucene构建搜索引擎的网站的影响,因为他们构建的都很差,现在想来,可能是他们和我一样没有真正深入理解Lucene)。现在我才发现,Lucene的作者在大方向上考虑问题的全面比我要好很多(虽然有些功能我不知道是否真的有用)。现在我的感受是:
1)Lucene对查询的理解十分深入,几乎什么样的查询需求它都考虑到了。而对于普通的商业搜索引擎来说(比如,百度),它们只是考虑到了布尔查询模式,远不及Lucene里面的查询方式多; 2)Lucene对过滤和排序的处理已经能够满足90%的要求了。过滤可以把不需要的结果删除,而排序则可以根据某个域的值来进行结果排序。基本的垂直搜索引擎,是必须这些功能的,因为这些功能能够缩小查询的结果集,提高用户体验。而百度等商业搜索引擎显然是不需要(或者没有提供)这些功能的。 3)Lucene的分值计算效果不错。抛开基本的IR的那些标准的分值计算算法不说(谁都知道总体上Lucene使用了简化的向量模型,但实际上Lucene在布尔模型查询上面也使用了简化的扩展布尔模型分值计算公式),Lucene支持了大部分额外的基于经验的分值计算。举例来说,查询“中国北京”的时候,以下是几个文档的实际排序(直接解析这个查询短语是得不到这个结果的,见第4点): 中国北京 4)Lucene不提供真正的查询串解析。基于文法的查询串解析,一个严重的结果就是容错太差,所以,我们几乎可以认为Lucene并不提供实际有用的查询串解析。所以呢,上面我们说的“中国北京”需要您自己把它解析为: PhraseQuery query = new PhraseQuery(); 然后才会有上面的那个结果。所以,使用Lucene的第一步是提供您自己的查询串解析器。 5)理解Lucene的算法限制。Doug Cutting不是神仙,他也无法解决算法的问题,所以呢,几乎所有算法的限制都会在Lucene里面出现,比如,RangeQuery查询速度极慢,Sort排序需要很大的内存来缓冲Field的值。这些并不是Doug Cutting的错,而是算法的限制,我想应该没有人能够解决这类问题吧?(虽然从IR中我们知道RangeQuery可以使用B+树等结构来加快查询,不过,我们似乎不能够责怪Lucene,因为Lucene使用的是紧凑的文件结构,难以支持B+树结构) 如果您真的需要考虑这些问题的话,您可以自己修改Lucene的代码或者提供额外的扩展。 6)理解Lucene的其他限制。在实际应用的过程中,您会发现Lucene有各种各样的限制,在这里,我想提醒您2个问题:a)缓冲同步;b)写/读同步。Lucene的缓冲做的不好,您可以根据实际情况自己扩展,在扩展的时候,请时刻注意缓冲和实际数据同步的问题。写/读同步其实是Lucene自己的问题,在同时读写一个Directory的时候,写的数据并不会马上表现到读上面,所以呢,要么关闭写,要么自己缓冲写结果。 Lucene是一个开源的基于java的搜索引擎,它只包含IR(Information Retrieve)部分。它即不是唯一的也不是最好的一个开源搜索引擎,更好的比如egothor,但是它是文档最全面和受到关注最多的一个。Nutch是基于Lucene并加入了分布式和Crawler部分的搜索引擎。在本文中,作者试图从掌握的知识范围谈论一下它们使用的技术和一般商业文本搜索引擎使用的技术之间的距离。因为作者水平有限,仅仅拥有2年不到的搜索研究和实践经验,不足之处请大家多多指教。谢谢。 1 网络搜索引擎的构架一个专业的网络搜索引擎至少包含3部分,即抓取、处理和搜索。下面是它们的一般功能:
仅仅从搜索引擎的构架来看,Lucene(Nutch)缺失的一环是信息的处理。信息的处理恰恰是整个搜索引擎中最核心的技术。 2 信息抓取网络信息抓取包含了网页抓取、文本文件抓取和其它文件抓取。对于使用http(还有https)等协议的网站来说,信息抓取的主要过程是:
普通的信息抓取一般可以被称为Spider,它利用基本的html页面分析器(比如,HtmlParser、NeckoHtml、JTidy等)来解析html页面,得到页面中的超链接。一般的说,一个Spider由以下2部分组成:
3 信息处理似乎在Lucene(Nutch)面前谈论信息处理显得有点不专业,因为它们压根就不支持。但是,信息处理部分你还是可以自己编写后嵌入到Lucene(Nutch)里面去的。信息处理话题太大,作者没有这个胆量和水平对此妄加谈论,虽然这个是作者一直研究的主要方向。 唯一可以肯定的就是,信息处理需要的知识至少有2点:1,机器学习(ML);2,自然语言理解(NLP)。前者典型的包括SVM、HMM等,后者包括HNC、知网等。笔者自信对ML有一定的理解,但是,对NLP的理解不太深入,还没有形成一个完整的解决方案。 4 信息获取对信息获取的研究已经好多好多年了,多到那个时候作者都未出生。这部分主要分为2个步骤,第一个步骤是把文档填入到数据库(也就是所谓的构建索引);第二个部分就是根据用户输入得到一系列最相关文档(即所谓的搜索)。得到最相关文档无外乎就是比较2个文档的相似度。当用户输入一个字符串(即一个文档)之后,搜索引擎根据这个文档到数据库中寻找和它最相关的文档,然后返回给用户。实际搜索引擎必须考虑速度的问题,不可能像理论上说的那样去做。搜索的时候,一般有如下3步:
5 速度第一对于搜索引擎来说,速度绝对是第一个需要考虑的问题。信息抓取的速度显然不在软件能够解决的范围内,它只能通过增加带宽和多级更新策略来提高了。信息处理的速度不在本文的讨论之列。信息获取的时候,有2个地方需要考虑到速度:
没有引入缓冲是Lucene(Nutch)的另外一个严重失误。在这个构架里面,你可以自己 构建一个查询结果缓冲(一级缓冲),但是,你很难构建一个基于词语的索引缓冲 (二级缓冲)。这对于一个大搜索量的系统来说,是不可想象的。更何况普通商业搜 索引擎还会有第三级缓冲。 6 精度第二如果仅仅从Lucene(Nutch)支持的查询方式和分值计算来看,Lucene(Nutch)不存在精度的问题,因为它们都是计算了全部数据的。商业搜索引擎因为数据量过大的缘故,不得不使用一些估计的算法来减少磁盘数据的读取,这会导致精度的略微丢失。反过来说,Lucene无法支持大规模数据。 7 效率第三这里说的效率主要是空间效率。比如,程序的内存占用和磁盘占用。Lucene使用了zlib压缩技术来压缩文档内容,还有使用了简单的压缩整数的方法。但是,它使用的压缩方法还是太少了,它少用压缩的结果是:1)文件结构和代码简单;2)查询速度变慢;3)索引segment合并快速;4)磁盘占用增加。同时,它几乎不用压缩也和它放弃缓冲有很大联系,因为压缩过的索引很容易放到内存里面,这点十分满足缓冲的空间需求。 |