1 、 Solr 简介

Solr 是一个基于 Lucene 的 Java 搜索引擎服务器。 Solr 提供了层面搜索、命中醒目显示并且支持多种输出格式(包括 XML/XSLT 和 JSON 格式)。它易于安装和配置,而且附带了一个基于 HTTP 的管理界面。 Solr 已经在众多大型的网站中使用,较为成熟和稳定。 Solr 包装并扩展了 Lucene ,所以 Solr 的基本上沿用了 Lucene 的相关术语。更重要的是, Solr 创建的索引与 Lucene 搜索引擎库完全兼容。通过对 Solr 进行适当的配置,某些情况下可能需要进行编码, Solr 可以阅读和使用构建到其他 Lucene 应用程序中的索引。此外,很多 Lucene 工具(如 Nutch 、 Luke )也可以使用 Solr 创建的索引。

2 、Ubuntu 下 Solr 安装配置

由于 Solr 基于 java 开发,因此 Solr 在 windows 及 Linux 都能较好部署使用,但由于 Solr 提供了一些用于测试及管理、维护较为方便的 shell 脚本,因此在生产部署时候建议安装在 Linux 上,测试时候可以在 windows 使用。

下面以 Ubuntu 下安装配置 Solr 进行说明。

首先下载Tomcat的压缩包。

unzip apache-tomcat-6.0.16.zip 


mv apache-tomcat-6.0.16 /opt/tomcat 


chmod 755 /opt/tomcat/bin/*




下载apache-solr-1.4.0压缩包。tar -xvf apache-solr-1.2.0.tgz

Solr 的安装配置最为麻烦的是对 solr.solr.home 的理解和配置,主要有三种

基于当前路径的方式

cp apache-solr-1.4.0/dist/apache-solr-1.4.0.war /opt/tomcat/webapps/solr.war 


mkdir /opt/solr-tomcat 


cp -r apache-solr-1.2.0/example/solr/ /opt/solr-tomcat/ 


cd /opt/solr-tomcat 


/opt/tomcat/bin/startup.sh



由于在此种情况下(没有设定 solr.solr.home 环境变量或 JNDI 的情况下), Solr 查找 ./solr ,因此在启动时候需要切换到 /opt/solr-tomcat

基于环境变量 solr.solr.home

在当前用户的环境变量中( .bash_profile )或在 /opt/tomcat/catalina.sh 中添加如下环境变量

export JAVA_OPTS="$JAVA_OPTS -Dsolr.solr.home=/opt/solr-tomcat/solr"



基于 JNDI 配置

mkdir –p /opt/tomcat/conf/Catalina/localhost 


touch /opt/tomcat/conf/Catalina/localhost/solr.xml ,内容如下 : 


 <Context docBase="/opt/tomcat/webapps/solr" debug="0" crossContext="true" > 


 <Environment name="solr/home" type="java.lang.String" value="/opt/solr-tomcat/solr" override="true" /> 


 </Context>



访问 solr 管理界面 http://127.0.0.1:8080/solr

3 、用solr从数据库建立中文索引

1.在Ubuntu下安装mysql服务端和客户端。

#apt-get install mysql-server-5.0 


#apt-get install mysql



2.添加Handler
编辑/opt/solr-tomcat/solr/conf文件夹下的solrconfig.xml文件,在config元素中添加

[xhtml] view plaincopy 


 < requestHandler name = "/dataimport" class = "org.apache.solr.handler.dataimport.DataImportHandler" > 

 < lst name = "defaults" > 

 < str name = "config" > data-config.xml </ str > 

 </ lst > 

 </ requestHandler >



3. 在此文件夹中新建一个data-config.xml文件,内容如下

[xhtml] view plaincopy 


 <dataConfig> 

 <dataSource type="JdbcDataSource" 

 driver="com.mysql.jdbc.Driver" 

 url="jdbc:mysql://127.0.0.1:3306/db_expert" 

 user="root" 

 password="root"/> 

 <document> 

 <entity name="expert" 

 query="select id,experName,researchfield,title,workunit,postaladdress,officephone,email,biography from expertinfo"> 

 </entity> 

 </document> 

 </dataConfig>



4. 修改schema.xml,找到<fieldType name="text",将分词器修改为中文分词器,这里用的是包装过的Paoding分词,这个东西好像已经不更新了,以后看看IKAnalyzer吧。

[xhtml] view plaincopy 


 <fieldType name="text" class="solr.TextField" positionIncrementGap="100"> 

 <analyzer type="index"> 

 <tokenizer class="net.paoding.analysis.analyzer.ChineseTokenizerFactory" mode="most-words"/> 

 <!-- in this example, we will only use synonyms at query time 

 <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> 

 --> 

 <!-- Case insensitive stop word removal. 

 add enablePositionIncrements=true in both the index and query 

 analyzers to leave a 'gap' for more accurate phrase queries. 

 --> 

 <filter class="solr.StopFilterFactory" 

 ignoreCase="true" 

 words="stopwords.txt" 

 enablePositionIncrements="true" 

 /> 

 <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/> 

 <filter class="solr.LowerCaseFilterFactory"/> 

 <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> 

 <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> 

 </analyzer> 

 <analyzer type="query"> 

 <tokenizer class="net.paoding.analysis.analyzer.ChineseTokenizerFactory" mode="most-words"/> 

 <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> 

 <filter class="solr.StopFilterFactory" 

 ignoreCase="true" 

 words="stopwords.txt" 

 enablePositionIncrements="true" 

 /> 

 <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/> 

 <filter class="solr.LowerCaseFilterFactory"/> 

 <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> 

 <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> 

 </analyzer> 

 </fieldType>



原来的schema.xml中没有的字段自己添加上。schema.xml默认是UTF-8编码。首先在<fields></fields>里添加要索引的域。

注意:数据库的表的主键的名字最好是id,以后才好办。

[xhtml] view plaincopy 


 <field name="id" type="int" indexed="true" stored="true" required="true" /> 

 <field name="experName" type="text" indexed="true" stored="true"/> 

 <field name="researchfield" type="text" indexed="true" stored="true"/> 

 <field name="title" type="text" indexed="true" stored="true"/> 

 <field name="workunit" type="text" indexed="true" stored="true"/> 

 <field name="postaladdress" type="text" indexed="true" stored="true"/> 

 <field name="officephone" type="text" indexed="true" stored="true"/> 

 <field name="email" type="text" indexed="true" stored="true"/> 

 <field name="biography" type="text" indexed="true" stored="true"/>



然后在<solrQueryParser defaultOperator="OR"/>下面添加下面行。

[xhtml] view plaincopy 


 <copyField source="experName" dest="text" /> 

 <copyField source="researchfield" dest="text" /> 

 <copyField source="title" dest="text" /> 

 <copyField source="workunit" dest="text" /> 

 <copyField source="postaladdress" dest="text" /> 

 <copyField source="officephone" dest="text" /> 

 <copyField source="email" dest="text" /> 

 <copyField source="biography" dest="text" />



5. 包装Paoding的分词器

[java] view plaincopy 


 1. package net.paoding.analysis.analyzer; 

 2. 

 3. import java.io.Reader; 

 4. import java.util.Map; 

 5. 

 6. import net.paoding.analysis.analyzer.impl.MaxWordLengthTokenCollector; 

 7. import net.paoding.analysis.analyzer.impl.MostWordsTokenCollector; 

 8. import net.paoding.analysis.knife.PaodingMaker; 

 9. 

 10. import org.apache.lucene.analysis.Tokenizer; 

 11. import org.apache.solr.analysis.BaseTokenizerFactory; 

 12. 

 13. /** 

 14. * Created by IntelliJ IDEA. 

 15. * User: ronghao 

 16. * Date: 2007-11-3 

 17. * Time: 14:40:59 中文切词 对庖丁切词的封装 

 18. */ 

 19. public class ChineseTokenizerFactory extends BaseTokenizerFactory { 

 20. /** 

 21. * 最多切分 默认模式 

 22. */ 

 23. public static final String MOST_WORDS_MODE = "most-words" ; 

 24. /** 

 25. * 按最大切分 

 26. */ 

 27. public static final String MAX_WORD_LENGTH_MODE = "max-word-length" ; 

 28. 

 29. private String mode = null ; 

 30. 

 31. public void setMode(String mode) { 

 32. if (mode == null || MOST_WORDS_MODE.equalsIgnoreCase(mode) || "default" .equalsIgnoreCase(mode)) { 

 33. this .mode = MOST_WORDS_MODE; 

 34. } else if (MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) { 

 35. this .mode = MAX_WORD_LENGTH_MODE; 

 36. } else { 

 37. throw new IllegalArgumentException( "不合法的分析器Mode参数设置:" + mode); 

 38. } 

 39. } 

 40. 

 41. @Override 

 42. public void init(Map<String, String> args) { 

 43. super .init(args); 

 44. setMode(args.get("mode" )); 

 45. } 

 46. 

 47. public Tokenizer create(Reader input) { 

 48. return new PaodingTokenizer2(input, PaodingMaker.make(), createTokenCollector()); 

 49. } 

 50. 

 51. private TokenCollector createTokenCollector() { 

 52. if (MOST_WORDS_MODE.equals(mode)) 

 53. return new MostWordsTokenCollector(); 

 54. if (MAX_WORD_LENGTH_MODE.equals(mode)) 

 55. return new MaxWordLengthTokenCollector(); 

 56. throw new Error( "never happened" ); 

 57. } 

 58. }


Java代码 收藏代码

1. package net.paoding.analysis.analyzer; 

 2. 

 3. import java.io.Reader; 

 4. import java.util.Map; 

 5. 

 6. import net.paoding.analysis.analyzer.impl.MaxWordLengthTokenCollector; 

 7. import net.paoding.analysis.analyzer.impl.MostWordsTokenCollector; 

 8. import net.paoding.analysis.knife.PaodingMaker; 

 9. 

 10. import org.apache.lucene.analysis.Tokenizer; 

 11. import org.apache.solr.analysis.BaseTokenizerFactory; 

 12. 

 13. /** 

 14. * Created by IntelliJ IDEA. 

 15. * User: ronghao 

 16. * Date: 2007-11-3 

 17. * Time: 14:40:59 中文切词 对庖丁切词的封装 

 18. */ 

 19. public class ChineseTokenizerFactory extends BaseTokenizerFactory { 

 20. /** 

 21. * 最多切分 默认模式 

 22. */ 

 23. public static final String MOST_WORDS_MODE = "most-words"; 

 24. /** 

 25. * 按最大切分 

 26. */ 

 27. public static final String MAX_WORD_LENGTH_MODE = "max-word-length"; 

 28. 

 29. private String mode = null; 

 30. 

 31. public void setMode(String mode) { 

 32. if (mode == null || MOST_WORDS_MODE.equalsIgnoreCase(mode) || "default".equalsIgnoreCase(mode)) { 

 33. this.mode = MOST_WORDS_MODE; 

 34. } else if (MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) { 

 35. this.mode = MAX_WORD_LENGTH_MODE; 

 36. } else { 

 37. throw new IllegalArgumentException("不合法的分析器Mode参数设置:" + mode); 

 38. } 

 39. } 

 40. 

 41. @Override 

 42. public void init(Map<String, String> args) { 

 43. super.init(args); 

 44. setMode(args.get("mode")); 

 45. } 

 46. 

 47. public Tokenizer create(Reader input) { 

 48. return new PaodingTokenizer(input, PaodingMaker.make(), this.createTokenCollector()); 

 49. } 

 50. 

 51. private TokenCollector createTokenCollector() { 

 52. if (MOST_WORDS_MODE.equals(mode)) 

 53. return new MostWordsTokenCollector(); 

 54. if (MAX_WORD_LENGTH_MODE.equals(mode)) 

 55. return new MaxWordLengthTokenCollector(); 

 56. throw new Error("never happened"); 

 57. } 

 58. }




这两个修改的类就放在/opt/tomcat/webapps/solr中,在压缩包的WEB-INF文件夹中新建classes文件夹,将这两个类连同包层次复制进去就行。

6.设置PAODING_DIC_HOME的环境变量,指向Paoding词典文件的位置。(比如/opt/dic)

#vim /etc/profile



添加下面的环境变量

JAVA_HOME=/usr/lib/jvm/java-6-openjdk 

CLASSPATH=.:/usr/lib/jvm/java-6-openjdk/lib 

ANT_HOME=/usr/share/ant 

PATH="$JAVA_HOME/lib:$ANT_HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" 

PAODING_DIC_HOME=/opt/dic 

export JAVA_HOME 

export CLASSPATH 

export ANT_HOME 

export PATH 

export PAODING_DIC_HOME



7. 将Paoding和数据库驱动放到/opt/tomcat/webapps/solr/WEB-INF/lib中。

进入浏览器,运行
http://localhost:8983/solr/dataimport?command=full-import 导入成功后,运行
http://localhost:8983/solr/admin/
在搜索框中输入搜索内容进行查询

现在就完成了数据库的索引了。