﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-我的小船停在代码的海洋中...-随笔分类-搜索引擎</title><link>http://www.blogjava.net/machilansing/category/14202.html</link><description>Lansing--Coding 不是梦
</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 15:57:51 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 15:57:51 GMT</pubDate><ttl>60</ttl><item><title>Lucene In Action Ch6 笔记</title><link>http://www.blogjava.net/machilansing/archive/2007/01/05/91910.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Fri, 05 Jan 2007 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2007/01/05/91910.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/91910.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2007/01/05/91910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/91910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/91910.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Lucene In Action ch 6(I) 				笔记 --自定义排序								----- 2006-2-16      								使用				Lucene				来搜索内容,搜索结果的显示顺序当然是比较重要的.Lucene中Build-in的几个排序定义在大多数情况下是不适合我们使用的.要适合自己的应用程序的场景,就只能自定义排序功能,本节...&nbsp;&nbsp;<a href='http://www.blogjava.net/machilansing/archive/2007/01/05/91910.html'>阅读全文</a><img src ="http://www.blogjava.net/machilansing/aggbug/91910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2007-01-05 10:27 <a href="http://www.blogjava.net/machilansing/archive/2007/01/05/91910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene In Action Ch4 笔记</title><link>http://www.blogjava.net/machilansing/archive/2007/01/05/91906.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Fri, 05 Jan 2007 02:14:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2007/01/05/91906.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/91906.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2007/01/05/91906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/91906.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/91906.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Lucene In Action ch 4 				笔记(I) -- Analysis								----- 2006-2-12								本章详细的讨论了 Lucene的分析处理过程和几个Analyzer. 								在indexing过程中要把需要indexing的text分析处理一下, 经过处理和切词 然后建立index. 而不通的Ana...&nbsp;&nbsp;<a href='http://www.blogjava.net/machilansing/archive/2007/01/05/91906.html'>阅读全文</a><img src ="http://www.blogjava.net/machilansing/aggbug/91906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2007-01-05 10:14 <a href="http://www.blogjava.net/machilansing/archive/2007/01/05/91906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene In Action Ch3 笔记</title><link>http://www.blogjava.net/machilansing/archive/2007/01/05/91905.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Fri, 05 Jan 2007 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2007/01/05/91905.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/91905.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2007/01/05/91905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/91905.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/91905.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1. 				实现一个简单的search feature								   				在本章中只限于讨论简单Lucene 搜索API, 有下面几个相关的类:								 Lucene 				基本搜索API:																																												类													...&nbsp;&nbsp;<a href='http://www.blogjava.net/machilansing/archive/2007/01/05/91905.html'>阅读全文</a><img src ="http://www.blogjava.net/machilansing/aggbug/91905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2007-01-05 10:11 <a href="http://www.blogjava.net/machilansing/archive/2007/01/05/91905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene In Action Ch2 笔记</title><link>http://www.blogjava.net/machilansing/archive/2007/01/05/91904.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Fri, 05 Jan 2007 02:10:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2007/01/05/91904.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/91904.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2007/01/05/91904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/91904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/91904.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Lucene In Action ch2 				系统的讲解了 indexing,下面就来看看吧.								1,indexing				的处理过程.								  				首先要把indexing的数据转换为text,因为Lucene只能索引text,然后由Analysis来过虑text,把一些ch1中提到的所谓的stop words 过滤掉, 然后建...&nbsp;&nbsp;<a href='http://www.blogjava.net/machilansing/archive/2007/01/05/91904.html'>阅读全文</a><img src ="http://www.blogjava.net/machilansing/aggbug/91904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2007-01-05 10:10 <a href="http://www.blogjava.net/machilansing/archive/2007/01/05/91904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ORACLE 全文索引功能实现</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/ORACLE.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 01:33:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/ORACLE.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64049.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/ORACLE.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64049.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64049.html</trackback:ping><description><![CDATA[
		<span class="tt1">ORACLE 全文索引功能实现学习笔记 <br /><br />前言： 数据库工程师众所周知的一个事实是，当对数据库里的文本字段进行like检索的时候，任何数据索引都是不起作用的，这样也就导致系统会承担额外的开销和负载压力，对于庞大的数据记录，对其中的文本字段进行关键字匹配，就肯定会存在非常严重的效率障碍和性能障碍。因此，基于文本的全文索引技术也就逐渐兴起。 <br />全文索引的技术原理并不复杂，对段落性的文本内容进行逐词分解，并针对词出现频率，出现位置进行标记，按照词本身的编码顺序存储为索引文件。这样，在针对关键词进行检索的时候，就不会遍历所有的文本数据记录，而是根据索引文件进行有序查找，这里面一个显见的事实是，通过有序索引查找关键词，对于海量的数据记录而言，也只需要很少次数的指针跳转，（数量为X的索引记录，查询特定记录的指针跳转次数最多为Log2(x)。）即可完成搜索，而无须完整遍历整个数据表或文件集。 <br />但是全文索引技术的实现却并不简单，针对中文的尤其如此，英文文本中，空格是天然的分词标记，而中文段落却无法通过这样简单的途径分词，因此基于常用语词典和一些语言识别规则的分词技术成为一种非常高的技术门槛，幸好，很多商业公司提供了非常成熟的商业产品，使我等可以坐享其成，快速搭建全文搜索的平台。 <br /><br />ORACLE INTERMEDIA介绍 <br />ORACLE Intermedia是ORACLE公司官方发布的用来管理多媒体数据的数据库管理模块，通过它可以进行有效的视频，音频，图片等文件的统一存储，调用和相关处理；同时其中也包括一个Oracle Intermdedia Text功能模块，能够对多种格式文档进行分词索引处理，也提供了使用自然语法或高级查询方法进行跨文本查询的途径，可以查询word, PDF,RTF等格式的文件和数据。 <br />Oracle Intermedia 的索引效率和查询效率，据一些公开数据上看要远高于Microsoft的Index Server，而且本身具有平台无关特性，另外作为数据库产品，可以很好的和数据库应用进行整合，这一点也是纯粹的文件索引系统所无法实现的。当然，作为通用的数据库产品，Oracle不可能针对全文索引做到最大限度的优化，因此对于高并发大容量的搜索引擎应用，Oracle的方案可能就无法满足，这一点也是必须提前声明的。 <br /><br />全文索引实现步骤 <br />步骤1：查看Oracle Intermedia是否正确安装。Oracle Intermdeia是Oracle的一个附带模块，安装过程中选择即可。 <br />步骤2：设置词法解析器 <br />oracle根据不同语言，有不同的词法解析器，以下说明我们可能用到的三个 <br />basic_lexer，针对英语环境，以空格为分词标记，同时能分辨一些“噪音”单词，如 “if”, “is”等。 <br />chinese_vgram_lexer，专用的汉语分析器，按字为单元分析中文，算法简单，可以一网打尽中文用词，但是效率差强人意。 <br />chinese_lexer，可以识别大部分常用短语和词汇，不会产生大量冗余数据，有很好的实用性，但是语言支持只能为UTF-8编码，不支持zhs16gbk字符集。 <br />以ctxsys用户登陆系统，执行： <br />begin ctx_ddl.create_preference('my_lexer','chinese_vgram_lexer'); end; <br />这里假设我们的语法解析器命名为my_lexer，这个名称也可以根据实际应用变化。 <br />步骤3：建立索引字段 <br />我的测试用例保存在system空间，表名为my_docs，字段名为doc，字段类型为blob，存储标准word doc文件。 <br />仍旧保持ctxsys帐户登陆，执行如下操作 <br />create index system.myindex on system.my_docs(doc) indextype is ctxsys.context parameters(‘lexer’,’my_lexer’) ; <br />步骤4：同步操作（sync）及优化操作 <br />以system 登陆，同步操作执行 <br />exec ctx_ddl.sync_index('myindex'); <br /><br />创建同步定时任务代码如下 <br />VARIABLE jobno number; <br />BEGIN <br />　　DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.sync_index(''myindex'');', <br />　　SYSDATE, 'SYSDATE + (1/24/4)'); <br />　　commit; <br />　　END; <br />/ <br />以system登陆，优化索引操作执行 <br />exec ctx_ddl.optimize_index('myindex','FULL'); <br />创建优化定时任务代码如下 <br />VARIABLE jobno number; <br />　　BEGIN <br />　　DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.optimize_index(''myindex'',''FULL'');', <br />　　SYSDATE, 'SYSDATE + 1'); <br />　　commit; <br />　　END; <br />/ <br />步骤5：测试 <br />select id from my_docs where contains(doc,'关键字')&gt;0 <br />总结： <br />该学习笔记内容大部分可以通过搜索引擎找到，并非本人原创内容，本文全部经个人在windows平台下，在oracle 9i下测试完成，留档记录，为日后的项目和产品开发做技术准备。 </span>
<img src ="http://www.blogjava.net/machilansing/aggbug/64049.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 09:33 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/ORACLE.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>全文索引—CONTAINS语法</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/CONTAINS.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 01:31:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/CONTAINS.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64048.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/CONTAINS.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64048.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64048.html</trackback:ping><description><![CDATA[
		<strong>全文索引—CONTAINS语法<br /><br /></strong>全文索引—CONTAINS语法<br />全文索引——CONTAINS 语法<br />我们通常在 WHERE 子句中使用 CONTAINS ，就象这样：SELECT * FROM table_name WHERE CONTAINS(fullText_column,'search contents')。 <br /><br />我们通过例子来学习，假设有表 students，其中的 address 是全文本检索的列。<br />1. 查询住址在北京的学生<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, 'beijing' )<br />remark: beijing是一个单词，要用单引号括起来。<br /><br />2. 查询住址在河北省的学生<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, '"HEIBEI province"' )<br />remark: HEBEI province是一个词组，在单引号里还要用双引号括起来。<br /><br />3. 查询住址在河北省或北京的学生<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, '"HEIBEI province" OR beijing' )<br />remark: 可以指定逻辑操作符(包括 AND ，AND NOT，OR )。<br /><br />4. 查询有 '南京路' 字样的地址<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, 'nanjing NEAR road' )<br />remark: 上面的查询将返回包含 'nanjing road'，'nanjing east road'，'nanjing west road' 等字样的地址。<br />          A NEAR B，就表示条件： A 靠近 B。<br /><br />5. 查询以 '湖' 开头的地址<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, '"hu*"' )<br />remark: 上面的查询将返回包含 'hubei'，'hunan' 等字样的地址。<br />          记住是 *，不是 %。<br /><br />6. 类似加权的查询<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, 'ISABOUT (city weight (.8), county wright (.4))' )<br />remark: ISABOUT 是这种查询的关键字，weight 指定了一个介于 0~1之间的数，类似系数(我的理解)。表示不同条件有不同的侧重。<br /><br />7. 单词的多态查询<br />SELECT student_id,student_name<br />FROM students<br />WHERE CONTAINS( address, 'FORMSOF (INFLECTIONAL,street)' )<br />remark: 查询将返回包含 'street'，'streets'等字样的地址。<br />         对于动词将返回它的不同的时态，如：dry，将返回 dry，dried，drying 等等。<img src ="http://www.blogjava.net/machilansing/aggbug/64048.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 09:31 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/CONTAINS.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Java的全文索引/检索引擎——Lucene</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/Lucene.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/Lucene.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64037.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/Lucene.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64037.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64037.html</trackback:ping><description><![CDATA[
		<p>
				<a name="intro">
						<b>基于Java的全文索引/检索引擎——Lucene</b>
				</a>
		</p>
		<p>Lucene不是一个完整的全文索引应用，而是是一个用Java写的全文索引引擎工具包，它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。</p>
		<p>Lucene的作者：Lucene的贡献者<a href="http://www.nutch.org/blog/cutting.html">Doug Cutting</a>是一位资深全文索引/检索专家，曾经是V-Twin搜索引擎(Apple的Copland操作系统的成就之一)的主要开发者，后在Excite担任高级系统架构设计师，目前从事于一些INTERNET底层架构的研究。他贡献出的Lucene的目标是为各种中小型应用程序加入全文检索功能。</p>
		<p>Lucene的发展历程：早先发布在作者自己的<a href="http://www.lucene.com/">www.lucene.com</a>，后来发布在<a href="http://sourceforge.net/projects/lucene/">SourceForge</a>，2001年年底成为APACHE基金会jakarta的一个子项目：<a href="http://jakarta.apache.org/lucene/">http://jakarta.apache.org/lucene/</a></p>
		<p>已经有很多Java项目都使用了Lucene作为其后台的全文索引引擎，比较著名的有：</p>
		<ul>
				<li>
						<a href="http://www.jivesoftware.com/">J</a>
						<a href="http://www.jivesoftware.com/">ive</a>：WEB论坛系统； 
</li>
				<li>
						<a href="http://eyebrowse.tigris.org/">Eyebrows</a>：邮件列表HTML归档/浏览/查询系统，本文的主要参考文档“<a href="http://www.javaworld.com/javaworld/jw-09-2000/jw-0915-lucene_p.html">TheLucene search engine: Powerful, flexible, and free</a>”作者就是EyeBrows系统的主要开发者之一，而EyeBrows已经成为目前APACHE项目的主要邮件列表归档系统。 
</li>
				<li>
						<a href="http://xml.apache.org/cocoon/index.html">Cocoon</a>:基于XML的web发布框架，全文检索部分使用了Lucene 
</li>
				<li>
						<p align="left">
								<a href="http://www.eclipse.org/">Eclipse</a>:基于Java的开放开发平台，帮助部分的全文索引使用了Lucene</p>
				</li>
		</ul>
		<p>对于中文用户来说，最关心的问题是其是否支持中文的全文检索。但通过后面对于Lucene的结构的介绍，你会了解到由于Lucene良好架构设计，对中文的支持只需对其语言词法分析接口进行扩展就能实现对中文检索的支持。</p>
		<p>
				<b>
						<a name="compare">全文检索的实现机制</a>
				</b>
		</p>
		<p>Lucene的API接口设计的比较通用，输入输出结构都很像数据库的表==&gt;记录==&gt;字段，所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。总体上看：可以先把<b>Lucene当成一个支持全文索引的数据库系统</b>。</p>
		<p>比较一下Lucene和数据库：</p>
		<table width="100%" border="1">
				<tbody>
						<tr>
								<td align="middle" width="50%">Lucene</td>
								<td align="middle" width="50%">数据库</td>
						</tr>
						<tr>
								<td width="50%">
										<pre>索引数据源：doc(field1,field2...) doc(field1,field2...)<br />                  \  indexer /<br />                 _____________<br />                | Lucene Index|<br />                --------------<br />                 / searcher \<br /> 结果输出：Hits(doc(field1,field2) doc(field1...))</pre>
								</td>
								<td width="50%">
										<pre> 索引数据源：record(field1,field2...) record(field1..)<br />              \  SQL: insert/<br />               _____________<br />              | DB  Index   |<br />               -------------<br />              / SQL: select \<br />结果输出：results(record(field1,field2..) record(field1...))</pre>
								</td>
						</tr>
						<tr>
								<td width="50%">Document：一个需要进行索引的“单元”<br />一个Document由多个字段组成</td>
								<td width="50%">Record：记录，包含多个字段</td>
						</tr>
						<tr>
								<td width="50%">Field：字段</td>
								<td width="50%">Field：字段</td>
						</tr>
						<tr>
								<td width="50%">Hits：查询结果集，由匹配的Document组成</td>
								<td width="50%">RecordSet：查询结果集，由多个Record组成</td>
						</tr>
				</tbody>
		</table>
		<p>
				<font size="1">
						<b>全文检索 ≠ like "%keyword%"</b>
				</font>
		</p>
		<p>通常比较厚的书籍后面常常附关键词索引表（比如：北京：12, 34页，上海：3,77页……），它能够帮助读者比较快地找到相关内容的页码。而数据库索引能够大大提高查询的速度原理也是一样，想像一下通过书后面的索引查找的速度要比一页一页地翻内容高多少倍……而索引之所以效率高，另外一个原因是它是排好序的。<b>对于检索系统来说核心是一个排序问题</b>。</p>
		<p align="left">由于数据库索引不是为全文索引设计的，因此，<b>使用like "%keyword%"时，数据库索引是不起作用的</b>，在使用like查询时，搜索过程又变成类似于一页页翻书的遍历过程了，所以对于含有模糊查询的数据库服务来说，LIKE对性能的危害是极大的。如果是需要对多个关键词进行模糊匹配：like"%keyword1%" and like "%keyword2%" ...其效率也就可想而知了。</p>
		<p>所以建立一个高效检索系统的关键是建立一个类似于科技索引一样的反向索引机制，将数据源（比如多篇文章）排序顺序存储的同时，有另外一个排好序的关键词列表，用于存储关键词==&gt;文章映射关系，利用这样的映射关系索引：[关键词==&gt;出现关键词的文章编号，出现次数（甚至包括位置：起始偏移量，结束偏移量），出现频率]，检索过程就是把<b>模糊查询变成多个可以利用索引的精确查询的逻辑组合的过程</b>。从而大大提高了多关键词查询的效率，所以，全文检索问题归结到最后是一个排序问题。</p>
		<p>由此可以看出模糊查询相对数据库的精确查询是一个非常不确定的问题，这也是大部分数据库对全文检索支持有限的原因。Lucene最核心的特征是通过特殊的索引结构实现了传统数据库不擅长的全文索引机制，并提供了扩展接口，以方便针对不同应用的定制。</p>
		<p>可以通过一下表格对比一下数据库的模糊查询：</p>
		<p>
				<span style="FONT-WEIGHT: bold">
						<table style="WIDTH: 540px; HEIGHT: 592px" height="592" width="540" border="1">
								<tbody>
										<tr>
												<td align="middle" width="9%" height="16">　</td>
												<td align="middle" width="47%" height="16">Lucene全文索引引擎</td>
												<td align="middle" width="40%" height="16">数据库</td>
										</tr>
										<tr>
												<td width="9%" height="48">索引</td>
												<td width="47%" height="48">将数据源中的数据都通过全文索引一一建立反向索引</td>
												<td width="40%" height="48">对于LIKE查询来说，数据传统的索引是根本用不上的。数据需要逐个便利记录进行GREP式的模糊匹配，比有索引的搜索速度要有多个数量级的下降。</td>
										</tr>
										<tr>
												<td width="9%" height="49">匹配效果</td>
												<td width="47%" height="49">通过词元(term)进行匹配，通过语言分析接口的实现，可以实现对中文等非英语的支持。</td>
												<td width="40%" height="49">使用：like "%net%" 会把netherlands也匹配出来，<br />多个关键词的模糊匹配：使用like "%com%net%"：就不能匹配词序颠倒的xxx.net..xxx.com</td>
										</tr>
										<tr>
												<td width="9%" height="32">匹配度</td>
												<td width="47%" height="32">有匹配度算法，将匹配程度（相似度）比较高的结果排在前面。</td>
												<td width="40%" height="32">没有匹配程度的控制：比如有记录中net出现5词和出现1次的，结果是一样的。</td>
										</tr>
										<tr>
												<td width="9%" height="32">结果输出</td>
												<td width="47%" height="32">通过特别的算法，将最匹配度最高的头100条结果输出，结果集是缓冲式的小批量读取的。</td>
												<td width="40%" height="32">返回所有的结果集，在匹配条目非常多的时候（比如上万条）需要大量的内存存放这些临时结果集。</td>
										</tr>
										<tr>
												<td width="9%" height="32">可定制性</td>
												<td width="47%" height="32">通过不同的语言分析接口实现，可以方便的定制出符合应用需要的索引规则（包括对中文的支持）</td>
												<td width="40%" height="32">没有接口或接口复杂，无法定制</td>
										</tr>
										<tr>
												<td width="9%" height="32">结论</td>
												<td width="47%" height="32">高负载的模糊查询应用，需要负责的模糊查询的规则，索引的资料量比较大</td>
												<td width="40%" height="32">使用率低，模糊匹配规则简单或者需要模糊查询的资料量少</td>
										</tr>
								</tbody>
						</table>
						<br />全文检索和数据库应用最大的不同在于：让</span>
				<span style="FONT-WEIGHT: bold">最相关的</span>
				<span style="FONT-WEIGHT: bold">头100条结果满足98%以上用户的需求<br /></span>
				<br />Lucene的创新之处：</p>
		<p>大部分的搜索（数据库）引擎都是用B树结构来维护索引，索引的更新会导致大量的IO操作，Lucene在实现中，对此稍微有所改进：不是维护一个索引文件，而是在扩展索引的时候不断创建新的索引文件，然后定期的把这些新的小索引文件合并到原先的大索引中（针对不同的更新策略，批次的大小可以调整），这样在不影响检索的效率的前提下，提高了索引的效率。</p>
		<p>Lucene和其他一些全文检索系统/应用的比较：</p>
		<table style="WIDTH: 543px; HEIGHT: 617px" width="543" border="1">
				<tbody>
						<tr>
								<td align="middle" width="18%">　</td>
								<td align="middle" width="45%">Lucene</td>
								<td align="middle" width="37%">其他开源全文检索系统</td>
						</tr>
						<tr>
								<td width="18%">增量索引和批量索引</td>
								<td width="45%">可以进行增量的索引(Append)，可以对于大量数据进行批量索引，并且接口设计用于优化批量索引和小批量的增量索引。</td>
								<td width="37%">很多系统只支持批量的索引，有时数据源有一点增加也需要重建索引。</td>
						</tr>
						<tr>
								<td width="18%">数据源</td>
								<td width="45%">Lucene没有定义具体的数据源，而是一个文档的结构，因此可以非常灵活的适应各种应用（只要前端有合适的转换器把数据源转换成相应结构），</td>
								<td width="37%">很多系统只针对网页，缺乏其他格式文档的灵活性。</td>
						</tr>
						<tr>
								<td width="18%">索引内容抓取</td>
								<td width="45%">Lucene的文档是由多个字段组成的，甚至可以控制那些字段需要进行索引，那些字段不需要索引，近一步索引的字段也分为需要分词和不需要分词的类型：<br />   需要进行分词的索引，比如：标题，文章内容字段<br />   不需要进行分词的索引，比如：作者/日期字段</td>
								<td width="37%">缺乏通用性，往往将文档整个索引了</td>
						</tr>
						<tr>
								<td width="18%">语言分析</td>
								<td width="45%">通过语言分析器的不同扩展实现：<br />可以过滤掉不需要的词：an the of 等，<br />西文语法分析：将jumps jumped jumper都归结成jump进行索引/检索<br />非英文支持：对亚洲语言，阿拉伯语言的索引支持</td>
								<td width="37%">缺乏通用接口实现</td>
						</tr>
						<tr>
								<td width="18%">查询分析</td>
								<td width="45%">通过查询分析接口的实现，可以定制自己的查询语法规则：<br />比如： 多个关键词之间的 + - and or关系等</td>
								<td width="37%">　</td>
						</tr>
						<tr>
								<td width="18%">并发访问</td>
								<td width="45%">能够支持多用户的使用</td>
								<td width="37%">　</td>
						</tr>
				</tbody>
		</table>
		<p>　</p>
		<p>
				<b>
						<a name="segment">关于亚洲语言的的切分词问题(Word Segment)</a>
				</b>
		</p>
		<p>对于中文来说，全文索引首先还要解决一个语言分析的问题，对于英文来说，语句中单词之间是天然通过空格分开的，但亚洲语言的中日韩文语句中的字是一个字挨一个，所有，首先要把语句中按“词”进行索引的话，这个词如何切分出来就是一个很大的问题。</p>
		<p>首先，肯定不能用单个字符作(si-gram)为索引单元，否则查“上海”时，不能让含有“海上”也匹配。</p>
		<p>但一句话：“北京天安门”，计算机如何按照中文的语言习惯进行切分呢？<br />“北京 天安门” 还是“北 京 天安门”？让计算机能够按照语言习惯进行切分，往往需要机器有一个比较丰富的词库才能够比较准确的识别出语句中的单词。</p>
		<p>另外一个解决的办法是采用自动切分算法：将单词按照2元语法(bigram)方式切分出来，比如：<br />"北京天安门" ==&gt; "北京 京天 天安 安门"。</p>
		<p>这样，在查询的时候，无论是查询"北京" 还是查询"天安门"，将查询词组按同样的规则进行切分："北京"，"天安安门"，多个关键词之间按与"and"的关系组合，同样能够正确地映射到相应的索引中。这种方式对于其他亚洲语言：韩文，日文都是通用的。</p>
		<p>基于自动切分的最大优点是没有词表维护成本，实现简单，缺点是索引效率低，但对于中小型应用来说，基于2元语法的切分还是够用的。基于2元切分后的索引一般大小和源文件差不多，而对于英文，索引文件一般只有原文件的30%-40%不同，</p>
		<table height="68" width="100%" border="1">
				<tbody>
						<tr>
								<td align="middle" width="11%" height="18">
										<br />
								</td>
								<td align="middle" width="39%" height="18">自动切分</td>
								<td align="middle" width="50%" height="18">词表切分</td>
						</tr>
						<tr>
								<td width="11%" height="16">实现</td>
								<td width="39%" height="16">实现非常简单</td>
								<td width="50%" height="16">实现复杂</td>
						</tr>
						<tr>
								<td width="11%" height="16">查询</td>
								<td width="39%" height="16">增加了查询分析的复杂程度，</td>
								<td width="50%" height="16">适于实现比较复杂的查询语法规则</td>
						</tr>
						<tr>
								<td width="11%" height="16">存储效率</td>
								<td width="39%" height="16">索引冗余大，索引几乎和原文一样大</td>
								<td width="50%" height="16">索引效率高，为原文大小的30％左右</td>
						</tr>
						<tr>
								<td width="11%" height="16">维护成本</td>
								<td width="39%" height="16">无词表维护成本</td>
								<td width="50%" height="16">词表维护成本非常高：中日韩等语言需要分别维护。<br />还需要包括词频统计等内容</td>
						</tr>
						<tr>
								<td width="11%" height="16">适用领域</td>
								<td width="39%" height="16">嵌入式系统：运行环境资源有限<br />分布式系统：无词表同步问题<br />多语言环境：无词表维护成本</td>
								<td width="50%" height="16">对查询和存储效率要求高的专业搜索引擎<br /></td>
						</tr>
				</tbody>
		</table>
		<p>目前比较大的搜索引擎的语言分析算法一般是基于以上2个机制的结合。关于中文的语言分析算法，大家可以在Google查关键词"wordsegment search"能找到更多相关的资料。</p>
		<p>
				<a name="demo">
						<b>安装和使用</b>
				</a>
		</p>
		<p>下载：<a href="http://jakarta.apache.org/lucene/">http://jakarta.apache.org/lucene/</a></p>
		<p>注意：Lucene中的一些比较复杂的词法分析是用JavaCC生成的（JavaCC：JavaCompilerCompiler，纯Java的词法分析生成器），所以如果从源代码编译或需要修改其中的QueryParser、定制自己的词法分析器，还需要从<a href="https://javacc.dev.java.net/">https://javacc.dev.java.net/</a>下载javacc。</p>
		<p>lucene的组成结构：对于外部应用来说索引模块(index)和检索模块(search)是主要的外部应用入口</p>
		<table width="100%" border="1">
				<tbody>
						<tr>
								<td width="27%">org.apache.Lucene.search/</td>
								<td width="73%">搜索入口</td>
						</tr>
						<tr>
								<td width="27%">org.apache.Lucene.index/</td>
								<td width="73%">索引入口</td>
						</tr>
						<tr>
								<td width="27%">org.apache.Lucene.analysis/</td>
								<td width="73%">语言分析器</td>
						</tr>
						<tr>
								<td width="27%">org.apache.Lucene.queryParser/</td>
								<td width="73%">查询分析器</td>
						</tr>
						<tr>
								<td width="27%">org.apache.Lucene.document/</td>
								<td width="73%">存储结构</td>
						</tr>
						<tr>
								<td width="27%">org.apache.Lucene.store/ </td>
								<td width="73%">底层IO/存储结构</td>
						</tr>
						<tr>
								<td width="27%">org.apache.Lucene.util/</td>
								<td width="73%">一些公用的数据结构</td>
						</tr>
				</tbody>
		</table>
		<p>简单的例子演示一下Lucene的使用方法：</p>索引过程：从命令行读取文件名（多个），将文件分路径(path字段)和内容(body字段)2个字段进行存储，并对内容进行全文索引：索引的单位是Document对象，每个Document对象包含多个字段Field对象，针对不同的字段属性和数据输出的需求，对字段还可以选择不同的索引/存储字段规则，列表如下： 
<table border="1"><tbody><tr><th>方法</th><th>切词</th><th>索引</th><th>存储</th><th>用途</th></tr><tr><td>Field.Text(String name, String value)</td><td>Yes</td><td>Yes</td><td>Yes</td><td valign="top">切分词索引并存储，比如：标题，内容字段</td></tr><tr><td>Field.Text(String name, Reader value)</td><td>Yes</td><td>Yes</td><td>No</td><td valign="top">切分词索引不存储，比如：META信息，<br />不用于返回显示，但需要进行检索内容</td></tr><tr><td>Field.Keyword(String name, String value)</td><td>No</td><td>Yes</td><td>Yes</td><td valign="top">不切分索引并存储，比如：日期字段</td></tr><tr><td>Field.UnIndexed(String name, String value)</td><td>No</td><td>No</td><td>Yes</td><td valign="top">不索引，只存储，比如：文件路径</td></tr><tr><td>Field.UnStored(String name, String value)</td><td>Yes</td><td>Yes</td><td>No</td><td valign="top">只全文索引，不存储</td></tr></tbody></table><pre>public class IndexFiles { <br />  //使用方法：: IndexFiles [索引输出目录] [索引的文件列表] ... <br />  public static void main(String[] args) throws Exception {<br />    String indexPath = args[0];<br />    IndexWriter writer;<br />    //用指定的语言分析器构造一个新的写索引器（第3个参数表示是否为追加索引）<br />    writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false);<br /><br />    for (int i=1; i&lt;args.length; i++) {<br />      System.out.println("Indexing file " + args[i]);<br />      InputStream is = new FileInputStream(args[i]);<br /><br />      //构造包含2个字段Field的Document对象<br />      //一个是路径path字段，不索引，只存储<br />      //一个是内容body字段，进行全文索引，并存储<br />      Document doc = new Document();<br />      doc.add(Field.UnIndexed("path", args[i]));<br />      doc.add(Field.Text("body", (Reader) new InputStreamReader(is)));<br />      //将文档写入索引<br />      writer.addDocument(doc);<br />      is.close();<br />    };<br />    //关闭写索引器<br />    writer.close();<br />  }<br />}<br />　</pre><p>索引过程中可以看到：</p><ul><li>语言分析器提供了抽象的接口，因此语言分析(Analyser)是可以定制的，虽然lucene缺省提供了2个比较通用的分析器SimpleAnalyser和StandardAnalyser，这2个分析器缺省都不支持中文，所以要加入对中文语言的切分规则，需要修改这2个分析器。 
</li><li>Lucene并没有规定数据源的格式，而只提供了一个通用的结构（Document对象）来接受索引的输入，因此输入的数据源可以是：数据库，WORD文档，PDF文档，HTML文档……只要能够设计相应的解析转换器将数据源构造成成Docuement对象即可进行索引。 
</li><li>对于大批量的数据索引，还可以通过调整IndexerWrite的文件合并频率属性（mergeFactor）来提高批量索引的效率。 </li></ul><p>检索过程和结果显示：</p><p>搜索结果返回的是Hits对象，可以通过它再访问Document==&gt;Field中的内容。</p><p>假设根据body字段进行全文检索，可以将查询结果的path字段和相应查询的匹配度(score)打印出来，</p><pre>public class Search { <br />  public static void main(String[] args) throws Exception {<br />    String indexPath = args[0], queryString = args[1];<br />    //指向索引目录的搜索器<br />    Searcher searcher = new IndexSearcher(indexPath);<br />    //查询解析器：使用和索引同样的语言分析器<br />    Query query = QueryParser.parse(queryString, "body", <br />                              new SimpleAnalyzer());<br />    //搜索结果使用Hits存储<br />    Hits hits = searcher.search(query);<br />    //通过hits可以访问到相应字段的数据和查询的匹配度<br />    for (int i=0; i&lt;hits.length(); i++) {<br />      System.out.println(hits.doc(i).get("path") + "; Score: " + <br />                         hits.score(i));<br />    };<br />  }<br />}</pre>在整个检索过程中，语言分析器，查询分析器，甚至搜索器（Searcher）都是提供了抽象的接口，可以根据需要进行定制。 
<p><b><a name="hacking">Hacking Lucene</a></b></p><p><b>简化的查询分析器</b></p><p>个人感觉lucene成为JAKARTA项目后，画在了太多的时间用于调试日趋复杂QueryParser，而其中大部分是大多数用户并不很熟悉的，目前LUCENE支持的语法：</p><p>Query ::= ( Clause )*<br />Clause ::= ["+", "-"] [&lt;TERM&gt; ":"] ( &lt;TERM&gt; | "(" Query ")")</p><p>中间的逻辑包括：and or + - &amp;&amp;||等符号，而且还有"短语查询"和针对西文的前缀/模糊查询等，个人感觉对于一般应用来说，这些功能有一些华而不实，其实能够实现目前类似于Google的查询语句分析功能其实对于大多数用户来说已经够了。所以，Lucene早期版本的QueryParser仍是比较好的选择。</p><p><b>添加修改删除指定记录（Document）</b></p><p>Lucene提供了索引的扩展机制，因此索引的动态扩展应该是没有问题的，而指定记录的修改也似乎只能通过记录的删除，然后重新加入实现。如何删除指定的记录呢？删除的方法也很简单，只是需要在索引时根据数据源中的记录ID专门另建索引，然后利用IndexReader.delete(Termterm)方法通过这个记录ID删除相应的Document。</p><p><b>根据某个字段值的排序功能</b></p><p>lucene缺省是按照自己的相关度算法（score）进行结果排序的，但能够根据其他字段进行结果排序是一个在LUCENE的开发邮件列表中经常提到的问题，很多原先基于数据库应用都需要除了基于匹配度（score）以外的排序功能。而从全文检索的原理我们可以了解到，任何不基于索引的搜索过程效率都会导致效率非常的低，如果基于其他字段的排序需要在搜索过程中访问存储字段，速度回大大降低，因此非常是不可取的。</p><p>但这里也有一个折中的解决方法：在搜索过程中能够影响排序结果的只有索引中已经存储的docID和score这2个参数，所以，基于score以外的排序，其实可以通过将数据源预先排好序，然后根据docID进行排序来实现。这样就避免了在LUCENE搜索结果外对结果再次进行排序和在搜索过程中访问不在索引中的某个字段值。</p><p>这里需要修改的是IndexSearcher中的HitCollector过程：</p><pre>...<br />　scorer.score(new HitCollector() {<br />	private float minScore = 0.0f;<br />	public final void collect(int doc, float score) {<br />	  if (score &gt; 0.0f &amp;&amp;			  // ignore zeroed buckets<br />	      (bits==null || bits.get(doc))) {	  // skip docs not in bits<br />	    totalHits[0]++;<br />	    if (score &gt;= minScore) {<br />              /* 原先：Lucene将docID和相应的匹配度score例入结果命中列表中：<br />	       * hq.put(new ScoreDoc(doc, score));	  // update hit queue<br />               * 如果用doc 或 1/doc 代替 score，就实现了根据docID顺排或逆排<br />               * 假设数据源索引时已经按照某个字段排好了序，而结果根据docID排序也就实现了<br />               * 针对某个字段的排序，甚至可以实现更复杂的score和docID的拟合。<br />               */<br />              hq.put(new ScoreDoc(doc, (float) 1/doc )); <br />	      if (hq.size() &gt; nDocs) {		  // if hit queue overfull<br />		hq.pop();			  // remove lowest in hit queue<br />		minScore = ((ScoreDoc)hq.top()).score; // reset minScore<br />	      }<br />	    }<br />	  }<br />	}<br />      }, reader.maxDoc());</pre><p><b>更通用的输入输出接口</b></p><p>虽然lucene没有定义一个确定的输入文档格式，但越来越多的人想到使用一个标准的中间格式作为Lucene的数据导入接口，然后其他数据，比如PDF只需要通过解析器转换成标准的中间格式就可以进行数据索引了。这个中间格式主要以XML为主，类似实现已经不下4，5个：</p><pre>数据源: WORD       PDF     HTML    DB       other<br />         \          |       |      |         /<br />                       XML中间格式<br />                            |<br />                     Lucene INDEX</pre><p>目前还没有针对MSWord文档的解析器，因为Word文档和基于ASCII的RTF文档不同，需要使用COM对象机制解析。这个是我在Google上查的相关资料：<a href="http://www.intrinsyc.com/products/enterprise_applications.asp">http://www.intrinsyc.com/products/enterprise_applications.asp</a><br />另外一个办法就是把Word文档转换成text：<a href="http://www.winfield.demon.nl/index.html">http://www.winfield.demon.nl/index.html</a><br /></p><p><br /><b>索引过程优化</b></p><p>索引一般分2种情况，一种是小批量的索引扩展，一种是大批量的索引重建。在索引过程中，并不是每次新的DOC加入进去索引都重新进行一次索引文件的写入操作（文件I/O是一件非常消耗资源的事情）。</p><p>Lucene先在内存中进行索引操作，并根据一定的批量进行文件的写入。这个批次的间隔越大，文件的写入次数越少，但占用内存会很多。反之占用内存少，但文件IO操作频繁，索引速度会很慢。在IndexWriter中有一个MERGE_FACTOR参数可以帮助你在构造索引器后根据应用环境的情况充分利用内存减少文件的操作。根据我的使用经验：缺省Indexer是每20条记录索引后写入一次，每将MERGE_FACTOR增加50倍，索引速度可以提高1倍左右。<br /></p><p><span style="FONT-WEIGHT: bold">搜索过程优化<br /></span></p><p><span style="FONT-WEIGHT: bold"></span>lucene支持内存索引：这样的搜索比基于文件的I/O有数量级的速度提升。<br /><a href="http://www.onjava.com/lpt/a/3273">http://www.onjava.com/lpt/a/3273</a><br />而尽可能减少IndexSearcher的创建和对搜索结果的前台的缓存也是必要的。<br /><span style="FONT-WEIGHT: bold"></span></p><p><b></b></p><p>Lucene面向全文检索的优化在于首次索引检索后，并不把所有的记录（Document）具体内容读取出来，而起只将所有结果中匹配度最高的头100条结果（TopDocs）的ID放到结果集缓存中并返回，这里可以比较一下数据库检索：如果是一个10,000条的数据库检索结果集，数据库是一定要把所有记录内容都取得以后再开始返回给应用结果集的。所以即使检索匹配总数很多，Lucene的结果集占用的内存空间也不会很多。对于一般的模糊检索应用是用不到这么多的结果的，头100条已经可以满足90%以上的检索需求。<br /></p><p>如果首批缓存结果数用完后还要读取更后面的结果时Searcher会再次检索并生成一个上次的搜索缓存数大1倍的缓存，并再重新向后抓取。所以如果构造一个Searcher去查1－120条结果，Searcher其实是进行了2次搜索过程：头100条取完后，缓存结果用完，Searcher重新检索再构造一个200条的结果缓存，依此类推，400条缓存，800条缓存。由于每次Searcher对象消失后，这些缓存也访问那不到了，你有可能想将结果记录缓存下来，缓存数尽量保证在100以下以充分利用首次的结果缓存，不让Lucene浪费多次检索，而且可以分级进行结果缓存。<br /></p><p>Lucene的另外一个特点是在收集结果的过程中将匹配度低的结果自动过滤掉了。这也是和数据库应用需要将搜索的结果全部返回不同之处。</p><p><a href="http://sourceforge.net/projects/weblucene/">我的一些尝试</a>：</p><ul><li>支持中文的Tokenizer：这里有2个版本，一个是通过JavaCC生成的，对CJK部分按一个字符一个TOKEN索引，另外一个是从SimpleTokenizer改写的，对英文支持数字和字母TOKEN，对中文按迭代索引。 
</li><li>基于XML数据源的索引器：XMLIndexer，因此所有数据源只要能够按照DTD转换成指定的XML，就可以用XMLIndxer进行索引了。 
</li><li>根据某个字段排序：按记录索引顺序排序结果的搜索器：IndexOrderSearcher，因此如果需要让搜索结果根据某个字段排序，可以让数据源先按某个字段排好序（比如：PriceField），这样索引后，然后在利用这个按记录的ID顺序检索的搜索器，结果就是相当于是那个字段排序的结果了。 </li></ul><p><a name="learn"><b>从Lucene学到更多</b></a></p><p>Luene的确是一个面对对象设计的典范</p><ul><li>所有的问题都通过一个额外抽象层来方便以后的扩展和重用：你可以通过重新实现来达到自己的目的，而对其他模块而不需要； 
</li><li>简单的应用入口Searcher, Indexer，并调用底层一系列组件协同的完成搜索任务； 
</li><li>所有的对象的任务都非常专一：比如搜索过程：QueryParser分析将查询语句转换成一系列的精确查询的组合(Query),通过底层的索引读取结构IndexReader进行索引的读取，并用相应的打分器给搜索结果进行打分/排序等。所有的功能模块原子化程度非常高，因此可以通过重新实现而不需要修改其他模块。  
</li><li>除了灵活的应用接口设计，Lucene还提供了一些适合大多数应用的语言分析器实现（SimpleAnalyser,StandardAnalyser），这也是新用户能够很快上手的重要原因之一。 </li></ul><p>这些优点都是非常值得在以后的开发中学习借鉴的。作为一个通用工具包，Lunece的确给予了需要将全文检索功能嵌入到应用中的开发者很多的便利。</p><p>此外，通过对Lucene的学习和使用，我也更深刻地理解了为什么很多数据库优化设计中要求，比如：</p><ul><li>尽可能对字段进行索引来提高查询速度，但过多的索引会对数据库表的更新操作变慢，而对结果过多的排序条件，实际上往往也是性能的杀手之一。 
</li><li>很多商业数据库对大批量的数据插入操作会提供一些优化参数，这个作用和索引器的merge_factor的作用是类似的， 
</li><li>20%/80%原则：查的结果多并不等于质量好，尤其对于返回结果集很大，如何优化这头几十条结果的质量往往才是最重要的。 
</li><li>尽可能让应用从数据库中获得比较小的结果集，因为即使对于大型数据库，对结果集的随机访问也是一个非常消耗资源的操作。<br /></li></ul><p>参考资料：</p><p>Apache: Lucene Project<br /><a href="http://jakarta.apache.org/lucene/">http://jakarta.apache.org/lucene/<br /></a>Lucene开发/用户邮件列表归档<br /><a href="http://www.mail-archive.com/lucene-dev@jakarta.apache.org/">Lucene-dev@jakarta.apache.org</a><br /><a href="http://www.mail-archive.com/lucene-user@jakarta.apache.org/">Lucene-user@jakarta.apache.org</a></p><p>The Lucene search engine: Powerful, flexible, and free<br /><a href="http://www.javaworld.com/javaworld/jw-09-2000/jw-0915-lucene_p.html">http://www.javaworld.com/javaworld/jw-09-2000/jw-0915-Lucene_p.html</a></p><p>Lucene Tutorial<br /><a href="http://www.darksleep.com/puff/lucene/lucene.html">http://www.darksleep.com/puff/lucene/lucene.html</a></p><p>Notes on distributed searching with Lucene<br /><a href="http://home.clara.net/markharwood/lucene/">http://home.clara.net/markharwood/lucene/</a></p><p>中文语言的切分词<br /><a href="http://www.google.com/search?sourceid=navclient&amp;hl=zh-CN&amp;q=chinese+word+segment">http://www.google.com/search?sourceid=navclient&amp;hl=zh-CN&amp;q=chinese+word+segment</a></p><p>搜索引擎工具介绍<a href="http://searchtools.com/"><br />http://searchtools.com/</a></p><p>Lucene作者Cutting的几篇论文和专利<br /><a href="http://lucene.sourceforge.net/publications.html">http://lucene.sourceforge.net/publications.html</a> </p><p>Lucene的.NET实现：dotLucene<br /><a href="http://sourceforge.net/projects/dotlucene/">http://sourceforge.net/projects/dotlucene/<br /></a></p><p>Lucene作者Cutting的另外一个项目：基于Java的搜索引擎Nutch<br /><a href="http://www.nutch.org/">http://www.nutch.org/</a>   <a href="http://sourceforge.net/projects/nutch/">http://sourceforge.net/projects/nutch/<br /></a></p><p>关于基于词表和N-Gram的切分词比较<br /><a href="http://china.nikkeibp.co.jp/cgi-bin/china/news/int/int200302100112.html">http://china.nikkeibp.co.jp/cgi-bin/china/news/int/int200302100112.html</a><br /><br />2005-01-08 <a href="http://lucene.sourceforge.net/talks/pisa/">Cutting在Pisa大学做的关于Lucene的讲座：非常详细的Lucene架构解说</a></p><img src ="http://www.blogjava.net/machilansing/aggbug/64037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 09:08 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/Lucene.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>