<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lucene.net 教程</title>
	<atom:link href="http://www.xeie.cn/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.xeie.cn</link>
	<description>Lucene教程</description>
	<lastBuildDate>Tue, 26 Jan 2010 03:54:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>lucene乱码解决方案</title>
		<link>http://www.xeie.cn/index.php/lucene%e4%b9%b1%e7%a0%81/lucene%e4%b9%b1%e7%a0%81%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/</link>
		<comments>http://www.xeie.cn/index.php/lucene%e4%b9%b1%e7%a0%81/lucene%e4%b9%b1%e7%a0%81%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:54:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[lucene乱码]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=325</guid>
		<description><![CDATA[用paoding中文分词,先建立词典
vi /etc/profile
export PAODING_DIC_HOME=/data/paoding/dic
将paoding的dic目录里的内容copy到 /data/paoding/dic
windows设置见手册
另外导入lucene/contrib/memory下的包lucene-memory到regain/lib中.再编译.
server版本中有个问题需要修改.如果出现乱码可尝试将
src/net/sf/regain/search/SearchToolkit.java
修改为下面的
queryString = query.toString().trim();
//add by robin
try {
queryString = new String(queryString.getBytes(”iso-8859-1″),”UTF-8″);
} catch (Exception e) {
}
request.setContextAttribute(SEARCH_QUERY_CONTEXT_ATTR_NAME, queryString);
}
]]></description>
			<content:encoded><![CDATA[<p>用paoding中文分词,先建立词典<br />
vi /etc/profile<br />
export PAODING_DIC_HOME=/data/paoding/dic<br />
将paoding的dic目录里的内容copy到 /data/paoding/dic<br />
windows设置见手册</p>
<p>另外导入lucene/contrib/memory下的包lucene-memory到regain/lib中.再编译.</p>
<p>server版本中有个问题需要修改.如果出现乱码可尝试将<br />
src/net/sf/regain/search/SearchToolkit.java<br />
修改为下面的<br />
queryString = query.toString().trim();</p>
<p>//add by robin<br />
try {<br />
queryString = new String(queryString.getBytes(”iso-8859-1″),”UTF-8″);<br />
} catch (Exception e) {<br />
}<br />
request.setContextAttribute(SEARCH_QUERY_CONTEXT_ATTR_NAME, queryString);<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/lucene%e4%b9%b1%e7%a0%81/lucene%e4%b9%b1%e7%a0%81%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>lucene搜索引擎memoryIndwx错误</title>
		<link>http://www.xeie.cn/index.php/lucene-memoryindwx/lucene%e6%90%9c%e7%b4%a2%e5%bc%95%e6%93%8ememoryindwx%e9%94%99%e8%af%af/</link>
		<comments>http://www.xeie.cn/index.php/lucene-memoryindwx/lucene%e6%90%9c%e7%b4%a2%e5%bc%95%e6%93%8ememoryindwx%e9%94%99%e8%af%af/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:53:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[lucene memoryIndwx]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=323</guid>
		<description><![CDATA[是因为highlight这个类中用到了memoryIndex这个类，而默认的classpath下没有放入这个jar文件，所以会报找不到类的异常
JVM在启动的时候会自动设置Heap size的值，其初始空间(即-Xms)是物理内存的1/64，最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。
例如：java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar
]]></description>
			<content:encoded><![CDATA[<p>是因为highlight这个类中用到了memoryIndex这个类，而默认的classpath下没有放入这个jar文件，所以会报找不到类的异常</p>
<p>JVM在启动的时候会自动设置Heap size的值，其初始空间(即-Xms)是物理内存的1/64，最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。<br />
例如：java -jar -Xmn16m -Xms64m -Xmx128m MyApp.jar</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/lucene-memoryindwx/lucene%e6%90%9c%e7%b4%a2%e5%bc%95%e6%93%8ememoryindwx%e9%94%99%e8%af%af/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>regain 安装教程</title>
		<link>http://www.xeie.cn/index.php/regain-%e5%ae%89%e8%a3%85/regain-%e5%ae%89%e8%a3%85%e6%95%99%e7%a8%8b/</link>
		<comments>http://www.xeie.cn/index.php/regain-%e5%ae%89%e8%a3%85/regain-%e5%ae%89%e8%a3%85%e6%95%99%e7%a8%8b/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:52:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[regain 安装]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=321</guid>
		<description><![CDATA[一、修改增加中文分词模块为 Paoding-analysis
非常简单，只需要修改一个源码文件。
源代码文件（以下都用下划线表示）：src\net\sf\regainRegainToolKit.java
import net.paoding.analysis.analyzer.PaodingAnalyzer;
import org.apache.lucene.analysis.cn.ChineseAnalyzer;
public static Analyzer createAnalyzer(String analyzerType,
String[] stopWordList, String[] exclusionList, String[] untokenizedFieldNames)
throws RegainException
if (analyzerType.equalsIgnoreCase(&#8221;english&#8221;)) {
analyzerClassName = StandardAnalyzer.class.getName();
} else if (analyzerType.equalsIgnoreCase(&#8221;german&#8221;)) {
analyzerClassName = GermanAnalyzer.class.getName();
} else if (analyzerType.equalsIgnoreCase(&#8221;chinese&#8221;)){
analyzerClassName = ChineseAnalyzer.class.getName();//Add by ping.
}  else if (analyzerType.equalsIgnoreCase(&#8221;paoding&#8221;)){
analyzerClassName = PaodingAnalyzer.class.getName();//Add by ping.
}
源码修改只涉及以上一个文件，但是要完整编译和最终运成功，还需要其他修改。
主要包括：
1.修改ant的编译配置文件build.xml，
2.拷贝paoding-analysis.jar到lib目录。
build.xml修改如下：
[这里摘录修改的片段，修改增加部分为粗体]
&#8230;
&#60;target name=&#8221;runtime-desktop&#8221; depends=&#8221;prepare-once, runtime-desktop-fast&#8221;&#62;
&#60;echo message=&#8221;Creating the jars &#8230;&#8221; /&#62;
&#60;fileset id=&#8221;desktop-common-jars&#8221; dir=&#8221;build/included-lib-classes/common&#8221;&#62;
&#60;include name=&#8221;org/apache/lucene/**&#8221;/&#62;
&#60;include name=&#8221;org/apache/log4j/**&#8221;/&#62;
&#60;include name=&#8221;org/apache/regexp/**&#8221;/&#62;
&#60;!&#8211; Add by ping. &#8211;&#62;
&#60;include [...]]]></description>
			<content:encoded><![CDATA[<p>一、修改增加中文分词模块为 Paoding-analysis</p>
<p>非常简单，只需要修改一个源码文件。</p>
<p>源代码文件（以下都用下划线表示）：src\net\sf\regainRegainToolKit.java</p>
<p>import net.paoding.analysis.analyzer.PaodingAnalyzer;<br />
import org.apache.lucene.analysis.cn.ChineseAnalyzer;</p>
<p>public static Analyzer createAnalyzer(String analyzerType,<br />
String[] stopWordList, String[] exclusionList, String[] untokenizedFieldNames)<br />
throws RegainException</p>
<p>if (analyzerType.equalsIgnoreCase(&#8221;english&#8221;)) {<br />
analyzerClassName = StandardAnalyzer.class.getName();<br />
} else if (analyzerType.equalsIgnoreCase(&#8221;german&#8221;)) {<br />
analyzerClassName = GermanAnalyzer.class.getName();<br />
} else if (analyzerType.equalsIgnoreCase(&#8221;chinese&#8221;)){<br />
analyzerClassName = ChineseAnalyzer.class.getName();//Add by ping.<br />
}  else if (analyzerType.equalsIgnoreCase(&#8221;paoding&#8221;)){<br />
analyzerClassName = PaodingAnalyzer.class.getName();//Add by ping.<br />
}</p>
<p>源码修改只涉及以上一个文件，但是要完整编译和最终运成功，还需要其他修改。<br />
主要包括：<br />
1.修改ant的编译配置文件build.xml，<br />
2.拷贝paoding-analysis.jar到lib目录。</p>
<p>build.xml修改如下：<br />
[这里摘录修改的片段，修改增加部分为粗体]<br />
&#8230;<br />
&lt;target name=&#8221;runtime-desktop&#8221; depends=&#8221;prepare-once, runtime-desktop-fast&#8221;&gt;<br />
&lt;echo message=&#8221;Creating the jars &#8230;&#8221; /&gt;<br />
&lt;fileset id=&#8221;desktop-common-jars&#8221; dir=&#8221;build/included-lib-classes/common&#8221;&gt;<br />
&lt;include name=&#8221;org/apache/lucene/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/log4j/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/regexp/**&#8221;/&gt;<br />
&lt;!&#8211; Add by ping. &#8211;&gt;<br />
&lt;include name=&#8221;net/paoding/analysis/**&#8221;/&gt;<br />
&lt;include name=&#8221;paoding-*.properties&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/commons/**&#8221;/&gt;</p>
<p>&#8230;<br />
&lt;target name=&#8221;runtime-server&#8221; depends=&#8221;prepare-once, runtime-server-fast, -web-temps&#8221;&gt;<br />
&lt;jar jarfile=&#8221;build/runtime/crawler/${programname.file}-crawler.jar&#8221;<br />
compress=&#8221;false&#8221;<br />
index=&#8221;true&#8221;&gt;<br />
&lt;manifest&gt;<br />
&lt;attribute name=&#8221;Main-Class&#8221; value=&#8221;net.sf.regain.crawler.Main&#8221;/&gt;<br />
&lt;/manifest&gt;<br />
&lt;fileset dir=&#8221;build/included-lib-classes/common&#8221;&gt;<br />
&lt;include name=&#8221;org/apache/lucene/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/log4j/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/regexp/**&#8221;/&gt;</p>
<p>&lt;!&#8211; Add by ping. &#8211;&gt;<br />
&lt;include name=&#8221;net/paoding/analysis/**&#8221;/&gt;<br />
&lt;include name=&#8221;paoding-*.properties&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/commons/**&#8221;/&gt;<br />
&#8230;</p>
<p>&lt;mkdir dir=&#8221;build/runtime/search/webapps&#8221;/&gt;<br />
&lt;war destfile=&#8221;build/runtime/search/webapps/${programname.file}.war&#8221;<br />
webxml=&#8221;web/server/web-inf/web.xml&#8221;&gt;<br />
&lt;classes dir=&#8221;build/classes&#8221;&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/crawler/**&#8221;/&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/ui/desktop/**&#8221;/&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/util/sharedtag/simple/**&#8221;/&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/util/ui/**&#8221;/&gt;<br />
&lt;/classes&gt;<br />
&lt;lib dir=&#8221;lib&#8221;&gt;<br />
&lt;include name=&#8221;lucene-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;jakarta-regexp-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;log4j-*.jar&#8221;/&gt;<br />
&lt;!&#8211;Add by ping.&#8211;&gt;<br />
&lt;include name=&#8221;paoding-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;commons-logging*.jar&#8221;/&gt;<br />
&lt;/lib&gt;</p>
<p>&#8230;<br />
&lt;mkdir dir=&#8221;${deploy-target.dir}/${programname.file}/WEB-INF/lib&#8221;/&gt;<br />
&lt;copy todir=&#8221;${deploy-target.dir}/${programname.file}/WEB-INF/lib&#8221;&gt;<br />
&lt;fileset dir=&#8221;lib&#8221;&gt;<br />
&lt;include name=&#8221;lucene-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;jakarta-regexp-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;log4j-*.jar&#8221;/&gt;<br />
&lt;!&#8211;Add by ping.&#8211;&gt;<br />
&lt;include name=&#8221;paoding-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;commons-logging*.jar&#8221;/&gt;<br />
&lt;/fileset&gt;<br />
&lt;/copy&gt;</p>
<p>二、修改查询结果片段长度</p>
<p>1.默认查询结果显示片段为100个字节，<br />
个人认为比较短，可以修改为结果片段长度为300.</p>
<p>lucene\contrib\highlighter\src\java<br />
org.apache.lucene.search.highlight<br />
SimpleFragmenter.java</p>
<p>public class SimpleFragmenter implements Fragmenter<br />
{<br />
private static final int DEFAULT_FRAGMENT_SIZE =100*3;<br />
定于查询结果片段的长度。默认为100字节，修改为300字节</p>
<p>三、另外，对查询结果页面进行稍微修改。</p>
<p>1.package net.sf.regain.search.results;<br />
SingleSearchRusults.jsp</p>
<p>public void highlightHitDocument(int index)<br />
resHighlSummary = highlighter.getBestFragments(tokenStream, text, 3,<br />
&#8221; . . .  . . . &lt;br&gt;&lt;span class=\&#8221;resultTag\&#8221;&gt;[Result]&lt;/span&gt; &#8220;);<br />
定于查询结果显示。</p>
<p>2.web\web\common<br />
search.jsp</p>
<p>&lt;search:list msgNoResults=&#8221;&lt;tr&gt;&lt;td colspan=&#8217;2&#8242;&gt;{msg:noResultsFound}&lt;br/&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;&#8221;&gt;<br />
&lt;tr&gt;&lt;td colspan=&#8221;2&#8243;&gt;<br />
&lt;search:hit_typeicon imgpath=&#8221;img/ext&#8221;/&gt; &lt;search:hit_link/&gt;<br />
&lt;span&gt;<br />
(&lt;search:msg key=&#8221;relevance&#8221;/&gt;: &lt;search:hit_score/&gt;)&lt;br/&gt;<br />
&lt;span&gt;[Result]&lt;/span&gt;<br />
&lt;search:hit_field field=&#8221;summary&#8221;/&gt;&lt;br/&gt;<br />
&lt;search:hit_content/&gt;<br />
&lt;search:hit_path after=&#8221;&lt;br/&gt;&#8221; createLinks=&#8221;true&#8221;/&gt;<br />
&lt;search:hit_field field=&#8221;mimetype&#8221;/&gt;&amp;nbsp;<br />
&lt;span&gt;&lt;search:hit_url beautified=&#8221;true&#8221;/&gt; &#8211; &lt;search:hit_size/&gt;&lt;/span&gt;&lt;br/&gt;<br />
&lt;br/&gt;&lt;/span&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;/search:list&gt;</p>
<p>查询结果显示页面和显示数据域的定义。</p>
<p>3.增加显示样式<br />
src\web\common<br />
regain.css</p>
<p>.resultTag {<br />
color: #0000FF;<br />
font-weight: bold;<br />
}</p>
<p>4.一点小修饰，获取文章内容的按钮默认是德文，翻译成英文表示。<br />
src/net/sf/regain/search/sharedlib/hit/ContentTag.java<br />
protected void printEndTag(PageRequest request, PageResponse response,<br />
Document hit, int hitIndex)<br />
throws RegainException {</p>
<p>String content = null;<br />
content = hit.get(&#8221;content&#8221;);<br />
if (content != null) {<br />
String hitNumber = Integer.toString(hitIndex + 1);<br />
response.print(&#8221;&lt;input type=\&#8221;button\&#8221; class=\&#8221;button\&#8221; onclick=\&#8221;return toggleMe(&#8217;hit_&#8221; +<br />
hitNumber + &#8220;&#8216;)\&#8221; value=\&#8221;Click here Get &#8221; + hitNumber + &#8221; content\&#8221;&gt;&#8221;);</p>
<p>property文件<br />
词典库文件<br />
编码问题</p>
<p>regain增加paoding中文分词以及server端版本设置<br />
原文来自:http://monner.javaeye.com/blog/254804<br />
———————————————————————-<br />
补充:<br />
用paoding中文分词,先建立词典<br />
vi /etc/profile<br />
export PAODING_DIC_HOME=/data/paoding/dic<br />
将paoding的dic目录里的内容copy到 /data/paoding/dic<br />
windows设置见手册</p>
<p>另外导入lucene/contrib/memory下的包lucene-memory到regain/lib中.再编译.</p>
<p>server版本中有个问题需要修改.如果出现乱码可尝试将<br />
src/net/sf/regain/search/SearchToolkit.java<br />
修改为下面的<br />
queryString = query.toString().trim();</p>
<p>//add by robin<br />
try {<br />
queryString = new String(queryString.getBytes(”iso-8859-1″),”UTF-8″);<br />
} catch (Exception e) {<br />
}<br />
request.setContextAttribute(SEARCH_QUERY_CONTEXT_ATTR_NAME, queryString);<br />
}</p>
<p>return queryString;<br />
——————————-<br />
regain的服务器版本端配置关键修改点<br />
在</p>
<p>file:///home/admin/domains/25q.net/</p>
<p>然后在</p>
<p>file:///home/admin/domains/25q.net/</p>
<p>这里两处路径都需要加.否则会导致 index empty的错误</p>
<p>原文部分内容:</p>
<p>一、修改增加中文分词模块为 Paoding-analysis</p>
<p>非常简单，只需要修改一个源码文件。</p>
<p>源代码文件（以下都用下划线表示）：src\net\sf\regainRegainToolKit.java</p>
<p>import net.paoding.analysis.analyzer.PaodingAnalyzer;<br />
import org.apache.lucene.analysis.cn.ChineseAnalyzer;</p>
<p>public static Analyzer createAnalyzer(String analyzerType,<br />
String[] stopWordList, String[] exclusionList, String[] untokenizedFieldNames)<br />
throws RegainException</p>
<p>if (analyzerType.equalsIgnoreCase(”english”)) {<br />
analyzerClassName = StandardAnalyzer.class.getName();<br />
} else if (analyzerType.equalsIgnoreCase(”german”)) {<br />
analyzerClassName = GermanAnalyzer.class.getName();<br />
} else if (analyzerType.equalsIgnoreCase(”chinese”)){<br />
analyzerClassName = ChineseAnalyzer.class.getName();//Add by ping.<br />
} else if (analyzerType.equalsIgnoreCase(”paoding”)){<br />
analyzerClassName = PaodingAnalyzer.class.getName();//Add by ping.<br />
}</p>
<p>源码修改只涉及以上一个文件，但是要完整编译和最终运成功，还需要其他修改。<br />
主要包括：<br />
1.修改ant的编译配置文件build.xml，<br />
2.拷贝paoding-analysis.jar到lib目录。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/regain-%e5%ae%89%e8%a3%85/regain-%e5%ae%89%e8%a3%85%e6%95%99%e7%a8%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Regain增加中文Paoding分词模块</title>
		<link>http://www.xeie.cn/index.php/regain-paoding/regain%e5%a2%9e%e5%8a%a0%e4%b8%ad%e6%96%87paoding%e5%88%86%e8%af%8d%e6%a8%a1%e5%9d%97/</link>
		<comments>http://www.xeie.cn/index.php/regain-paoding/regain%e5%a2%9e%e5%8a%a0%e4%b8%ad%e6%96%87paoding%e5%88%86%e8%af%8d%e6%a8%a1%e5%9d%97/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:50:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Regain Paoding]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=319</guid>
		<description><![CDATA[一、修改增加中文分词模块为 Paoding-analysis
非常简单，只需要修改一个源码文件。
源代码文件（以下都用下划线表示）：src\net\sf\regainRegainToolKit.java

import net.paoding.analysis.analyzer.PaodingAnalyzer;
import org.apache.lucene.analysis.cn.ChineseAnalyzer;
public static Analyzer createAnalyzer(String analyzerType,
String[] stopWordList, String[] exclusionList, String[] untokenizedFieldNames)
throws RegainException
if (analyzerType.equalsIgnoreCase(&#8221;english&#8221;)) {
analyzerClassName = StandardAnalyzer.class.getName();
} else if (analyzerType.equalsIgnoreCase(&#8221;german&#8221;)) {
analyzerClassName = GermanAnalyzer.class.getName();
} else if (analyzerType.equalsIgnoreCase(&#8221;chinese&#8221;)){
analyzerClassName = ChineseAnalyzer.class.getName();//Add by ping.
}  else if (analyzerType.equalsIgnoreCase(&#8221;paoding&#8221;)){
analyzerClassName = PaodingAnalyzer.class.getName();//Add by ping.
} 
源码修改只涉及以上一个文件，但是要完整编译和最终运成功，还需要其他修改。
主要包括：
1.修改ant的编译配置文件build.xml，
2.拷贝paoding-analysis.jar到lib目录。
build.xml修改如下：
[这里摘录修改的片段，修改增加部分为粗体]
&#8230;
&#60;target name=&#8221;runtime-desktop&#8221; depends=&#8221;prepare-once, runtime-desktop-fast&#8221;&#62;
&#60;echo message=&#8221;Creating the jars &#8230;&#8221; /&#62;
&#60;fileset id=&#8221;desktop-common-jars&#8221; dir=&#8221;build/included-lib-classes/common&#8221;&#62;
&#60;include name=&#8221;org/apache/lucene/**&#8221;/&#62;
&#60;include name=&#8221;org/apache/log4j/**&#8221;/&#62;
&#60;include name=&#8221;org/apache/regexp/**&#8221;/&#62;
 &#60;!&#8211; Add by [...]]]></description>
			<content:encoded><![CDATA[<div><strong>一、修改增加中文分词模块为 Paoding-analysis</strong></div>
<div>非常简单，只需要修改一个源码文件。</div>
<div><span style="text-decoration: underline;">源代码文件（以下都用下划线表示）：src\net\sf\regain</span><span style="text-decoration: underline;">RegainToolKit.java</span></div>
<div>
<strong>import net.paoding.analysis.analyzer.PaodingAnalyzer;<br />
import org.apache.lucene.analysis.cn.ChineseAnalyzer;</strong></div>
<div>public static Analyzer createAnalyzer(String analyzerType,<br />
String[] stopWordList, String[] exclusionList, String[] untokenizedFieldNames)<br />
throws RegainException</div>
<div>if (analyzerType.equalsIgnoreCase(&#8221;english&#8221;)) {<br />
analyzerClassName = StandardAnalyzer.class.getName();<br />
} else if (analyzerType.equalsIgnoreCase(&#8221;german&#8221;)) {<br />
analyzerClassName = GermanAnalyzer.class.getName();<br />
} <strong>else if (analyzerType.equalsIgnoreCase(&#8221;chinese&#8221;)){<br />
analyzerClassName = ChineseAnalyzer.class.getName();//Add by ping.<br />
}  else if (analyzerType.equalsIgnoreCase(&#8221;paoding&#8221;)){<br />
analyzerClassName = PaodingAnalyzer.class.getName();//Add by ping.<br />
} </strong></div>
<div>源码修改只涉及以上一个文件，但是要完整编译和最终运成功，还需要其他修改。</div>
<div>主要包括：</div>
<div>1.修改ant的编译配置文件build.xml，</div>
<div>2.拷贝paoding-analysis.jar到lib目录。</div>
<div>build.xml修改如下：</div>
<div>[这里摘录修改的片段，修改增加部分为<strong>粗体</strong>]</div>
<div>&#8230;</div>
<div>&lt;target name=&#8221;runtime-desktop&#8221; depends=&#8221;prepare-once, runtime-desktop-fast&#8221;&gt;<br />
&lt;echo message=&#8221;Creating the jars &#8230;&#8221; /&gt;<br />
&lt;fileset id=&#8221;desktop-common-jars&#8221; dir=&#8221;build/included-lib-classes/common&#8221;&gt;<br />
&lt;include name=&#8221;org/apache/lucene/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/log4j/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/regexp/**&#8221;/&gt;<br />
<strong> &lt;!&#8211; Add by ping. &#8211;&gt;<br />
&lt;include name=&#8221;net/paoding/analysis/**&#8221;/&gt;<br />
&lt;include name=&#8221;paoding-*.properties&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/commons/**&#8221;/&gt;</strong></div>
<div>&#8230;</div>
<div>&lt;target name=&#8221;runtime-server&#8221; depends=&#8221;prepare-once, runtime-server-fast, -web-temps&#8221;&gt;<br />
&lt;jar jarfile=&#8221;build/runtime/crawler/${programname.file}-crawler.jar&#8221;<br />
compress=&#8221;false&#8221;<br />
index=&#8221;true&#8221;&gt;<br />
&lt;manifest&gt;<br />
&lt;attribute name=&#8221;Main-Class&#8221; value=&#8221;net.sf.regain.crawler.Main&#8221;/&gt;<br />
&lt;/manifest&gt;<br />
&lt;fileset dir=&#8221;build/included-lib-classes/common&#8221;&gt;<br />
&lt;include name=&#8221;org/apache/lucene/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/log4j/**&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/regexp/**&#8221;/&gt;</div>
<div><strong> &lt;!&#8211; Add by ping. &#8211;&gt;<br />
&lt;include name=&#8221;net/paoding/analysis/**&#8221;/&gt;<br />
&lt;include name=&#8221;paoding-*.properties&#8221;/&gt;<br />
&lt;include name=&#8221;org/apache/commons/**&#8221;/&gt;</strong></div>
<div>&#8230;</div>
<div>&lt;mkdir dir=&#8221;build/runtime/search/webapps&#8221;/&gt;<br />
&lt;war destfile=&#8221;build/runtime/search/webapps/${programname.file}.war&#8221;<br />
webxml=&#8221;web/server/web-inf/web.xml&#8221;&gt;<br />
&lt;classes dir=&#8221;build/classes&#8221;&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/crawler/**&#8221;/&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/ui/desktop/**&#8221;/&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/util/sharedtag/simple/**&#8221;/&gt;<br />
&lt;exclude name=&#8221;net/sf/regain/util/ui/**&#8221;/&gt;<br />
&lt;/classes&gt;<br />
&lt;lib dir=&#8221;lib&#8221;&gt;<br />
&lt;include name=&#8221;lucene-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;jakarta-regexp-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;log4j-*.jar&#8221;/&gt;<br />
<strong> &lt;!&#8211;Add by ping.&#8211;&gt;<br />
&lt;include name=&#8221;paoding-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;commons-logging*.jar&#8221;/&gt;</strong><br />
&lt;/lib&gt;</div>
<div>&#8230;</div>
<div>&lt;mkdir dir=&#8221;${deploy-target.dir}/${programname.file}/WEB-INF/lib&#8221;/&gt;<br />
&lt;copy todir=&#8221;${deploy-target.dir}/${programname.file}/WEB-INF/lib&#8221;&gt;<br />
&lt;fileset dir=&#8221;lib&#8221;&gt;<br />
&lt;include name=&#8221;lucene-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;jakarta-regexp-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;log4j-*.jar&#8221;/&gt;<br />
<strong> &lt;!&#8211;Add by ping.&#8211;&gt;<br />
&lt;include name=&#8221;paoding-*.jar&#8221;/&gt;<br />
&lt;include name=&#8221;commons-logging*.jar&#8221;/&gt;</strong><br />
&lt;/fileset&gt;<br />
&lt;/copy&gt;</div>
<div>二、修改查询结果片段长度</div>
<div>
<div><strong>1.默认查询结果显示片段为100个字节，</strong></div>
<div><strong>个人认为比较短，可以修改为结果片段长度为300.</strong></div>
<div><span style="text-decoration: underline;">lucene\contrib\highlighter\src\java</span></div>
<div><span style="text-decoration: underline;"> org.apache.lucene.search.highlight</span></div>
<div><span style="text-decoration: underline;"> SimpleFragmenter.java</span></div>
<div>public class SimpleFragmenter implements Fragmenter<br />
{<br />
<strong>private static final int DEFAULT_FRAGMENT_SIZE =100*3;</strong></div>
<div><strong>定于查询结果片段的长度。默认为100字节，修改为300字节</strong></div>
</div>
<div>三、另外，对查询结果页面进行稍微修改。</div>
<div><span style="text-decoration: underline;">1.package net.sf.regain.search.results;</span></div>
<div><span style="text-decoration: underline;">SingleSearchRusults.jsp</span></div>
<div>public void highlightHitDocument(int index)</div>
<div>resHighlSummary = highlighter.getBestFragments(tokenStream, text, 3,</div>
<div>&#8220;<strong> . . .  . . . &lt;br&gt;&lt;span class=\&#8221;resultTag\&#8221;&gt;[Result]&lt;/span&gt;</strong> &#8220;);</div>
<div><strong> 定于查询结果显示。</strong></div>
<div><span style="text-decoration: underline;">2.web\web\common</span></div>
<div><span style="text-decoration: underline;"> search.jsp</span></div>
<div>&lt;search:list msgNoResults=&#8221;&lt;tr&gt;&lt;td colspan=&#8217;2&#8242;&gt;{msg:noResultsFound}&lt;br/&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;&#8221;&gt;<br />
&lt;tr&gt;&lt;td colspan=&#8221;2&#8243;&gt;<br />
&lt;search:hit_typeicon imgpath=&#8221;img/ext&#8221;/&gt; &lt;search:hit_link/&gt;<br />
&lt;span&gt;<br />
(&lt;search:msg key=&#8221;relevance&#8221;/&gt;: &lt;search:hit_score/&gt;)&lt;br/&gt;<br />
<strong> &lt;span&gt;[Result]&lt;/span&gt;<br />
&lt;search:hit_field field=&#8221;summary&#8221;/&gt;&lt;br/&gt;<br />
</strong> &lt;search:hit_content/&gt;<br />
&lt;search:hit_path after=&#8221;&lt;br/&gt;&#8221; createLinks=&#8221;true&#8221;/&gt;<br />
&lt;search:hit_field field=&#8221;mimetype&#8221;/&gt;&amp;nbsp;<br />
&lt;span&gt;&lt;search:hit_url beautified=&#8221;true&#8221;/&gt; &#8211; &lt;search:hit_size/&gt;&lt;/span&gt;&lt;br/&gt;<br />
&lt;br/&gt;&lt;/span&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;/search:list&gt;</div>
<div><strong>查询结果显示页面和显示数据域的定义。</strong></div>
<div><span style="text-decoration: underline;">3.增加显示样式</span></div>
<div><span style="text-decoration: underline;">src\web\common</span></div>
<div><span style="text-decoration: underline;"> regain.css</span></div>
<div>.resultTag {<br />
color: #0000FF;<br />
font-weight: bold;</div>
<div>}</div>
<div>4.一点小修饰，获取文章内容的按钮默认是德文，翻译成英文表示。</div>
<div><span style="text-decoration: underline;">src/net/sf/regain/search/sharedlib/hit/ContentTag.java</span></div>
<div>protected void printEndTag(PageRequest request, PageResponse response,<br />
Document hit, int hitIndex)<br />
throws RegainException {</div>
<div>String content = null;<br />
content = hit.get(&#8221;content&#8221;);<br />
if (content != null) {<br />
String hitNumber = Integer.toString(hitIndex + 1);<br />
response.print(&#8221;&lt;input type=\&#8221;button\&#8221; class=\&#8221;button\&#8221; onclick=\&#8221;return toggleMe(&#8217;hit_&#8221; +<br />
<strong> hitNumber + &#8220;&#8216;)\&#8221; value=\&#8221;Click here Get &#8221; + hitNumber + &#8221; content\&#8221;&gt;&#8221;);</strong></div>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/regain-paoding/regain%e5%a2%9e%e5%8a%a0%e4%b8%ad%e6%96%87paoding%e5%88%86%e8%af%8d%e6%a8%a1%e5%9d%97/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>regain安装配置简介</title>
		<link>http://www.xeie.cn/index.php/regain%e5%ae%89%e8%a3%85/regain%e5%ae%89%e8%a3%85%e9%85%8d%e7%bd%ae%e7%ae%80%e4%bb%8b/</link>
		<comments>http://www.xeie.cn/index.php/regain%e5%ae%89%e8%a3%85/regain%e5%ae%89%e8%a3%85%e9%85%8d%e7%bd%ae%e7%ae%80%e4%bb%8b/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:48:57 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[regain安装]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=317</guid>
		<description><![CDATA[一、Regain简要介绍
regain是一款与Web搜索引擎类似的桌面搜索引擎系统，其不同之处在于regain不是对Internet内容的搜索，而是针对自己的文档或文件的搜索，使用regain可以轻松地在几秒内完成大量数据（许多个G）的搜索。Regain采用了Lucene的搜索语法，因此支持多种查询方式，支持多索引的搜索及基于文件类型的高级搜索，并且能实现URL重写及文件到HTTP的桥接，并且对中文也提供了较好的支持。
Regain提供了两种版本：桌面搜索及服务器搜索。桌面搜索提供了对普通桌面计算机的文档与局域网环境下的网页的快速搜索。服务器版本主要安装在Web服务器上，为网站及局域网环境下的文件服务器进行搜索。
Regain使用Java编写，因此可以实现跨平台安装，能安装于Windows、Linux、Mac OS及Solaris上。服务器版本需要 JSPs环境及标签库（tag library），因此需要安装一个Tomcat容器。而桌面版自带了一个小型的Web服务器，安装非常简单。
二、安装配置简介
大致知道了regain是什么以后，如果regain的功能正好是您需要的，那我们就来一起进行安装配置吧。
1.下载regain最新版本。主页http://regain.sourceforge.net/
如果只是安装使用的话，可以直接这里下载编译好的版本：http://regain.sourceforge.net/download.php 提供多种平台的最新稳定版本。如果是研究学习，或者想自己做优化修改，则建议下载带源码的版本：http://sourceforge.net /project/showfiles.php?group_id=111168
2.下载后解压到特定目录，本文范例以 e:\Devp\Java\JavaApp\regain 目录为解压目录
3.如果仅仅是下载编译好的版本安装试用的话，几乎都不需要什么设置，直接解压后，打开命令行窗口进入安装目录，直接运行

java -jar regain.jar 命令行
运行后会在右下角systray系统托盘处出现regain的形状为“r”的小图标，右击会弹出search\status \Perferences菜单。直接选择Search就会打开查询页面。其实如果第一次运行，系统会自动弹出欢迎页面。Perferences设置页面可 以增加用户要索引的文件数据目录和web端口。
4.更多设置在conf目录中，主要设置文件包括如下4个文件，设置都非常简单直观
现在把比较重要的设置稍做解释。
（1）SearchConfiguration.xml  主要包括查询模块的设置。
&#8230;
&#60;!&#8211; The search index &#8216;main&#8217; &#8211;&#62;
&#60;index name=&#8221;main&#8221; default=&#8221;true&#8221; isparent=&#8221;true&#8221;&#62;
&#60;!&#8211; The directory where the index is located &#8211;&#62;
 &#60;dir&#62;D:\SearchEngine\Index\regainindex&#60;/dir&#62;索引放置的目录
&#60;/index&#62;
（2）DesktopConfiguration.xml 主要包括本地桌面查询设置，可通过perferences页面设置。
&#60;configuration&#62;
&#60;!&#8211; The interval to update the search index in minutes &#8211;&#62;
&#60;interval&#62;1440&#60;/interval&#62;
&#60;!&#8211; Allow/Disallow external access to the running desktop instance &#8211;&#62;
&#60;allow_external_access&#62;true&#60;/allow_external_access&#62;
&#60;port&#62;60009&#60;/port&#62; 端口
&#60;/configuration&#62;
（3）CrawlerConfiguration.xml 主要包括数据抓取和索引生成模块的设置
&#60;startlist&#62;
&#60;start index=&#8221;false&#8221; parse=&#8221;true&#8221;&#62;file://D:/SearchEngine/Data&#60;/start&#62;
关键参数！！！ [...]]]></description>
			<content:encoded><![CDATA[<p><strong>一、Regain简要介绍</strong><br />
regain是一款与Web搜索引擎类似的桌面搜索引擎系统，其不同之处在于regain不是对Internet内容的搜索，而是针对自己的文档或文件的搜索，使用regain可以轻松地在几秒内完成大量数据（许多个G）的搜索。<strong>Regain采用了Lucene的搜索语法，因此支持多种查询方式，支持多索引的搜索及基于文件类型的高级搜索，并且能实现URL重写及文件到HTTP的桥接，并且对中文也提供了较好的支持。</strong></p>
<p>Regain提供了两种版本：桌面搜索及服务器搜索。桌面搜索提供了对普通桌面计算机的文档与局域网环境下的网页的快速搜索。服务器版本主要安装在Web服务器上，为网站及局域网环境下的文件服务器进行搜索。</p>
<p>Regain使用Java编写，因此可以实现跨平台安装，能安装于Windows、Linux、Mac OS及Solaris上。服务器版本需要 JSPs环境及标签库（tag library），因此需要安装一个Tomcat容器。而桌面版自带了一个小型的Web服务器，安装非常简单。</p>
<p><strong>二、安装配置简介</strong><br />
大致知道了regain是什么以后，如果regain的功能正好是您需要的，那我们就来一起进行安装配置吧。<br />
1.下载regain最新版本。主页http://regain.sourceforge.net/<br />
如果只是安装使用的话，可以直接这里下载编译好的版本：http://regain.sourceforge.net/download.php 提供多种平台的最新稳定版本。如果是研究学习，或者想自己做优化修改，则建议下载带源码的版本：http://sourceforge.net /project/showfiles.php?group_id=111168</p>
<p>2.下载后解压到特定目录，本文范例以 e:\Devp\Java\JavaApp\regain 目录为解压目录</p>
<p>3.如果仅仅是下载编译好的版本安装试用的话，几乎都不需要什么设置，直接解压后，打开命令行窗口进入安装目录，直接运行<br />
<strong><br />
java -jar regain.jar </strong>命令行</p>
<p>运行后会在右下角systray系统托盘处出现regain的形状为“r”的小图标，右击会弹出search\status \Perferences菜单。直接选择Search就会打开查询页面。其实如果第一次运行，系统会自动弹出欢迎页面。Perferences设置页面可 以增加用户要索引的文件数据目录和web端口。</p>
<p>4.更多设置在conf目录中，主要设置文件包括如下4个文件，设置都非常简单直观<br />
现在把比较重要的设置稍做解释。</p>
<p>（1）SearchConfiguration.xml  主要包括查询模块的设置。<br />
&#8230;<br />
&lt;!&#8211; The search index &#8216;main&#8217; &#8211;&gt;<br />
&lt;index name=&#8221;main&#8221; default=&#8221;true&#8221; isparent=&#8221;true&#8221;&gt;<br />
&lt;!&#8211; The directory where the index is located &#8211;&gt;<br />
<strong> &lt;dir&gt;D:\SearchEngine\Index\regainindex&lt;/dir&gt;索引放置的目录</strong><br />
&lt;/index&gt;</p>
<p>（2）DesktopConfiguration.xml 主要包括本地桌面查询设置，可通过perferences页面设置。</p>
<p>&lt;configuration&gt;</p>
<p>&lt;!&#8211; The interval to update the search index in minutes &#8211;&gt;<br />
&lt;interval&gt;1440&lt;/interval&gt;</p>
<p>&lt;!&#8211; Allow/Disallow external access to the running desktop instance &#8211;&gt;<br />
&lt;allow_external_access&gt;true&lt;/allow_external_access&gt;</p>
<p><strong>&lt;port&gt;60009&lt;/port&gt; 端口</strong></p>
<p>&lt;/configuration&gt;</p>
<p>（3）CrawlerConfiguration.xml 主要包括数据抓取和索引生成模块的设置</p>
<p>&lt;startlist&gt;<br />
&lt;start index=&#8221;false&#8221; parse=&#8221;true&#8221;&gt;<strong>file://D:/SearchEngine/Data</strong>&lt;/start&gt;<br />
<strong>关键参数！！！ 设置用户需要进行索引的文档资料目录！可通过perferences页面设置。</strong><br />
&lt;/startlist&gt;</p>
<p>&lt;searchIndex&gt;<br />
&lt;!&#8211; The directory where the index should be located &#8211;&gt;<br />
<strong> &lt;dir&gt;D:\SearchEngine\Index\regainindex&lt;/dir&gt;索引放置的目录，同文件1的设置</strong></p>
<p>&lt;!&#8211;<br />
| Specifies the analyzer type to use.<br />
|<br />
| You may specify the class name of the analyzer or you use one of the<br />
| following aliases:<br />
|  * english: For the english language<br />
|    (alias for org.apache.lucene.analysis.standard.StandardAnalyzer)<br />
|  * german: For the german language<br />
|    (alias for org.apache.lucene.analysis.de.GermanAnalyzer)<br />
|  * <strong>paoding: 个人增加的paoding分词模块</strong><br />
|  * <strong>chinese: 个人增加的中文模块</strong><br />
+&#8211;&gt;<br />
<strong> &lt;analyzerType&gt;paoding&lt;/analyzerType&gt;<br />
默认是german，建议修改为english,<br />
当然最好就是替换成中文模块，我会在后面把整个替换步骤单独讲。</strong></p>
<p>&lt;!&#8211;<br />
| Contains all words that should not be indexed.<br />
| Separate the words by a blank.<br />
+&#8211;&gt;<br />
<strong> &lt;stopwordList/&gt;<br />
词语分割符号，实际相当于词法分析时做分割的词语列表。<br />
（默认的设置不是这样的，我修改是因为我已修改为中文分词模块，这个参数没什么必要！<br />
其实如果用户选择english，此参数也用途不大，因为默认是german分割符号）</strong></p>
<p>&lt;!&#8211;<br />
| Contains all words that should not be changed by an analyser when indexed.<br />
| Separate the words by a blank.<br />
+&#8211;&gt;<br />
<strong> &lt;exclusionList/&gt;生成索引时需要排除的词语列表(中文模块则此参数也没有什么必要)</strong></p>
<p>（4）log4j.properties<br />
日志输出配置</p>
<p>5.基本上上述设置后regain应该可以运行。<br />
regain是个不可多得的本地文件全文索引和快速全文搜索工具！虽然它也支持抓取互联网或者局域网页面数据进行索引。但是作为本地桌面全文搜索工具来讲，它比较专业精致，而且完美支持中文文件和中文目录。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/regain%e5%ae%89%e8%a3%85/regain%e5%ae%89%e8%a3%85%e9%85%8d%e7%bd%ae%e7%ae%80%e4%bb%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>lucene下进行文本索引</title>
		<link>http://www.xeie.cn/index.php/lucene%e6%96%87%e6%9c%ac%e7%b4%a2%e5%bc%95/lucene%e4%b8%8b%e8%bf%9b%e8%a1%8c%e6%96%87%e6%9c%ac%e7%b4%a2%e5%bc%95/</link>
		<comments>http://www.xeie.cn/index.php/lucene%e6%96%87%e6%9c%ac%e7%b4%a2%e5%bc%95/lucene%e4%b8%8b%e8%bf%9b%e8%a1%8c%e6%96%87%e6%9c%ac%e7%b4%a2%e5%bc%95/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:41:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[lucene文本索引]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=314</guid>
		<description><![CDATA[lucene是一个用java开发的开源文本索引和检索API。为了进一步阅读本文中即将阐述的索引技术，你需要对lucene的索引结构有个大致 的了解。正如我在本系列的以前的文章中提到的，一个典型的lucene索引存储在硬盘的文件系统的某个目录(directory)中。
lucene中一个索引的核心元素包括片段(segment)，文档(document)，字段(field)，条目(term)等。每个索引 (index)包含一到多个片段，每个片段包含一到多个文档，每个文档包含一到多个字段，每个字段包含一到多个条目，每个条目是对字段进行描述的键值对。 一个片段由一系列的文件 (file)组成，构成片段的文件的确切数字因不同的索引(index)而不同，取决于索引中字段的数目。同一片段的所有文件共享通用的前缀，通过不同的 后缀区分他们。你可以把片段假想为一个子索引，虽然片段不是一个完全独立的索引。
-rw-rw-r--    1 otis     otis            4   Nov 22 22:43 deletable
-rw-rw-r--    1 otis     otis      1000000   Nov 22 22:43 [...]]]></description>
			<content:encoded><![CDATA[<p>lucene是一个用java开发的开源文本索引和检索API。为了进一步阅读本文中即将阐述的索引技术，你需要对lucene的索引结构有个大致 的了解。正如我在本系列的以前的文章中提到的，一个典型的lucene索引存储在硬盘的文件系统的某个目录(directory)中。<br />
lucene中一个索引的核心元素包括片段(segment)，文档(document)，字段(field)，条目(term)等。每个索引 (index)包含一到多个片段，每个片段包含一到多个文档，每个文档包含一到多个字段，每个字段包含一到多个条目，每个条目是对字段进行描述的键值对。 一个片段由一系列的文件 (file)组成，构成片段的文件的确切数字因不同的索引(index)而不同，取决于索引中字段的数目。同一片段的所有文件共享通用的前缀，通过不同的 后缀区分他们。你可以把片段假想为一个子索引，虽然片段不是一个完全独立的索引。</p>
<pre>-rw-rw-r--    1 otis     otis            4   Nov 22 22:43 deletable
-rw-rw-r--    1 otis     otis      1000000   Nov 22 22:43 _lfyc.f1
-rw-rw-r--    1 otis     otis      1000000   Nov 22 22:43 _lfyc.f2
-rw-rw-r--    1 otis     otis     31030502   Nov 22 22:28 _lfyc.fdt
-rw-rw-r--    1 otis     otis      8000000   Nov 22 22:28 _lfyc.fdx
-rw-rw-r--    1 otis     otis           16   Nov 22 22:28 _lfyc.fnm
-rw-rw-r--    1 otis     otis   1253701335   Nov 22 22:43 _lfyc.frq
-rw-rw-r--    1 otis     otis   1871279328   Nov 22 22:43 _lfyc.prx
-rw-rw-r--    1 otis     otis        14122   Nov 22 22:43 _lfyc.tii
-rw-rw-r--    1 otis     otis      1082950   Nov 22 22:43 _lfyc.tis
-rw-rw-r--    1 otis     otis           18   Nov 22 22:43 segments

示例1：只包含了一个片段的索引
注意所有属于该片段的文件(file)拥有相同的前缀:_lfyc。因为这个索引包含两个字段，你会注意到有两个
文件具有满足fN模式的后缀(例中：f1和f2)，如果这个索引有3个字段，那么肯定有一个文件的名称是<code>_lfyc.f3。
一旦索引完全建好了，片段的数目也就固定了，但是</code><code>该数目会在</code><code>索引创建过程中变化。当新的文档(document)
加入到索引的时候，lucene会增加片段，并且片段的合并也频繁发生。在下一部分中会介绍如何控制片段的添加
和合并以便提高索引速度。
更多关于文件(files)创建索引(index)的信息可以查阅在lucene的站点中的文件格式的文档。你也可以在这篇文
章的</code><a href="http://www.onjava.com/pub/a/onjava/2003/03/05/lucene.html?page=2#references">参考</a><code>部分找到。
<span style="font-weight: bold;">索引加速的要素
</span>以前的文章中介绍了如何使用</code><code>LuceneIndexExample类索引文本。因为那个例子太基础了，没有必要考虑索引速度
问题。而如果你要在重要的应用中使用lucene，可能就想确定最佳索引性能。典型的文本检索的瓶颈发生在向硬盘
中写入索引文件的过程中。因此，在索引文档的过程中，我们需要指导lucene能智能的增加和合并索引片段。
当新的文档被加入到一个lucene索引中时，它们先被存储在内存中而不是立即写入到硬盘中，这是出于性能的考虑。
提高lucene索引性能的最简单的方法是调整</code><code>IndexWriter类的</code><code>mergeFactor成员变量的值，这个配置值告诉lucene在
写入硬盘之前在内存中存储多少文档，还能控制多个片段</code><code>合并</code><code>到一起的频率。默认值为10的情况下，在写入到硬盘
中的一个片段中之前，lucene会存储10个文档在内存中，同样在</code><code>mergeFactor</code><code>默认值等于10的情况下，硬盘上片段的
数量达到10个的时候，lucene会合并这些片段到一个片段中（这时可能会抛出一个异常，我会在后面解释）。
例如，如果我们设置</code><code>mergeFactor=10，每加入10个文档(document)到索引(index)中就会在硬盘中添加一个片段
(segment)，当第10个大小为10的片段(包含10个文档的片段)被创建时，这10个片段中包含的100个文档将会被合并为
一个片段，以此类推，当10个大小为100的片段被创建（确切说是被合并）时，这10个片段就会被合并成1个大小为1000
的片段，因此在任何时间，一个索引中都不会超过9个片段。
前面提到的异常需要另一个成员变量来处理：</code><code>maxMergeDocs。当合并片段的时候，lucene会确信创建的片段没有超过
</code><code>阈值maxMergeDocs。例如：如果我们设置</code><code>maxMergeDocs等于1000，当我们增加10000个文档的时候，lucene会创建第10
个大小为1000的片段并且每添加1000个文档保持片段的大小为1000而不是把10个大小为1000的片段为一个大小为10000
的片段。
</code><code>maxMergeDocs的默认值是常量</code><code>#MAX_VALUE，以我的经验，该值几乎不需要调整。
现在我解释一下</code><code>mergeFactor和</code><code>maxMergeDocs如何工作，你会看到</code><code>mergeFactor设置的越大，将会占用越多的内存资源，
当然会减少向磁盘中写入的次数，进而加快索引的速度。相反，</code><code>mergeFactor值设置的越小，内存占用就越少，会造成
索引被频繁的更新，使得索引保持比较新的状态，当然就会减慢索引进程。相似的，</code><code>maxMergeDocs越大，对批量索引
就越适合，相反，</code><code>maxMergeDocs值越小，越适合互动的索引。
为了更好的感觉</code><code>mergeFactor和</code><code>maxMergeDocs</code>对索引速度的不同影响，让我们来看看下面的<code>IndexTuningDemo类，这个类
在命令行下有三个参数：要加入到索引中的文档数目，</code><code>mergeFactor配置项的值，</code><code>maxMergeDocs配置项的值，所有的参数
必须要指定，必须为数字，并且必须按照这个顺序，为了使代码简短、清晰，没有对不正常调用的检查。
</code></pre>
<p>import org.apache.lucene.index.IndexWriter;<span><br />
</span>import org.apache.lucene.analysis.Analyzer;<span><br />
</span>import org.apache.lucene.analysis.StopAnalyzer;<span><br />
</span>import org.apache.lucene.document.Document;<span><br />
</span>import org.apache.lucene.document.Field;</p>
<pre><code>/**
 * 在临时文件夹中创建一个叫'index'的索引.
 * 加入索引中的文档数, mergeFactor 和
 * maxMergeDocs <strong>必须</strong> 在命令行中按顺序指定
 * - 这个类期望被以正确的方式调用.
 *
 * 注意: 在第一次运行的时候, 手动创建
 *  'index'文件夹到临时目录中.
 */</code>
<code>public class IndexTuningDemo
{
    public static void main(String[] args) throws Exception
    {
        int docsInIndex  = Integer.parseInt(args[0]);

        // create an index called 'index' in a temporary directory
        String indexDir =
            System.getProperty("java.io.tmpdir", "tmp") +
            System.getProperty("file.separator") + "index";

        Analyzer    analyzer = new StopAnalyzer();
        IndexWriter writer   = new IndexWriter(indexDir, analyzer, true);

        // set variables that affect speed of indexing
        writer.mergeFactor   = Integer.parseInt(args[1]);
        writer.maxMergeDocs  = Integer.parseInt(args[2]);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i &lt; docsInIndex; i++)
        {
            Document doc = new Document();
            doc.add(Field.Text("fieldname", "Bibamus, moriendum est"));
            writer.addDocument(doc);
        }
        writer.close();
        long stopTime = System.currentTimeMillis();
        System.out.println("Total time: " + (stopTime - startTime) + " ms");
    }
}

下面是输出结果：

</code><code>prompt&gt; time java IndexTuningDemo 100000 10 1000000

Total time: 410092 ms

real    6m51.801s
user    5m30.000s
sys     0m45.280s

prompt&gt; time java IndexTuningDemo 100000 1000 100000

Total time: 249791 ms

real    4m11.470s
user    3m46.330s
sys     0m3.660s

正如你看到的，两个调用都创建了一个包含100000文档的索引，可第一个花费的时间要长，这是因为第一个调用中
</code><code>mergeFactor设定的是默认值10，使得lucene写入磁盘的频率比第二个（</code><code>mergeFactor=1000</code><code>）要高。
注意，这两个值在提升lucene索引性能的同时，同样会影响lucene所用的文件描述符的数量，能够导致抛出</code>
"Too many open files"异常，如果发生这个错误，你首先需要考虑如果你能优化索引，那么这将在稍后进行阐述。
优化对多于一个片段的索引有帮助，如果优化索引没有解决这个问题，你应该尝试增加你的计算机中允许打开的最
大文件数的值，这个通常在操作系统级进行调整，并且调节方法因操作系统而异。如果你在UNIX系统下使用lucene，
你可以通过命令行获知允许打开的最大文件数。
在bash下你可以通过内建的ulimit命令：
<code>prompt&gt; ulimit -n</code>
<span>
</span>在<code>tcsh</code>下，该命令对应为:</pre>
<p><code><span style="font-family: 新宋体;">prompt&gt; limit descriptors</span></code></p>
<p>在<code><span style="font-family: 新宋体;">bash下改变此值</span></code>, 如下:</p>
<p><code><span style="font-family: 新宋体;">prompt&gt; ulimit -n &lt;允许打开的最大文件数&gt;</span></code></p>
<p><span style="font-family: 新宋体;"><span>在</span><code>tcsh下</code></span>, 调整如下:</p>
<p><code><span style="font-family: 新宋体;">prompt&gt; limit descriptors &lt;允许打开的最大文件数&gt;</span></code></p>
<pre>为了为索引进程估计一个允许打开的最大文件数的设置值，记住lucene在索引过程中将要打开的文件的最大数可以
通过<code>(1 + mergeFactor) * FilesPerSegment公式计算出来。
例如：在mergeFactor默认值等于10，并且索引1000000文档的前提下，在一个未经优化的索引中，lucene会打开110
个文件，在调用了IndexWriter的optimize()方法的时候，所有的片段将被合并为1个片段，将会减少lucene需要打
开文件的数目。

<span style="font-weight: bold;">内存中索引
</span>前面我提到了，新的文档加入索引首先先保存在内存中，而不是立即写入到硬盘上，你也看到了如何通过改变</code><code>
IndexWriter成员变量控制保存到内存中的文件比率，lucene的分发包（源码）中包含了一个RAMDirctory类，
可以提供索引中更多控制，跟FSDirectory类一样，这个类也实现了Directory接口，只不过FSDirctory存储索引
文档到硬盘上，而RAMDirectory存储到内存中。
由于RAMDirectory不是把所有东西都写到硬盘上，因此速度比FSDirectory更快。但是，通常计算机中的内存容量
要比硬盘小，因此RAMDirectory对大规模的索引不太适合。
下面的</code><code>MemoryVsDisk</code> 类将对如何使用RAMDirectory作为内存级的缓存以提升索引速度进行示范。

<code>import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import java.io.IOException;

</code><code>/**
 * 在临时文件夹中创建一个叫'index'的索引.
 * 加入索引中的文档数, mergeFactor 和
 * maxMergeDocs <strong>必须</strong> 在命令行中按顺序指定
 * - 这个类期望被以正确的方式调用.
 *
 * 注意: 在第一次运行的时候, 手动创建'index'文件夹到临时目录中.</code><code>
 * 另外, 如果第四个命令行参数是 '-r' 此类
 * 将在最后写入磁盘之前先将所有文档索引在RAMDirectory中，
 * 如果要使用常规的FSDirectory，请把第四个命令行参数设为'-f'
 *
 * 注意: 第一次运行时需要在临时文件夹中手动创建 'index'目录.
 */
public class MemoryVsDisk
{
    public static void main(String[] args) throws Exception
    {
        int docsInIndex  = Integer.parseInt(args[0]);

        // 在临时文件夹中创建一个'index'索引
        String indexDir =
            System.getProperty("java.io.tmpdir", "tmp") +
            System.getProperty("file.separator") + "index";

        Analyzer analyzer  = new StopAnalyzer();
        long     startTime = System.currentTimeMillis();

        if ("-r".equalsIgnoreCase(args[3]))
        {
            // 如果指定 -r 参数, 使用 RAMDirectory
            RAMDirectory ramDir    = new RAMDirectory();
            IndexWriter  ramWriter = new IndexWriter(ramDir, analyzer, true);
            addDocs(ramWriter, docsInIndex);
            IndexWriter fsWriter   = new IndexWriter(indexDir, analyzer, true);
            fsWriter.addIndexes(new Directory[] { ramDir });
            ramWriter.close();
            fsWriter.close();
        }
        else
        {
            // 使用FSDirectory创建索引
            IndexWriter fsWriter  = new IndexWriter(indexDir, analyzer, true);
            fsWriter.mergeFactor  = Integer.parseInt(args[1]);
            fsWriter.maxMergeDocs = Integer.parseInt(args[2]);
            addDocs(fsWriter, docsInIndex);
            fsWriter.close();
        }

        long stopTime = System.currentTimeMillis();
        System.out.println("Total time: " + (stopTime - startTime) + " ms");
    }

    private static void addDocs(IndexWriter writer, int docsInIndex)
        throws IOException
    {
        for (int i = 0; i &lt; docsInIndex; i++)
        {
            Document doc = new Document();
            doc.add(Field.Text("fieldname", "Bibamus, moriendum est"));
            writer.addDocument(doc);
        }
    }
}</code></pre>
<p>使用 <code><span style="font-family: 新宋体;">FSDirectory</span></code>创建一个包含 10,000 文档的索引 , 如下:</p>
<p><code><span style="font-family: 新宋体;">prompt&gt; time java MemoryVsDisk 10000 10 100000 -f</p>
<p>Total time: 41380 ms<br />
real 0m42.739s<br />
user 0m36.750s<br />
sys 0m4.180s</span></code></p>
<p>使用 <code><span style="font-family: 新宋体;">RAMDirectory</span></code>,更快的创建一个同样大小的索引，调用 <code><span style="font-family: 新宋体;">MemoryVsDisk</span></code> 如下:</p>
<p><code><span style="font-family: 新宋体;">prompt&gt; time java MemoryVsDisk 10000 10 100000 -r<br />
Total time: 27325 ms<br />
real 0m28.695s<br />
user 0m27.920s<br />
sys 0m0.610s</span></code></p>
<p>注意：通过选择一个更合适的<code><span style="font-family: 新宋体;">mergeFactor</span></code>值，你可以达到相同的甚至更快的索引速度</p>
<p><span style="font-family: 新宋体;"><code>prompt&gt; time java MemoryVsDisk 10000 1000 100000 -f<br />
Total time: 24724 ms<br />
real 0m26.108s<br />
user 0m25.280s<br />
sys 0m0.620s</p>
<p>在你调节</code><code>mergeFactor值的时候要注意，如果超过了JVM运行的最大内存的阈值，将会抛出</code><code>java.lang.OutOfMemoryError异常</code></span></p>
<pre>最后，不要忘了，通过为JVM分配足够多的内存，可以极大的提升所有java程序的运行效率。
<code>prompt&gt; time java -Xmx300MB -Xms200MB MemoryVsDisk 10000 10 100000 -r

Total time: 15166 ms
real    0m17.311s
user    0m15.400s
sys     0m1.590s

<span style="font-weight: bold;">合并索引
</span>当你通过调节</code><code>IndexWriter类的</code><code>mergeFactor</code> 和 <code>maxMergeDocs成员变量提升lucene的索引速度已经满足不了需要的时候，
你可以使用</code><code>RAMDirectory创建内存级的索引，你也可以创建多线程的索引程序，使用多个基于</code><code>RAMDirectory的索引进行
并行处理，每一个在一个线程中，通过使用</code><code>IndexWriter的</code><code>addIndexes(Directory[])方法在硬盘上把他们合并为一个索引。
再往更深的层次考虑，一个复杂的索引应用可以在多个并行的计算机上创建基于内存的索引。

<span style="font-weight: bold;">在多线程的环境下构建索引
</span>多线程或者进程可以同时对同一索引进行检索，而同一时间只能有一个线程或进程对同一索引进行修改。如果你的多线程的
应用使用多个线程向同一索引中加入文档，你必须将他们对</code><code>IndexWriter.addDocument(Document)方法的调用序列化，放任
非序列化的调用会导致修改索引时发生冲突，使lucene抛出意想不到的异常。另外，为了防止滥用，lucene使用文件锁禁止
多线程或者进程在同一时间对同一索引目录创建</code><code>IndexWriter类。
例如，下面的代码

</code><code>import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.StopAnalyzer;

/**
 * 示范Lucene通过加锁避免多进程在同一时间向同一索引执行写操作
 * 注意: 在第一次运行之前，需要在临时文件夹中手动创建'index'目录.
 */
public class DoubleTrouble
{
    public static void main(String[] args) throws Exception
    {
        // create an index called 'index' in a temporary directory
        String indexDir =
            System.getProperty("java.io.tmpdir", "tmp") +
            System.getProperty("file.separator") + "index";

        Analyzer    analyzer     = new StopAnalyzer();
        IndexWriter firstWriter  = new IndexWriter(indexDir, analyzer, true);

        // the following line will cause an exception
        IndexWriter secondWriter = new IndexWriter(indexDir, analyzer, false);

        // the following two lines will never even be reached
        firstWriter.close();
        secondWriter.close();
    }
}

会导致下面的异常：
</code><code>Exception in thread "main" java.io.IOException:
        Index locked for write: Lock@/tmp/index/write.lock
        at org.apache.lucene.index.IndexWriter.&lt;init&gt;(IndexWriter.java:145)
        at org.apache.lucene.index.IndexWriter.&lt;init&gt;(IndexWriter.java:122)
        at DoubleTrouble.main(DoubleTrouble.java:23)

<span style="font-weight: bold;">索引优化
</span>在这篇文章中我已经提到优化索引很多次了，可我还没有详细的对此进行解释。若要优化索引，你需要调用IndexWriter实例的
optimize()方法，调用发生时，所有内存中的文档将被写入到硬盘上，所有的片段将被合并为一个，减少索引中的文件数目，
不过，索引优化不会提高索引进程的性能，相反，还会使得索引的速度减慢，即便如此，为了使打开文件的数目得到控制，优化
有时是很有必要的。例如，在索引进程工作的时候优化索引可能需要考虑索引进程和检索进程并行工作的情况，虽然这两个进程都
单独维护自己打开的文件集。一个好的规则是，如果不久会有更多的文档被加入到索引中，就要避免调用optimize()方法，另一方面，
如果你知道该索引会在很长一段时间内不被修改，该索引只是被检索，你需要优化它，这样会减少片段的数量</code><code>(在硬盘上的文件数)，
于是就会提升检索性能，在检索时，lucene打开的文件越少，检索速度越快。
下面使用</code><code>IndexOptimizeDemo类讲解optimize起到的效果：

</code><code>import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

/**
 * Creates an index called 'index' in a temporary directory.
 * If you want the index to optimize the index at the end use '-o'
 * command line argument.  If you do not want to optimize the index
 * at the end use any other value for the command line argument.
 * This class expects to be called correctly.
 *
 * Note: before running this for the first time, manually create the
 * directory called 'index' in your temporary directory.
 */
public class IndexOptimizeDemo
{
    public static void main(String[] args) throws Exception
    {
        // create an index called 'index' in a temporary directory
        String indexDir =
            System.getProperty("java.io.tmpdir", "tmp") +
            System.getProperty("file.separator") + "index";

        Analyzer    analyzer = new StopAnalyzer();
        IndexWriter writer   = new IndexWriter(indexDir, analyzer, true);

        for (int i = 0; i &lt; 15; i++)
        {
            Document doc = new Document();
            doc.add(Field.Text("fieldname", "Bibamus, moriendum est"));
            writer.addDocument(doc);
        }
        if ("-o".equalsIgnoreCase(args[0]))
        {
            System.out.println("Optimizing the index...");
            writer.optimize();
        }
        writer.close();
    }
}</code>
<code>从类的代码中你可以看到，只有-o参数被指定时创建的索引才被优化，如果要创建一个没有被优化的索引，如下：

</code><code>prompt&gt; java IndexOptimizeDemo -n</code>

<code>-rw-rw-r--    1 otis     otis           10 Feb 18 23:50 _a.f1
-rw-rw-r--    1 otis     otis          260 Feb 18 23:50 _a.fdt
-rw-rw-r--    1 otis     otis           80 Feb 18 23:50 _a.fdx
-rw-rw-r--    1 otis     otis           14 Feb 18 23:50 _a.fnm
-rw-rw-r--    1 otis     otis           30 Feb 18 23:50 _a.frq
-rw-rw-r--    1 otis     otis           30 Feb 18 23:50 _a.prx
-rw-rw-r--    1 otis     otis           11 Feb 18 23:50 _a.tii
-rw-rw-r--    1 otis     otis           41 Feb 18 23:50 _a.tis
-rw-rw-r--    1 otis     otis            4 Feb 18 23:50 deletable
-rw-rw-r--    1 otis     otis            5 Feb 18 23:50 _g.f1
-rw-rw-r--    1 otis     otis          130 Feb 18 23:50 _g.fdt
-rw-rw-r--    1 otis     otis           40 Feb 18 23:50 _g.fdx
-rw-rw-r--    1 otis     otis           14 Feb 18 23:50 _g.fnm
-rw-rw-r--    1 otis     otis           15 Feb 18 23:50 _g.frq
-rw-rw-r--    1 otis     otis           15 Feb 18 23:50 _g.prx
-rw-rw-r--    1 otis     otis           11 Feb 18 23:50 _g.tii
-rw-rw-r--    1 otis     otis           41 Feb 18 23:50 _g.tis
-rw-rw-r--    1 otis     otis           22 Feb 18 23:50 segments</code>
<code>
</code><em>实例2: 一个没有被优化的索引通常包含比第一个更多的文件，</em><em><em>这个索引包含了两个片段
</em></em>
如果要对索引进行完全优化，如下：
<code>prompt&gt; java IndexOptimizeDemo -o</code>

<code>-rw-rw-r--    1 otis     otis            4 Feb 18 23:50 deletable
-rw-rw-r--    1 otis     otis           15 Feb 18 23:50 _h.f1
-rw-rw-r--    1 otis     otis          390 Feb 18 23:50 _h.fdt
-rw-rw-r--    1 otis     otis          120 Feb 18 23:50 _h.fdx
-rw-rw-r--    1 otis     otis           14 Feb 18 23:50 _h.fnm
-rw-rw-r--    1 otis     otis           45 Feb 18 23:50 _h.frq
-rw-rw-r--    1 otis     otis           45 Feb 18 23:50 _h.prx
-rw-rw-r--    1 otis     otis           11 Feb 18 23:50 _h.tii
-rw-rw-r--    1 otis     otis           41 Feb 18 23:50 _h.tis
-rw-rw-r--    1 otis     otis           15 Feb 18 23:50 segments</code> 

<em>示例 3: 一个完全优化的索引只包含了一个片段.

</em></pre>
<h3><a>结论</a></h3>
<p>该文章讨论了lucene索引的基本结构并且示范了提高索引性能的一些技术，你还可以认识到在多线程环境下进行索引的一些潜在的问题，如何优化索 引，对索引进程有什么影响，这些知识可以让你更好的控制lucene的索引进程以便提高它的性能，下篇文章中将介绍lucene的文本检索能力.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/lucene%e6%96%87%e6%9c%ac%e7%b4%a2%e5%bc%95/lucene%e4%b8%8b%e8%bf%9b%e8%a1%8c%e6%96%87%e6%9c%ac%e7%b4%a2%e5%bc%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Jakarta Lucene文本检索</title>
		<link>http://www.xeie.cn/index.php/apache-jakarta-lucene/apache-jakarta-lucene%e6%96%87%e6%9c%ac%e6%a3%80%e7%b4%a2/</link>
		<comments>http://www.xeie.cn/index.php/apache-jakarta-lucene/apache-jakarta-lucene%e6%96%87%e6%9c%ac%e6%a3%80%e7%b4%a2/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:39:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache Jakarta Lucene]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=312</guid>
		<description><![CDATA[Lucene是一个可以为应用添加文本索引和检索功能的Java类库。它不是一个可以下载、安装、运行的完整应用， 它提供了一个简单但功能强大的核心API。你仅需要知道一些Lucene类和方法就可以踏上使用的道路了。
Lucene主要提供了两个服务：文本索引，文本检索。这两个功能互相相对独立，虽然索引不用说影响着检索。这篇文章我将专注于讲解文本索引，我们会看到提供文本索引功能的一些核心lucene类。
Lucene背景
Lucene最初是由Doug Cutting开发的，可以通过SourceForge(传说中的SF)下载到。作为服务器端的开源java产品于2001年9月份加入了apache软 件基金会的jakarta家族。从那时发布的每一个版本，这个项目都吸引了越来越多的用户和开发者。2002年11月Lucene Version1.2发布了，1.3版本开发中。通过那些标注为&#8220;Powered by Lucene&#8221;的组织，我听说了FedEx，Overture, Mayo Clinic, Hewlett Packard, New Scientist magazine, Epiphany等等正在使用，至少在评估Lucene。
Lucene安装
跟其他jakarta项目一样，Lucene以预编译二进制或源码的形式发布。从Lucene的发布页你可以下载到最新的Lucene版本。如果你喜欢使 用最新的特性，还有当日最新版提供。为了示范Lucene的用法，我假想大家都在使用预编译版本，直接下载Lucene.jar把它加入到你的 CLASSPATH环境变量中。如果你选择下载源码包，自己进行编译，那么你需要jakarta ant 和javaCC，这两个也是免费提供下载的。虽然开发javaCC的公司已经不存在了，你仍然可以从本文参考部分找到下载的URL。
Lucene索引
在转向代码之前，先让我们看一看Lucene用于文本索引的主要Java类，它们是IndexWriter，Analyzer，Document和 Field。IndexWriter用于创建新索引和添加文档到存在的索引中去。文本被索引之前，先被传递给Analyzer，Analyzers负责从 要索引的文本中提取可索引的令牌符号，把不可索引的剔除掉。Lucene有一些不同的Analyzer实现，其中的一些负责对无意义的终止字符（一些对区 分文档没有帮助的经常用到的诸如&#8221;a&#8221;,&#8221;an&#8221;,&#8221;the&#8221;,&#8221;in&#8221;,&#8221;the&#8221;等单词）做跳过处理，一些负责把令牌词处理成小写，以便检索时可以做到大小写不敏感，还有一些其他的不赘述了。
索引是文档的集合，文档是字段的集合，每个字段有名称（key，键）和内容(value，值)。考虑到一个文档对应RDBMS（关系型数据库管理系统）中表的一行，一个字段对应表的那一行的某一列。
现在，让我们假定一个简单的场景，你有一些文本需要索引，这些文本存储在一个字符串实例变量中，下面我们使用一个java类来描述上述的场景。

import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

/**
 * LuceneIndexExample 类提供了一个简单的使用lucene进行索引的例子
 * 它在一个临时目录中创建了一个名称为"index-1"的新索引，
 * 每次调用向该索引中添加一个包含一个字段的文档
 */
public class LuceneIndexExample
{
    public static void main(String args[]) throws Exception
    {
     [...]]]></description>
			<content:encoded><![CDATA[<p>Lucene是一个可以为应用添加文本索引和检索功能的Java类库。它不是一个可以下载、安装、运行的完整应用， 它提供了一个简单但功能强大的核心API。你仅需要知道一些Lucene类和方法就可以踏上使用的道路了。<br />
Lucene主要提供了两个服务：文本索引，文本检索。这两个功能互相相对独立，虽然索引不用说影响着检索。这篇文章我将专注于讲解文本索引，我们会看到提供文本索引功能的一些核心lucene类。<br />
<span style="font-weight: bold;">Lucene背景</span><br />
Lucene最初是由<span>Doug Cutting开发的，可以通过SourceForge(传说中的SF)下载到。作为服务器端的开源java产品于2001年9月份加入了apache软 件基金会的jakarta家族。从那时发布的每一个版本，这个项目都吸引了越来越多的用户和开发者。2002年11月Lucene Version1.2发布了，1.3版本开发中。通过那些标注为</span><span>&#8220;Powered by Lucene&#8221;的组织，我听说了FedEx，</span><span>Overture, Mayo Clinic, Hewlett Packard, New Scientist magazine, Epiphany等等正在使用，至少在评估Lucene。<br />
Lucene安装<br />
跟其他jakarta项目一样，Lucene以预编译二进制或源码的形式发布。从Lucene的发布页你可以下载到最新的Lucene版本。如果你喜欢使 用最新的特性，还有当日最新版提供。为了示范Lucene的用法，我假想大家都在使用预编译版本，直接下载Lucene.jar把它加入到你的 CLASSPATH环境变量中。如果你选择下载源码包，自己进行编译，那么你需要jakarta ant 和javaCC，这两个也是免费提供下载的。虽然开发javaCC的公司已经不存在了，你仍然可以从本文参考部分找到下载的</span><span>URL</span><span>。<br />
Lucene索引<br />
在转向代码之前，先让我们看一看Lucene用于文本索引的主要Java类，它们是IndexWriter，Analyzer，Document和 Field。IndexWriter用于创建新索引和添加文档到存在的索引中去。文本被索引之前，先被传递给Analyzer，Analyzers负责从 要索引的文本中提取可索引的令牌符号，把不可索引的剔除掉。Lucene有一些不同的Analyzer实现，其中的一些负责对无意义的终止字符（一些对区 分文档没有帮助的经常用到的诸如&#8221;a&#8221;,&#8221;an&#8221;,&#8221;the&#8221;,&#8221;in&#8221;,&#8221;the&#8221;等单词）</span><span>做跳过处理</span><span>，一些负责把令牌词处理成小写，以便检索时可以做到大小写不敏感，还有一些其他的不赘述了。<br />
索引是文档的集合，文档是字段的集合，每个字段有名称（key，键）和内容(value，值)。考虑到一个文档对应RDBMS（关系型数据库管理系统）中表的一行，一个字段对应表的那一行的某一列。<br />
现在，让我们假定一个简单的场景，你有一些文本需要索引，这些文本存储在一个字符串实例变量中，下面我们使用一个java类来描述上述的场景。<br />
</span></p>
<pre><code>import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

/**
 * LuceneIndexExample 类提供了一个简单的使用lucene进行索引的例子
 * 它在一个临时目录中创建了一个名称为</code><code>"index-1"</code><code>的新索引，
 * 每次调用向该索引中添加一个包含一个字段的文档
 */
public class LuceneIndexExample
{
    public static void main(String args[]) throws Exception
    {
        String text = "This is the text to index with Lucene";

        String indexDir =
            System.getProperty("java.io.tmpdir", "tmp") +
            System.getProperty("file.separator") + "index-1";
        Analyzer analyzer = new StandardAnalyzer();
        boolean createFlag = true;

        IndexWriter writer =
            new IndexWriter(indexDir, analyzer, createFlag);
        Document document  = new Document();
        document.add(Field.Text("fieldname", text));
        writer.addDocument(document);
        writer.close();
    }
}</code></pre>
<p>让我们来安步分析这组代码，lucene将索引存储在硬盘的文件系统中，每个索引在一个单独的目录中存储，多个索引不能共享一个目录，<span><span style="font-family: Arial;"><code>IndexWriter</code>构 造类的第一个参数指定了索引应该存储的目录，第二个参数提供了用来预处理存储前被索引的文本的Analizer类的实现类，Analyzer类的特殊实现 类消除噪音单词，转换令牌词为小写，并且对输入的文本进行细微的修饰（诸如从缩写字中消除周期），最后一个参数是个布尔变量，当为真(true)的时候， 告诉IndexWriter在指定的目录中创建新的索引或者覆盖已经存在的索引，如果为假(false)的时候，告诉IndexWriter不要添加文档 到一个已经存在的索引中。当我们创建一个新的空文档时，添加一个名称为fieldname的字段到文档中，包含一个我们将要索引的文本值。文档填充好以 后，使用IndexWriter的addDocument方法把它加入到索引中去，最后关闭IndexWriter实例，这一点很重要，因为它指示把索引 的改动保存到硬盘中。<br />
分析器(Analyzers)<br />
我在上文提到过，Analizer是对输入的文本进行预处理的部件。检索的时候也能用的到。因为搜索字符串也需要以处理索引文本的方式进行处理。对索引和检索来说，使用相同的Analyzer是很重要的，不同的Analyzer会导致得到不正确的结果。<br />
Analyzer类是一个抽象类，但是Lucene提供了一些实现类以便对输入的文本进行不同的预处理。如果你要实现的索引文本和查询串预处理方式 Lucene没有提供，那么需要实现Analyzer类以便对需求自定义。例如，如果你要索引非拉丁语系的文本，就需要自定义Analyzer实现类。</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/apache-jakarta-lucene/apache-jakarta-lucene%e6%96%87%e6%9c%ac%e6%a3%80%e7%b4%a2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Solr实现企业搜索</title>
		<link>http://www.xeie.cn/index.php/apache-solr%e4%bc%81%e4%b8%9a%e6%90%9c%e7%b4%a2/apache-solr%e5%ae%9e%e7%8e%b0%e4%bc%81%e4%b8%9a%e6%90%9c%e7%b4%a2/</link>
		<comments>http://www.xeie.cn/index.php/apache-solr%e4%bc%81%e4%b8%9a%e6%90%9c%e7%b4%a2/apache-solr%e5%ae%9e%e7%8e%b0%e4%bc%81%e4%b8%9a%e6%90%9c%e7%b4%a2/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:37:57 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache Solr企业搜索]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=309</guid>
		<description><![CDATA[基于 Lucene 搜索引擎并且在 Apache Software License 许可下以开源形式提供，Solr 是（根据 Lucene 站点）“基于 Lucene Java™ 搜索库、配有 XML/HTTP 和 JSON API、命中结果突出显示、分面组配式搜索、缓存、复制和 Web 管理界面的开源企业搜索服务器”。
其中值得注意的是，大流量的 Web 站点、Netflix、Digg 和 CNET 的 News.com 和 CNET Reviews 使用 Solr 来增强搜索功能。由 Solr 驱动的公共站点的长串列表可以在 Solr 维基中找到（请参阅 参考资料）。
了解如何使用 Solr 和 PHP 创建搜索汽车零部件数据库的小型应用程序。虽然示例数据库只是包含一些记录，但是它轻轻松松就能包含数百万条记录。本文中使用的所有源代码均可从 下载 部分获得。
安装 Solr
要将 Solr 与 PHP 结合使用，您必须安装 Solr，设计索引，准备 Solr 要索引的数据，载入索引，编写执行查询的 PHP 代码和显示结果。创建可搜索索引所需的大部分工作可以通过命令行执行。当然，Solr 的 PHP 编程接口也会影响索引的内容。
Solr [...]]]></description>
			<content:encoded><![CDATA[<p>基于 <a href="http://lucene.apache.org/">Lucene<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> 搜索引擎并且在 Apache Software License 许可下以开源形式提供，Solr 是（根据 Lucene 站点）“基于 Lucene Java™ 搜索库、配有 XML/HTTP 和 JSON API、命中结果突出显示、分面组配式搜索、缓存、复制和 Web 管理界面的开源企业搜索服务器”。</p>
<p>其中值得注意的是，大流量的 Web 站点、Netflix、Digg 和 CNET 的 News.com 和 CNET Reviews 使用 Solr 来增强搜索功能。由 Solr 驱动的公共站点的长串列表可以在 Solr 维基中找到（请参阅 <a href="http://www.javajia.com/index.php#resources">参考资料<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a>）。</p>
<p>了解如何使用 Solr 和 PHP 创建搜索汽车零部件数据库的小型应用程序。虽然示例数据库只是包含一些记录，但是它轻轻松松就能包含数百万条记录。本文中使用的所有源代码均可从 <a href="http://www.javajia.com/index.php#download">下载<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> 部分获得。</p>
<p><a name="install"><span>安装 Solr</span></a></p>
<p>要将 Solr 与 PHP 结合使用，您必须安装 Solr，设计索引，准备 Solr 要索引的数据，载入索引，编写执行查询的 PHP 代码和显示结果。创建可搜索索引所需的大部分工作可以通过命令行执行。当然，Solr 的 PHP 编程接口也会影响索引的内容。</p>
<p>Solr 是用 Java 技术实现的。要运行 Solr 及其管理工具，您必须安装 Java V1.5 软件开发包 (Java 5 SDK)。几个提供商都提供了 Java V1.5 SDK —— 例如，<a href="http://java.sun.com/j2se/downloads.html">Sun Microsystems<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a>、<a href="http://www.ibm.com/developerworks/java/jdk/">IBM®                 <img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> 和 <a href="http://www.bea.com/jrockit/">BEA Systems<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> —— 并且每个实现都能够驱动 Solr。只需选择适用于您的操作系统的 Java 包并遵循相应的说明来完成安装。</p>
<p>在 许多情况下，安装 Java V1.5 就像运行自提取归档和接受许可证协议条款一样简单。归档中的脚本在几秒钟内就能完成所有大部分艰巨任务。其他操作系统（例如 Debian）将在 APT 系统库中提供 Java 5 SDK。例如，如果使用 Debian 或 Ubuntu，则可以用 <code>sudo apt-get install sun-java5-jdk</code> 安装 Java V1.5 软件。</p>
<p>APT 还将自动下载使用 Java 5 SDK 所需的所有依赖性，非常方便。</p>
<p>如果 Java 软件已经安装并且 Java 可执行文件已在 <code>PATH</code> 中，请运行 <code>java -version</code> 来确定拥有的 Java 代码。</p>
<p>在 这里，让我们使用 Mac OS X V10.5 Leopard 操作系统作为演示的基础。Apple 的 Leopard 附带了 Java V1.5。只要对 Apache 的默认配置进行微小更改，Leopard 也可以运行 PHP 应用程序。在 Leopard 终端窗口中运行 <code>java -version</code> 将生成以下输出。<br />
<a name="list1"><strong>清单 1. 在 Leopard 终端窗口中运行 <code>java -version</code> </strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>$ which java
/usr/bin/java

$ java -version
java version "1.5.0_13"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05-237)
Java HotSpot(TM) Client VM (build 1.5.0_13-119, mixed mode, sharing)</pre>
</td>
</tr>
</tbody>
</table>
<p><strong>注</strong>：Leopard 将允许您在 /Applications/Utilities/Java 的 Java Preferences 应用程序中的 Java V1.4 与 V1.5 之间来回切换。如果 Leopard 安装显示 V1.4，则打开 Java Preferences 并按照图 1 所示更改设置。<br />
<a name="N100E5"><strong>图 1. Leopard 中的 Java Preferences 应用程序</strong></a><br />
<img src="http://www.ibm.com/developerworks/cn/opensource/os-php-apachesolr/javaprefs.jpg" alt="Leopard 中的 Java Preferences 应用程序" width="280" height="354" /></p>
<p>要安装 Solr，请访问 <a href="http://lucene.apache.org/solr/">Apache.org<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a>，单击 <strong>Resources &gt; Download</strong>，选择一个方便访问的项目镜像，并且在所示文件夹内浏览选择 Solr V1.2 的 tarball（.tgz 文件）。下载将传输名称类似 <em>apache-solr-1.2.0.tgz</em> 的文件。用下列代码解压缩 tarball。<br />
<a name="list2"><strong>清单 2. 解压缩 tarball</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>$ tar xzf apache-solr-1.2.0.tgz

$ ls -F apache-solr-1.2.0
CHANGES.txt NOTICE.txt  dist/ lib/
KEYS.txt  README.txt  docs/   src/
LICENSE.txt build.xml example/</pre>
</td>
</tr>
</tbody>
</table>
<p>在新创建的目录中，名为 <em>dist</em> 的文件夹包含绑定为 Java 归档 (JAR) 的 Solr 代码。子目录 example/exampledocs 包含已经格式化的数据示例 —— 通常为 XML 代码 —— 并且准备好供 Solr 索引。</p>
<p><em>example</em> 目录包含一个完整的样例 Solr 应用程序。要运行它，只需用应用程序归档 start.jar 启动 Java 引擎。<br />
<a name="list3"><strong>清单 3. 启动 Java 引擎</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>$ java -jar start.jar
2007-11-10 15:00:16.672::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2007-11-10 15:00:16.866::INFO:  jetty-6.1.3
...
INFO: SolrUpdateServlet.init() done
2007-11-10 15:00:18.694::INFO:  Started SocketConnector @ 0.0.0.0:8983</pre>
</td>
</tr>
</tbody>
</table>
<p>应用程序现在可以在 8983 端口上使用。启动浏览器并在地址栏中键入 <code>http://localhost:8983/solr/admin/</code>。这是用于管理 Solr 的接口（要停止 Solr 服务器，请在命令行中键入 <strong>Ctrl+C</strong> 组合键）。</p>
<p>但是 Solr 索引中还没有数据可供管理或查询。</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" align="right">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif%22" alt="" width="100%" height="4" /></p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif%22" border="0" alt="" width="16" height="16" /></td>
<td align="right" valign="top"><a href="http://www.javajia.com/index.php#main"><strong>回页首</strong><img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><a name="load"><span>把数据装入 Solr</span></a></p>
<p>Solr 非常灵活，支持创建有效索引的各种数据类型和规则。而且虽然 Solr 支持数据类型和规则十分广泛，但是如果标准组件不够用，还可以通过编写新的 Java 类进一步自定义 Solr。</p>
<p>给定一组数据类型和规则，您就可以创建一个 Solr 模式来描述数据和控制应当怎样构造索引。然后导出数据来匹配模式并将数据装入 Solr。Solr 将动态创建索引，在记录被创建、修改或删除时立即更新每个索引。</p>
<p>可以在 <a href="http://svn.apache.org/viewvc/lucene/solr/trunk/example/solr/conf/schema.xml?view=markup">Apache.org<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> 的 Solr 源代码库中找到默认的 Solr 模式。为供参考，下面显示了默认模式的代码片段。<br />
<a name="list3"><strong>清单 3. 默认的 Solr 模式代码片段</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>&lt;schema name="example" version="1.1"&gt;
  ...
  &lt;fields&gt;
  &lt;field name="id" type="string" indexed="true" stored="true" required="true" /&gt;
  &lt;field name="name" type="text" indexed="true" stored="true"/&gt;
  &lt;field name="nameSort" type="string" indexed="true" stored="false"/&gt;
  &lt;field name="cat" type="text" indexed="true" stored="true" multiValued="true"/&gt;
  ...
  &lt;/fields&gt;

  &lt;uniqueKey&gt;id&lt;/uniqueKey&gt;
  ...
  &lt;copyField source="name" dest="nameSort"/&gt;
  ...
&lt;/schema&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>模式的大部分内容都无需加以说明，但是有一些方面需要注意：</p>
<ul>
<li>如示，字段 <code>id</code> 是字符串 (<code>type="string"</code>) 并且应当被索引 (<code>indexed="true"</code>)。它也是一个必需字段 (<code>required="true"</code>)。使用此模式，载入 Solr 的每条记录必须为这个字段提供值。<code>&lt;uniqueKey&gt;id&lt;/uniqueKey&gt;</code> 修饰词进一步说明 <code>id</code> 字段必须惟一（Solr 不要求 ID 字段惟一；这只是在默认索引模式中建立的规则）。属性 <code>stored="true"</code> 表示 <code>id</code> 字段应当可检索。为什么不把 <code>stored</code> 设为 <code>false</code>？您可以使用不可检索的字段来以不同方式给结果排序，比方说使用 <code>nameSort</code>，它是 <code>name</code> 字段的副本（最后一行中的 <code>copyField</code> 命令），但是行为不同。注意，<code>nameSort</code> 是 <code>string</code>，而 <code>name</code> 是 <code>text</code>。默认索引模式将采取稍微不同的方式来处理这两种类型。</li>
<li>字段 <code>cat</code> 是 <code>multiValued</code>。记录可以为此字段定义多个值。例如，如果应用程序管理内容，则可以给一篇文章指定多个标题。您可以使用 <code>cat</code> 字段（或者自定义类似字段）来捕捉所有标题。</li>
</ul>
<p>清单 4 显示了 example/exampledocs/ipod_other.xml 文件，该文件表示 iPod 附件分类中的两个条目。<br />
<a name="list4"><strong>清单 4. 为默认 Solr 索引模式格式化的数据</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>&lt;add&gt;
&lt;doc&gt;
  &lt;field name="id"&gt;F8V7067-APL-KIT&lt;/field&gt;
  &lt;field name="name"&gt;Belkin Mobile Power Cord for iPod w/ Dock&lt;/field&gt;
  &lt;field name="manu"&gt;Belkin&lt;/field&gt;
  &lt;field name="cat"&gt;electronics&lt;/field&gt;
  &lt;field name="cat"&gt;connector&lt;/field&gt;
  &lt;field name="features"&gt;car power adapter, white&lt;/field&gt;
  &lt;field name="weight"&gt;4&lt;/field&gt;
  &lt;field name="price"&gt;19.95&lt;/field&gt;
  &lt;field name="popularity"&gt;1&lt;/field&gt;
  &lt;field name="inStock"&gt;false&lt;/field&gt;
&lt;/doc&gt;

&lt;doc&gt;
  &lt;field name="id"&gt;IW-02&lt;/field&gt;
  &lt;field name="name"&gt;iPod &amp; iPod Mini USB 2.0 Cable&lt;/field&gt;
  &lt;field name="manu"&gt;Belkin&lt;/field&gt;
  &lt;field name="cat"&gt;electronics&lt;/field&gt;
  &lt;field name="cat"&gt;connector&lt;/field&gt;
  &lt;field name="features"&gt;car power adapter for iPod, white&lt;/field&gt;
  &lt;field name="weight"&gt;2&lt;/field&gt;
  &lt;field name="price"&gt;11.50&lt;/field&gt;
  &lt;field name="popularity"&gt;1&lt;/field&gt;
  &lt;field name="inStock"&gt;false&lt;/field&gt;
&lt;/doc&gt;
&lt;/add&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p><code>add</code> 元素是用于将封装记录添加到索引中的 Solr 命令。每条记录都将被捕捉到 <code>doc</code> 元素中，该元素将使用一组名为 <code>field</code> 的元素来指定字段值。字段 <code>weight</code>、<code>price</code>、<code>inStock</code>、<code>manu</code>、<code>features</code> 和 <code>popularity</code> 都是在默认 Solr 索引模式中定义的其他字段。<code>features</code> 字段拥有与 <code>cat</code> 相同的属性，但是语义不同：它列举了产品的功能，数量可能较多。</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td></td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" align="right">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif%22" alt="" width="100%" height="4" /></p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif%22" border="0" alt="" width="16" height="16" /></td>
<td align="right" valign="top"><a href="http://www.javajia.com/index.php#main"><strong>回页首</strong><img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><a name="autoparts"><span>搜索汽车零部件</span></a></p>
<p>本例将索引汽车零部件集。每个汽车零部件都有多个字段，表 1 中显示了最重要的字段样例。第一列中列出了字段名。第二列将提供简要描述，而第三列将列出逻辑类型。第四列将显示用于表示数据的索引类型（按照 <a href="http://www.javajia.com/index.php#list5">清单 5<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> 的模式中的定义）。<br />
<a name="table1"><strong>表 1. 汽车零部件记录的字段</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" summary="The fields of an auto part record">
<tbody>
<tr>
<th>名称</th>
<th>描述</th>
<th>类型</th>
<th>Solr 类型</th>
</tr>
<tr>
<td>部件号（惟一，强制）</td>
<td>标识号</td>
<td>字符串</td>
<td><code>partno</code></td>
</tr>
<tr>
<td>名称</td>
<td>简要描述</td>
<td>字符串</td>
<td><code>name</code></td>
</tr>
<tr>
<td>型号（必需，多值）</td>
<td>型号，例如 “Camaro”</td>
<td>字符串</td>
<td><code>model</code></td>
</tr>
<tr>
<td>型号年份（多值）</td>
<td>型号年份，例如 2001</td>
<td>字符串</td>
<td><code>year</code></td>
</tr>
<tr>
<td>价格</td>
<td>单价</td>
<td>浮点</td>
<td><code>price</code></td>
</tr>
<tr>
<td>库存</td>
<td>是否有存货</td>
<td>布尔</td>
<td><code>inStock</code></td>
</tr>
<tr>
<td>功能</td>
<td>零部件的功能</td>
<td>字符串</td>
<td><code>features</code></td>
</tr>
<tr>
<td>时间标记</td>
<td>活动记录</td>
<td>字符串</td>
<td><code>timestamp</code></td>
</tr>
<tr>
<td>重量</td>
<td>装运重量</td>
<td>浮点</td>
<td><code>weight</code></td>
</tr>
</tbody>
</table>
<p>清单 3 显示了汽车零部件索引所使用的 Solr 模式部分。它大部分都是基于默认 Solr 模式。使用的具体字段 —— 名称和属性 —— 只是替换了在默认模式中找到的 <code>fields</code> 元素（如 <a href="http://www.javajia.com/index.php#list1">清单 1<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a> 中所示）。<br />
<a name="list5"><strong>清单 5. 汽车零部件索引模式</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;schema name="autoparts" version="1.0"&gt;
  ...
  &lt;fields&gt;
    &lt;field name="partno" type="string" indexed="true"
    stored="true" required="true" /&gt; 

    &lt;field name="name" type="text" indexed="true"
    stored="true" required="true" /&gt;

    &lt;field name="model" type="text_ws" indexed="true" stored="true"
    multiValued="true" required="true" /&gt;

    &lt;field name="year" type="text_ws" indexed="true" stored="true"
    multiValued="true" omitNorms="true" /&gt;

    &lt;field name="price"  type="sfloat" indexed="true"
    stored="true" required="true" /&gt;

    &lt;field name="inStock" type="boolean" indexed="true"
     stored="true" default="false" /&gt; 

    &lt;field name="features" type="text" indexed="true"
    stored="true" multiValued="true" /&gt;

    &lt;field name="timestamp" type="date" indexed="true"
    stored="true" default="NOW" multiValued="false" /&gt;

    &lt;field name="weight" type="sfloat" indexed="true" stored="true" /&gt;
  &lt;/fields&gt;

  &lt;uniqueKey&gt;partno&lt;/uniqueKey&gt;

  &lt;defaultSearchField&gt;name&lt;/defaultSearchField&gt;
&lt;/schema&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>针对以上字段，需要将汽车零部件数据库导出并格式化以上传到 Solr 中，如清单 6 所示。<br />
<a name="list6"><strong>清单 6. 为进行索引而格式化的汽车零部件数据库</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>&lt;add&gt;
&lt;doc&gt;
  &lt;field name="partno"&gt;1&lt;/field&gt;
  &lt;field name="name"&gt;Spark plug&lt;/field&gt;
  &lt;field name="model"&gt;Boxster&lt;/field&gt;
  &lt;field name="model"&gt;924&lt;/field&gt;
  &lt;field name="year"&gt;1999&lt;/field&gt;
  &lt;field name="year"&gt;2000&lt;/field&gt;
  &lt;field name="price"&gt;25.00&lt;/field&gt;
  &lt;field name="inStock"&gt;true&lt;/field&gt;
&lt;/doc&gt;
&lt;doc&gt;
  &lt;field name="partno"&gt;2&lt;/field&gt;
  &lt;field name="name"&gt;Windshield&lt;/field&gt;
  &lt;field name="model"&gt;911&lt;/field&gt;
  &lt;field name="year"&gt;1991&lt;/field&gt;
  &lt;field name="year"&gt;1999&lt;/field&gt;
  &lt;field name="price"&gt;15.00&lt;/field&gt;
  &lt;field name="inStock"&gt;false&lt;/field&gt;
&lt;/doc&gt;
&lt;/add&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>让我们安装新索引模式并把数据装入 Solr。首先，通过使用 <strong>Ctrl+C</strong> 组合键来停止 Solr 守护进程（如果它仍在运行）。在 example/solr/conf/schema.xml 中制作现有 Solr 模式的归档。接下来，通过清单 6 创建一个文本文件，将其保存到 /tmp/schema.xml 中，然后复制到 example/solr/conf/schema.xml 中。为清单 7 中所示的数据创建另一个文件。现在，您可以重新启动 Solr 并使用示例所提供的 posting 实用程序。<br />
<a name="list7"><strong>清单 7. 启用带有新模式的 Solr</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>$ cd apache-solr-1.2/example
$ cp solr/conf/schema.xml solr/conf/default_schema.xml
$ chmod a-w solr/conf/default_schema.xml

$ vi /tmp/schema.xml
...
$ cp /tmp/schema.xml solr/conf/schema.xml

$ vi /tmp/parts.xml
...

$ java -jar start.jar
...
2007-11-11 16:56:48.279::INFO:  Started SocketConnector @ 0.0.0.0:8983

$ java -jar exampledocs/post.jar /tmp/parts.xml
SimplePostTool: version 1.2
SimplePostTool: WARNING: Make sure your XML documents are encoded in UTF-8,
  other encodings are not currently supported
SimplePostTool: POSTing files to http://localhost:8983/solr/update...
SimplePostTool: POSTing file parts.xml
SimplePostTool: COMMITting Solr index changes...</pre>
</td>
</tr>
</tbody>
</table>
<p>成功！如果需要检验索引是否存在并包含两个文档，请将浏览器再次指向 http://localhost:8983/solr/admin/。您应当会在页面顶部看到 “(autoparts)”。如果看到了，请单击页面中间的查询框并键入 <code>partno: 1 or partno: 2</code>。</p>
<p>结果应当类似下面的内容：</p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<pre>3 on 10 0 partno: 1 OR partno: 2 2.2
true Boxster 924 Spark plug 1 25.0 2007-11-11T21:58:45.899Z 1999 2000
false 911 Windshield 2 15.0 2007-11-11T21:58:45.953Z 1991 1999</pre>
</td>
</tr>
</tbody>
</table>
<p>尝试其他一些查询。Lucene 维基中介绍了 Lucene 查询（Solr 中的搜索引擎）的语法（请参阅 <a href="http://www.javajia.com/index.php#resources">参考资料<img src="http://i.ixnp.com/images/v6.16/t.gif" alt="" /></a>）。</p>
<p>您还应当尝试再次编辑和载入数据。由于声明了 <code>partno</code> 字段惟一，因此重复上传同一个部件号将只用新记录替换旧索引记录。除了 <code>add</code> 命令之外，您还可以使用 <code>commit</code>、<code>optimize</code> 和 <code>delete</code>。最后一个命令可以按照 ID 删除一条特定记录，也可以通过查询删除多条记录。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/apache-solr%e4%bc%81%e4%b8%9a%e6%90%9c%e7%b4%a2/apache-solr%e5%ae%9e%e7%8e%b0%e4%bc%81%e4%b8%9a%e6%90%9c%e7%b4%a2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Solr项目介绍</title>
		<link>http://www.xeie.cn/index.php/apache-solr/apache-solr%e9%a1%b9%e7%9b%ae%e4%bb%8b%e7%bb%8d/</link>
		<comments>http://www.xeie.cn/index.php/apache-solr/apache-solr%e9%a1%b9%e7%9b%ae%e4%bb%8b%e7%bb%8d/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:37:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache Solr]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=307</guid>
		<description><![CDATA[Apache Solr项目，是一款基于Apache Lucene的开源企业搜索服务器，最近发布了1.3版。InfoQ采访了Solr的创建者Yonik Seeley，了解了新版本的更多信息和Solr提供给最终用户的功能。
Seeley首先描述了目标用户：“需要搜索框、分面浏览（导航）或者两者结合的任何人”，Solr的关键特性包括：
* 基于标准的开放接口——Solr搜索服务器支持通过XML、JSON和HTTP查询和获取结果。
* 易管理——Solr可以通过HTML页面管理，服务器统计数据以JMX输出，Solr配置通过XML完成。
* 分面浏览——搜索结果自动分类。
* 突出显示命中词——匹配的字符自动在搜索结果中高亮显示。
* 可伸缩性——快速增量更新和快照分发/复制到其他服务器。
* 灵活的插件体系——新功能能够以插件的形式方便的添加到Solr服务器上。
Seeley同时谈到了该版本中的主要新功能：
* 分布式搜索——索引现在可以透明的分割成多个部分，单个Solr服务器基于各个配置和模式支持多索引，无须停止Solr服务器就可以改动主要的配置。
* 扩展了查询功能——包含了一个新的Java客户端（SolrJ）和若干新功能，例如直接配置对于特定查询哪些文档首先命中、近似命中、搜索过期、记录分面时间和拼写检查
* 增强了数据导入工具——数据库和其他结构化数据源现在都可以导入、映射和转化。
* 更多可定制扩展点——存在一个新的更新处理器链，允许在查询时修改和重定向文档；一个搜索组件链修改和添加查询结果、用户查询分析器和插件式功能。
* 性能增强——显著提高了索引速度，二进制响应格式和快速查询删除功能。
详细的更新日志可以这里获得。
Seeley谈到了更多Solr在伸缩性、功能和实用性方面的细节：
Solr已经部署过数以百万计容量的文档，如果借助分布式搜索，Solr应该能够处理数十亿的文档集合。
Solr基于Lucene，具有优秀的全文相关性，可以很方便的提供词组接近性增强、近期文档增强、编辑增强和基于数字值的专有函数的定制评分机制。
AOL正在使用Solr增强它的频道功能：音乐、橄榄球运动、食谱、参考中心、房地产和汽车都使用这项技术。Solr的搜索功能也应用于Netflix、 Zappos、Gamespot、和Internet Archive。还有很多大客户我目前还不能透漏。
关于Solr的未来计划，Seeley提到了更多的可扩展性、对大集群更方便的配置和管理、基于区域和实时的搜索、重构以使用Spring配置插件。Seeley同时提供了一个邮件列表，在那里他详细讨论了Solr未来、特别是2.0版的计划。
]]></description>
			<content:encoded><![CDATA[<p>Apache Solr项目，是一款基于Apache Lucene的开源企业搜索服务器，最近发布了1.3版。InfoQ采访了Solr的创建者Yonik Seeley，了解了新版本的更多信息和Solr提供给最终用户的功能。</p>
<p>Seeley首先描述了目标用户：“需要搜索框、分面浏览（导航）或者两者结合的任何人”，Solr的关键特性包括：</p>
<p>* 基于标准的开放接口——Solr搜索服务器支持通过XML、JSON和HTTP查询和获取结果。<br />
* 易管理——Solr可以通过HTML页面管理，服务器统计数据以JMX输出，Solr配置通过XML完成。<br />
* 分面浏览——搜索结果自动分类。<br />
* 突出显示命中词——匹配的字符自动在搜索结果中高亮显示。<br />
* 可伸缩性——快速增量更新和快照分发/复制到其他服务器。<br />
* 灵活的插件体系——新功能能够以插件的形式方便的添加到Solr服务器上。</p>
<p>Seeley同时谈到了该版本中的主要新功能：</p>
<p>* 分布式搜索——索引现在可以透明的分割成多个部分，单个Solr服务器基于各个配置和模式支持多索引，无须停止Solr服务器就可以改动主要的配置。<br />
* 扩展了查询功能——包含了一个新的Java客户端（SolrJ）和若干新功能，例如直接配置对于特定查询哪些文档首先命中、近似命中、搜索过期、记录分面时间和拼写检查<br />
* 增强了数据导入工具——数据库和其他结构化数据源现在都可以导入、映射和转化。<br />
* 更多可定制扩展点——存在一个新的更新处理器链，允许在查询时修改和重定向文档；一个搜索组件链修改和添加查询结果、用户查询分析器和插件式功能。<br />
* 性能增强——显著提高了索引速度，二进制响应格式和快速查询删除功能。</p>
<p>详细的更新日志可以这里获得。</p>
<p>Seeley谈到了更多Solr在伸缩性、功能和实用性方面的细节：</p>
<p>Solr已经部署过数以百万计容量的文档，如果借助分布式搜索，Solr应该能够处理数十亿的文档集合。</p>
<p>Solr基于Lucene，具有优秀的全文相关性，可以很方便的提供词组接近性增强、近期文档增强、编辑增强和基于数字值的专有函数的定制评分机制。</p>
<p>AOL正在使用Solr增强它的频道功能：音乐、橄榄球运动、食谱、参考中心、房地产和汽车都使用这项技术。Solr的搜索功能也应用于Netflix、 Zappos、Gamespot、和Internet Archive。还有很多大客户我目前还不能透漏。</p>
<p>关于Solr的未来计划，Seeley提到了更多的可扩展性、对大集群更方便的配置和管理、基于区域和实时的搜索、重构以使用Spring配置插件。Seeley同时提供了一个邮件列表，在那里他详细讨论了Solr未来、特别是2.0版的计划。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/apache-solr/apache-solr%e9%a1%b9%e7%9b%ae%e4%bb%8b%e7%bb%8d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>apache lucene 的核心类</title>
		<link>http://www.xeie.cn/index.php/apache-lucene%e6%a0%b8%e5%bf%83%e7%b1%bb/apache-lucene-%e7%9a%84%e6%a0%b8%e5%bf%83%e7%b1%bb-2/</link>
		<comments>http://www.xeie.cn/index.php/apache-lucene%e6%a0%b8%e5%bf%83%e7%b1%bb/apache-lucene-%e7%9a%84%e6%a0%b8%e5%bf%83%e7%b1%bb-2/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 03:35:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[apache lucene核心类]]></category>

		<guid isPermaLink="false">http://www.xeie.cn/?p=305</guid>
		<description><![CDATA[下边介绍一下lucene的核心类：(参考lucene in action)
主要有两部分组成，核心索引类和核心搜索类，顾名思意，就是用来建立索引和用来搜索的类。
IndexWriter：可以对索引进行写操作，但不能读取或者搜索。是唯一能写索引的类。
Directory：Directory 类代表一个Lucene索引的位置。它是一个抽象类，允许它的子类(其中的两个包含在Lucene中)在合适时存储索引。在我们的Indexer示例中， 我们使用一个实际文件系统目录的路径传递给IndexWriter的构造函数来获得Directory的一个实例。IndexWriter然后使用 Directory的一个具体实现FSDirectory，并在文件系统的一个目录中创建索引。在你的应用程序中，你可能较喜欢将Lucene索引存储在 磁盘上。这时可以使用FSDirectory，一个包含文件系统真实文件列表的Driectory子类，如同我们在Indexer中一样。另一个 Directory的具体子类是RAMDirectory。尽管它提供了与FSDirectory相同的接口，RAMDirectory将它的所有数据加 载到内存中。所以这个实现对较小索引很有用处，可以全部加载到内存中并在程序关闭时销毁。因为所有数据加载到快速存取的内存中而不是在慢速的硬盘 上，RAMDirectory适合于你需要快速访问索引的情况，不管是索引或搜索。做为实例，Lucene的开发者在所有他们的单元测试中做了扩展使用： 当测试运行时，快速的内存驻留索引被创建搜索，当测试结束时，索引自动销毁，不会在磁盘上留下任何残余。当然，在将文件缓存到内存的操作系统中使用时 RAMDirectory和FSDirectory之间的性能差别较小
Analyzer:分析文本内容，提取关键字
Document:一个Document代表字段的集合。你可以把它想象为以后可获取的虚拟文档—一块数据，如一个网页、一个邮件消息或一个文本文件。一个文档的字段代表这个文档或与这个文档相关的元数据
Field:在索引中的每个Document含有一个或多个字段，具体化为Field类。每个字段相应于数据的一个片段，将在搜索时查询或从索引中重新获取。
Lucene提供四个不同的字段类型，你可以从中做出选择：
Keyword—不被分析，但是被索引并逐字存储到索引中。这个类型适合于原始值需要保持原样的字段，如URL、文件系统路径、日期、个人名称、社会安全号码、电话号码等等。例如，我们在Indexer(列表1.1)中把文件系统路径作为Keyword字段。
UnIndexed —不被分析也不被索引，但是它的值存储到索引中。这个类型适合于你需要和搜索结果一起显示的字段(如URL或数据库主键)，但是你从不直接搜索它的值。因 为这种类型字段的原始值存储在索引中，这种类型不适合于存放比较巨大的值，如果索引大小是个问题的话。
UnStored—和UnIndexed相反。这个字段类型被分析并索引但是不存储在索引中。它适合于索引大量的文本而不需要以原始形式重新获得它。例如网页的主体或任休其它类型的文本文档。
Text —被分析并索引。这就意味着这种类型的字段可以被搜索，但是要小心字段大小。如果要索引的数据是一个String，它也被存储；但如果数据(如我们的 Indexer例子)是来自一个Reader，它就不会被存储。这通常是混乱的来源，所以在使用Field.Text时要注意这个区别。
所有字段由名称和值组成。你要使用哪种字段类型取决于你要如何使用这个字段和它的值。严格来说，Lucene只有一个字段类型：以各自特征来区分的字段。有些是被分析的，有些不是；有些是被索引，然面有些被逐字地存储等等。
注 意 注意Field.Text(String, String)和Field.Text(String, Reader)之间的区别。String变量存储字段数据，而Reader变量不存储。为索引一个String而又不想存储它，可以用 Field.UnStored(String, String)
下边是核心搜索类：
IndexSearcher：IndexSearcher 用来搜索而IndexWriter用来索引：暴露几个搜索方法的索引的主要链接。你可以把IndexSearcher想象为以只读方式打开索引的一个类。 它提供几个搜索方法，其中一些在抽象基类Searcher中实现；最简单的接受单个Query对象做为参数并返回一个Hits对象。这个方法的典型应用类 似这样：
IndexSearcher is = new IndexSearcher(
FSDirectory.getDirectory(“/tmp/index”, false));
Query q = new TermQuery(new Term(“contents”, “lucene”));
Hits hits = is.search(q);
Term:
Term是搜索的基本单元。与Field对象类似，它由一对字符串元素组成：字段的名称和字段的值。注意Term对象也和索引过程有关。但是它们是由Lucene内部生成，所以在索引时你
一般不必考虑它们。在搜索时，你可能创建Term对象并TermQuery同时使用。
Query q = new TermQuery(new Term(“contents”, “lucene”));
Hits hits = is.search(q);
这段代码使Lucene找出在contents字段中含有单词lucene的所有文档。因为TermQuery对象继承自它的抽象父类Query，你可以在等式的左边用Query类型。
Query
Lucene 中包含一些Query的具体子类。到目前为止，在本章中我们仅提到过最基本的Lucene Query：TermQuery。其它Query类型有BooleanQuery，PhraseQuery, PrefixQuery, PhrasePrefixQuery, RangeQuery, FilteredQuery和SpanQuery
TermQuery
TermQuery是Lucene支持的最基本的查询类型，并且它也是最原始的查询类型之一。它用来匹配含有指定值的字段的文档.
Hits类是一个搜索结果(匹配给定查询的文档)文档队列指针的简单容器。基于性能考虑，Hits的实例并不从索引中加载所有匹配查询的所有文档，而是每次一小部分
]]></description>
			<content:encoded><![CDATA[<p>下边介绍一下lucene的核心类：(参考lucene in action)<br />
主要有两部分组成，核心索引类和核心搜索类，顾名思意，就是用来建立索引和用来搜索的类。</p>
<p>IndexWriter：可以对索引进行写操作，但不能读取或者搜索。是唯一能写索引的类。</p>
<p>Directory：Directory 类代表一个Lucene索引的位置。它是一个抽象类，允许它的子类(其中的两个包含在Lucene中)在合适时存储索引。在我们的Indexer示例中， 我们使用一个实际文件系统目录的路径传递给IndexWriter的构造函数来获得Directory的一个实例。IndexWriter然后使用 Directory的一个具体实现FSDirectory，并在文件系统的一个目录中创建索引。在你的应用程序中，你可能较喜欢将Lucene索引存储在 磁盘上。这时可以使用FSDirectory，一个包含文件系统真实文件列表的Driectory子类，如同我们在Indexer中一样。另一个 Directory的具体子类是RAMDirectory。尽管它提供了与FSDirectory相同的接口，RAMDirectory将它的所有数据加 载到内存中。所以这个实现对较小索引很有用处，可以全部加载到内存中并在程序关闭时销毁。因为所有数据加载到快速存取的内存中而不是在慢速的硬盘 上，RAMDirectory适合于你需要快速访问索引的情况，不管是索引或搜索。做为实例，Lucene的开发者在所有他们的单元测试中做了扩展使用： 当测试运行时，快速的内存驻留索引被创建搜索，当测试结束时，索引自动销毁，不会在磁盘上留下任何残余。当然，在将文件缓存到内存的操作系统中使用时 RAMDirectory和FSDirectory之间的性能差别较小</p>
<p>Analyzer:分析文本内容，提取关键字</p>
<p>Document:一个Document代表字段的集合。你可以把它想象为以后可获取的虚拟文档—一块数据，如一个网页、一个邮件消息或一个文本文件。一个文档的字段代表这个文档或与这个文档相关的元数据</p>
<p>Field:在索引中的每个Document含有一个或多个字段，具体化为Field类。每个字段相应于数据的一个片段，将在搜索时查询或从索引中重新获取。<br />
Lucene提供四个不同的字段类型，你可以从中做出选择：</p>
<p>Keyword—不被分析，但是被索引并逐字存储到索引中。这个类型适合于原始值需要保持原样的字段，如URL、文件系统路径、日期、个人名称、社会安全号码、电话号码等等。例如，我们在Indexer(列表1.1)中把文件系统路径作为Keyword字段。</p>
<p>UnIndexed —不被分析也不被索引，但是它的值存储到索引中。这个类型适合于你需要和搜索结果一起显示的字段(如URL或数据库主键)，但是你从不直接搜索它的值。因 为这种类型字段的原始值存储在索引中，这种类型不适合于存放比较巨大的值，如果索引大小是个问题的话。</p>
<p>UnStored—和UnIndexed相反。这个字段类型被分析并索引但是不存储在索引中。它适合于索引大量的文本而不需要以原始形式重新获得它。例如网页的主体或任休其它类型的文本文档。</p>
<p>Text —被分析并索引。这就意味着这种类型的字段可以被搜索，但是要小心字段大小。如果要索引的数据是一个String，它也被存储；但如果数据(如我们的 Indexer例子)是来自一个Reader，它就不会被存储。这通常是混乱的来源，所以在使用Field.Text时要注意这个区别。<br />
所有字段由名称和值组成。你要使用哪种字段类型取决于你要如何使用这个字段和它的值。严格来说，Lucene只有一个字段类型：以各自特征来区分的字段。有些是被分析的，有些不是；有些是被索引，然面有些被逐字地存储等等。<br />
注 意 注意Field.Text(String, String)和Field.Text(String, Reader)之间的区别。String变量存储字段数据，而Reader变量不存储。为索引一个String而又不想存储它，可以用 Field.UnStored(String, String)</p>
<p>下边是核心搜索类：<br />
IndexSearcher：IndexSearcher 用来搜索而IndexWriter用来索引：暴露几个搜索方法的索引的主要链接。你可以把IndexSearcher想象为以只读方式打开索引的一个类。 它提供几个搜索方法，其中一些在抽象基类Searcher中实现；最简单的接受单个Query对象做为参数并返回一个Hits对象。这个方法的典型应用类 似这样：</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" alt="" align="top" /><span style="color: #000000;">IndexSearcher is </span><span style="color: #000000;">=</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> IndexSearcher(<br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" alt="" align="top" />FSDirectory.getDirectory(“</span><span style="color: #000000;">/</span><span style="color: #000000;">tmp</span><span style="color: #000000;">/</span><span style="color: #000000;">index”, </span><span style="color: #0000ff;">false</span><span style="color: #000000;">));<br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" alt="" align="top" />Query q </span><span style="color: #000000;">=</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> TermQuery(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Term(“contents”, “lucene”));<br />
<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" alt="" align="top" />Hits hits </span><span style="color: #000000;">=</span><span style="color: #000000;"> is.search(q);</span></div>
<p>Term:<br />
Term是搜索的基本单元。与Field对象类似，它由一对字符串元素组成：字段的名称和字段的值。注意Term对象也和索引过程有关。但是它们是由Lucene内部生成，所以在索引时你<br />
一般不必考虑它们。在搜索时，你可能创建Term对象并TermQuery同时使用。<br />
Query q = new TermQuery(new Term(“contents”, “lucene”));<br />
Hits hits = is.search(q);<br />
这段代码使Lucene找出在contents字段中含有单词lucene的所有文档。因为TermQuery对象继承自它的抽象父类Query，你可以在等式的左边用Query类型。</p>
<p>Query<br />
Lucene 中包含一些Query的具体子类。到目前为止，在本章中我们仅提到过最基本的Lucene Query：TermQuery。其它Query类型有BooleanQuery，PhraseQuery, PrefixQuery, PhrasePrefixQuery, RangeQuery, FilteredQuery和SpanQuery</p>
<p>TermQuery<br />
TermQuery是Lucene支持的最基本的查询类型，并且它也是最原始的查询类型之一。它用来匹配含有指定值的字段的文档.</p>
<p>Hits类是一个搜索结果(匹配给定查询的文档)文档队列指针的简单容器。基于性能考虑，Hits的实例并不从索引中加载所有匹配查询的所有文档，而是每次一小部分</p>
]]></content:encoded>
			<wfw:commentRss>http://www.xeie.cn/index.php/apache-lucene%e6%a0%b8%e5%bf%83%e7%b1%bb/apache-lucene-%e7%9a%84%e6%a0%b8%e5%bf%83%e7%b1%bb-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
