欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Apache Solr单机环境配置(包括中文分词和Java API的使用)

Apache Solr单机环境配置(包括中文分词和Java API的使用)

2015年02月01日 18:48:12 小爷有点狂 阅读数:2593                

一、使用场景说明

项目中需要实现一个地址查询框,类似于在谷歌地图中输入地址,根据定义的规则实时检索并展现匹配的地址的功能(当然比那简单的多),为了减小数据库压力和提高检索效率,现采用apache solr实现。由于对性能和可靠性可用性等没太高的要求,所以此处没有考虑集群,只是一个简单的单机版环境。

二、概念介绍

 

三、安装启动和中文分词配置

1、下载solr-4.10.2.zip,解压得到solr-4.10.2目录

2、将solr-4.10.2\example下的solr目录拷贝出来作为SOLR_HOME(即配各个collection配置和数据存储的目录),此处拷贝到C:\Users\jiayu\Desktop\solr\下并重命名为solr_home

3、将solr-4.10.2\dist下的solr-4.10.2.war拷贝到tomcat的webapps目录下,启动tomcat后会自动解压,然后此war包即可删除,解压后默认目录名称为solr-4.10.2,为方便此处将其名称改为solr,然后在tomcat\webapps\solr\META-INF下创建context.xml(tomcat配置:可在tomcat的\conf\Catalina\localhost目录下创建与应用上下文同名的xml文件或在应用上下文的META-INF目录下创建context.xml),xml内容如下:


               

  1. <?xml version="1.0"encoding="UTF-8" standalone="yes"?>                            
  2. <ContextdocBase="D:\setups\apache-tomcat-7.0.54-others\webapps\solr.war"debug="0" crossContext="true" >                            
  3. <Environmentname="solr/home" type="java.lang.String"value="C:\Users\jiayu\Desktop\solr\solr_home"override="true" />                            
  4. </Context>                            


               


               

4、启动tomcat,此时会发现报出来一个错误:Error filterStart,查看tomcat日志:localhost.log,报缺少slf4j包,将solr-4.10.2\example\lib\ext下的所有jar包(此处没有校验具体需要哪个)拷贝到solr/WEB-INF/lib目录下,同时在WEB-INF下建立classes目录,建立log4j.properties文件,内容如下


               

  1. #  Logging level
  2. solr.log=logs/
  3. log4j.rootLogger=INFO, file, CONSOLE
  4. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
  5. log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
  6. log4j.appender.CONSOLE.layout.ConversionPattern=%-4r[%t] %-5p %c %x \u2013 %m%n
  7. #- size rotation with log cleanup.
  8. log4j.appender.file=org.apache.log4j.RollingFileAppender
  9. log4j.appender.file.MaxFileSize=4MB
  10. log4j.appender.file.MaxBackupIndex=9
  11. #- File to log to and log format
  12. log4j.appender.file.File=${solr.log}/solr.log
  13. log4j.appender.file.layout=org.apache.log4j.PatternLayout
  14. log4j.appender.file.layout.ConversionPattern=%-5p- %d{yyyy-MM-dd HH:mm:ss.SSS}; %C; %m\n
  15. log4j.logger.org.apache.zookeeper=WARN
  16. log4j.logger.org.apache.hadoop=WARN
  17. # set to INFO to enable infostream logmessages
  18. log4j.logger.org.apache.solr.update.LoggingInfoStream=OFF


               


               

重新启动,访问localhost:8080/solr/admin.html,出现如下界面说明启动成功


               

                 


               

配置中文分词

下载IKAnalyzer2012FF_u1.jar,并放在solr/WEB-INF/lib目录下

编辑solr_home/collection1/conf目录下的scheme.xml文件,添加如下内容:


               

  1. <fieldType name="text_ik"class="solr.TextField">  
  2. <analyzertype="index" isMaxWordLength="false"class="org.wltea.analyzer.lucene.IKAnalyzer"/>  
  3. <analyzertype="query" isMaxWordLength="true"class="org.wltea.analyzer.lucene.IKAnalyzer"/>  
  4. </fieldType>                            


               


               


               

 <fieldname="quesContent" type="text_ik" />


               


               

标明quesContent字段的分词由中文分词器去完成,打开solr管理页面,选择collection1(core selector),要分词的字段选择刚配置的quesContent,输入一段中文,点击分析,可看到分词效果


               

至此,配置工作完成,下面介绍一下如何从数据库导入数据,和如何利用它提供的javaAPI插入和查询数据

四、从数据库导入数据

将solr-4.10.2\dist目录下的solr-dataimporthandler-4.10.2.jar和solr-dataimporthandler-extras-4.10.2.jar拷贝到solr应用程序的WEB-INF/lib目录下,由于此处是从ORACLE中导入数据,还要将Oracle驱动oracle6.jar拷贝到lib下

在solr_home目录/collection1/conf下创建data-config.xml,内容如下


               

  1. <dataConfig>                            
  2. <dataSource driver="oracle.jdbc.driver.OracleDriver"url="jdbc:oracle:thin:@192.168.32.152:1521:star"user="ecms" password="ecms"/>                            
  3. <document>                            
  4. <entity name="addressen" query="select id,name fromaddressen">                            
  5. <fieldcolumn="id" name="id"/>                            
  6. <field column="name"name="name"/>                            
  7. </entity>                            
  8. </document>                            
  9. </dataConfig>                            


               


               

在/collection1/conf/solrconfig.xml中添加


               

  1. <requestHandlername="/dataimport"class="org.apache.solr.handler.dataimport.DataImportHandler">                            
  2. <lstname="defaults">  
  3. <strname="config">data-config.xml</str>  
  4. </lst>  
  5. </requestHandler>                            


               


               

启动后,登录solr管理界面,选择collection1,选择Dataimport选项,点击Execute按钮,如果配置无误的话数据便可导入进来


               

                 

五、solr-solrj-4.10.2.jar提供的java API使用

为了保证数据库中数据和solr中的数据同步,采用定时任务,每隔一段时间通过API调用,将数据库中数据同步到solr中。由于地址表中存放着各个国家的数据,在同步时,需要将数据按国家分开存放,所以对于每个国家的地址信息,单独创建一个core,在solr_home下有一个配置好的default_core目录,在插入地址时,判断如果此条地址的国家(比如country01)还没有对应的core,将创建目录country01,同时将default_core中的配置信息拷贝到country01中。

以下为完整代码:


               

  1. package com.star.basic.system.domain;
  2. import java.io.Serializable;
  3. import java.util.List;
  4. import org.apache.solr.client.solrj.beans.Field;
  5. public class SolrStoredAddress implements Serializable {
  6.                                 /**                            
  7. *                            
  8. */                            
  9.                                 private static final long serialVersionUID = 6192432007244661406L;
  10.                                 @Field                            
  11.                                 private String id;
  12.                                 @Field                            
  13.                                 private String name;
  14.                                 @Field                            
  15.                                 private String countryName;
  16.                                 @Field                            
  17.                                 private List<String> saleAreas;
  18.                                 @Field                            
  19.                                 private List<String> operators;
  20.                                 public String getId() {
  21.                                 return id;
  22.                                 }
  23.                                 public void setId(String id) {
  24.                                 this.id = id;
  25.                                 }
  26.                                 public String getName() {
  27.                                 return name;
  28.                                 }
  29.                                 public void setName(String name) {
  30.                                 this.name = name;
  31.                                 }
  32.                                 public String getCountryName() {
  33.                                 return countryName;
  34.                                 }
  35.                                 public void setCountryName(String countryName) {
  36.                                 this.countryName = countryName;
  37.                                 }
  38.                                 public List<String> getSaleAreas() {
  39.                                 return saleAreas;
  40.                                 }
  41.                                 public void setSaleAreas(List<String> saleAreas) {
  42.                                 this.saleAreas = saleAreas;
  43.                                 }
  44.                                 public List<String> getOperators() {
  45.                                 return operators;
  46.                                 }
  47.                                 public void setOperators(List<String> operators) {
  48.                                 this.operators = operators;
  49.                                 }
  50. }

               
  1. package com.star.basic.system.solr.utils;
  2. import java.io.IOException;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Map.Entry;
  8. import org.apache.solr.client.solrj.SolrQuery;
  9. import org.apache.solr.client.solrj.SolrServerException;
  10. import org.apache.solr.client.solrj.impl.HttpSolrServer;
  11. import org.apache.solr.client.solrj.response.QueryResponse;
  12. import com.star.basic.system.domain.SolrStoredAddress;
  13. public class SolrAddressUtils {
  14.                                 public static boolean available = true;
  15.                                 private static final String SOLR_URL = "http://127.0.0.1:8081/solr";
  16.                                 private static HttpSolrServer server = new HttpSolrServer(SOLR_URL);
  17.                                 /**                            
  18. * 将数据同步到solr中                            
  19. * @param addresses                            
  20. * @throws SolrServerException                            
  21. * @throws IOException                            
  22. */                            
  23.                                 public static void addAddresses(List<SolrStoredAddress> addresses)                            
  24.                                 throws SolrServerException, IOException {
  25.                                 available = false;
  26.                                 //将地址信息按国家分类                            
  27.                                 Map<String, List<SolrStoredAddress>> map = new HashMap<String, List<SolrStoredAddress>>();
  28.                                 for (SolrStoredAddress address : addresses) {
  29.                                 if (!map.containsKey(address.getCountryName())) {
  30.                                 map.put(address.getCountryName(),
  31.                                 new ArrayList<SolrStoredAddress>());
  32.                                 }
  33.                                 map.get(address.getCountryName()).add(address);
  34.                                 }
  35.                                 for (Entry<String, List<SolrStoredAddress>> entry : map.entrySet()) {
  36.                                 server.setBaseURL(SOLR_URL);
  37.                                 if (!SolrUtils.hasCore(entry.getKey(), server)) {
  38.                                 SolrUtils.createCore(entry.getKey(), server);
  39.                                 }
  40.                                 server.setBaseURL(SOLR_URL + "/" + entry.getKey());
  41.                                 server.deleteByQuery("*:*"); // CAUTION: deletes everything!                            
  42.                                 server.addBeans(entry.getValue());
  43.                                 server.commit();
  44.                                 }
  45.                                 available = true;
  46.                                 }
  47.                                 public static List<SolrStoredAddress> queryAddresses(String addrName,                            
  48. String countryName) {
  49.                                 if (!available) {
  50.                                 return null;
  51.                                 }
  52.                                 SolrQuery query = new SolrQuery();
  53.                                 query.setQuery("name:" + addrName);
  54.                                 query.setStart(0);
  55.                                 query.setRows(5);
  56.                                 server.setBaseURL(SOLR_URL + "/" + countryName);
  57.                                 QueryResponse response;
  58.                                 try {
  59.                                 response = server.query(query);
  60.                                 return response.getBeans(SolrStoredAddress.class);
  61.                                 } catch (SolrServerException e) {
  62.                                 e.printStackTrace();
  63.                                 }
  64.                                 return null;
  65.                                 }
  66.                                 public static void main(String[] args) throws SolrServerException,                            
  67. IOException {
  68.                                 // List<SolrStoredAddress> addrs = new ArrayList<SolrStoredAddress>();                            
  69.                                 // for (int i = 0; i < 10; i++) {                            
  70.                                 // SolrStoredAddress add = new SolrStoredAddress();                            
  71.                                 // add.setId(new Long(i));                            
  72.                                 // add.setName("add" + i);                            
  73.                                 // add.setCountryName("country" + i);                            
  74.                                 // addrs.add(add);                            
  75.                                 // }                            
  76.                                 // SolrAddressUtils.addAddresses(addrs);                            
  77.                                 server.setBaseURL(SOLR_URL + "/" + "country1");
  78.                                 List<SolrStoredAddress> addrs = new ArrayList<SolrStoredAddress>();
  79.                                 for (int i = 0; i < 10000; i++) {
  80.                                 SolrStoredAddress add = new SolrStoredAddress();
  81.                                 add.setId(String.valueOf(i));
  82.                                 add.setName("add" + i);
  83.                                 add.setCountryName("country1");
  84.                                 addrs.add(add);
  85.                                 }
  86.                                 SolrAddressUtils.addAddresses(addrs);
  87.                                 }
  88. }

               
  1. package com.star.basic.system.solr.utils;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import org.apache.solr.client.solrj.SolrServer;
  5. import org.apache.solr.client.solrj.SolrServerException;
  6. import org.apache.solr.client.solrj.request.CoreAdminRequest;
  7. import org.apache.solr.common.util.NamedList;
  8. import com.star.osgi.utils.FileUtils;
  9. public class SolrUtils {
  10.                                 private static final String DEFAULT_CORE_NAME = "default_core";
  11.                                 /**                            
  12. * 判断server中是否已经有对应的core                            
  13. *                            
  14. * @param coreName                            
  15. * @param server                            
  16. * @return                            
  17. * @throws SolrServerException                            
  18. * @throws IOException                            
  19. */                            
  20.                                 public static boolean hasCore(String coreName, SolrServer server)                            
  21.                                 throws SolrServerException, IOException {
  22.                                 NamedList<Object> responseData = CoreAdminRequest
  23.                                 .getStatus(coreName, server).getCoreStatus().get(coreName);
  24.                                 String name = (String) responseData.get("name");
  25.                                 if (name != null && name.equals(coreName)) {
  26.                                 return true;
  27.                                 }
  28.                                 return false;
  29.                                 }
  30.                                 /**                            
  31. * 创建core:从默认的core中拷贝所需文件,调用接口                            
  32. *                            
  33. * @param coreName                            
  34. * @param server                            
  35. * @throws SolrServerException                            
  36. * @throws IOException                            
  37. */                            
  38.                                 public static void createCore(String coreName, SolrServer server)                            
  39.                                 throws SolrServerException, IOException {
  40.                                 NamedList<Object> list = CoreAdminRequest
  41.                                 .getStatus(DEFAULT_CORE_NAME, server).getCoreStatus()
  42.                                 .get(DEFAULT_CORE_NAME);
  43.                                 String defaultCorePath = (String) list.get("instanceDir");
  44.                                 String solrHome = defaultCorePath.substring(0,
  45.                                 defaultCorePath.indexOf(DEFAULT_CORE_NAME));
  46.                                 File corePath = new File(solrHome, coreName);
  47.                                 if (!corePath.exists()) {
  48.                                 corePath.mkdir();
  49.                                 }
  50.                                 File confPath = new File(corePath.getAbsolutePath(), "conf");
  51.                                 if (!confPath.exists()) {
  52.                                 confPath.mkdir();
  53.                                 }
  54.                                 FileUtils.copyDir(new File(defaultCorePath, "conf"),
  55.                                 new File(corePath.getAbsolutePath(), "conf"));
  56.                                 CoreAdminRequest.createCore(coreName, corePath.getAbsolutePath(),
  57.                                 server);
  58.                                 }
  59. }

               
  1. 查询
  2. @RequestMapping("indexSearch.do")
  3. @ResponseBody                            
  4. public List<Address> indexSearch(@RequestParam(value = "name",required = false) String name,HttpServletRequest request) throws SolrServerException{
  5. Country country = (Country) request.getSession().getAttribute("country");
  6. if(name == null){
  7. return null;
  8. }
  9. List<SolrStoredAddress> addrs = SolrAddressUtils.querySolrAddresses(name,"country1");
  10. return convertToAddress(addrs);
  11. }


               


               

  1. Spring Data Solr也提供了对Solr接口的封装,简化接口调用,同时提供了事务等支持,大致测试配置如下,如有兴趣,可参考官方文档
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <beans xmlns="http://www.springframework.org/schema/beans"                            
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:solr="http://www.springframework.org/schema/data/solr"                            
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans                            
  6.    http://www.springframework.org/schema/beans/spring-beans.xsd                            
  7.    http://www.springframework.org/schema/data/solr                            
  8.    http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd">
  9. <solr:repositories base-package="solr.test.spring.solr" />
  10. <solr:solr-server id="solrServer" url="http://localhost:8081/solr" />
  11. <bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
  12. <constructor-arg index="0" ref="solrServer" />
  13. </bean>
  14. <!-- <solr:embedded-solr-server id="solrServer" solrHome="classpath:solr/test/spring/solr"                            
  15. /> -->
  16. </beans>
  17. package solr.test.spring.solr;
  18. import java.util.List;
  19. import org.springframework.data.repository.CrudRepository;
  20. import com.star.basic.system.domain.SolrStoredAddress;
  21. public interface AddressSolrRepository extends CrudRepository<SolrStoredAddress, Long> {
  22. List<SolrStoredAddress> findByName(String name);
  23. }



               

参考资料

solr wiki  http://wiki.apache.org/solr/Solrj

Apache Solr 4.5.1环境搭建及MYSQL数据导入 http://blog.csdn.net/weijonathan/article/details/16961299
               

Spring Data Solr http://docs.spring.io/spring-data/data-solr/docs/current/reference/html/                

 


普通分类: