solr应用


Solrj已经是很强大的solr客户端了。它本身就包装了httpCliet,以完全对象的方式对solr进行交互。很小很好很强大。
    不过在实际使用中,设置SolrQuery 的过程中,为了设置多个搜索条件和排序规则等等参数,我们往往会陷入并接字符串的地步,实在是很丑陋,不符合面向对象的思想。扩展性几乎为0,。基于这点,开发了一个小东西,我们只需要设置搜索对象,将对象扔给后台就可以了。
    比如,我们搭建的solr服务支持某10个字段的搜索,我们要搜索其中的一些,那么我们只需要传入要搜索的对象POJO,将要搜索的字段内容,set到POJO对象对应额字段即可。

    比如如下一个类:

 

[java]  view plain copy print ?
  1. package org.uppower.tnt.biz.core.manager.blog.dataobject;  
  2.   
  3. /** 
  4.  * @author yingmu 
  5.  * @version 2010-7-20 下午01:00:55 
  6.  */  
  7. public class SolrPropertyDO {  
  8.     private String auction_id;  
  9.     private String opt_tag;  
  10.     private String exp_tag;  
  11.     private String title;  
  12.     private String desc;  
  13.     private String brand;  
  14.     private String category;  
  15.     private String price;  
  16.     private String add_prov;  
  17.     private String add_city;  
  18.     private String quality;  
  19.     private String flag;  
  20.     private String sales;  
  21.     private String sellerrate;  
  22.     private String selleruid;  
  23.     private String ipv15;  
  24.   
  25.     public String getAuction_id() {  
  26.         return auction_id;  
  27.     }  
  28.   
  29.     public void setAuction_id(String auctionId) {  
  30.         auction_id = auctionId;  
  31.     }  
  32.   
  33.     ……  
  34.   
  35.     public String getExp_tag() {  
  36.         return exp_tag;  
  37.     }  
  38.   
  39.     public void setExp_tag(String expTag) {  
  40.         exp_tag = expTag;  
  41.     }  
  42. }  
Java代码   收藏代码
  1. package org.uppower.tnt.biz.core.manager.blog.dataobject;  
  2.   
  3. /** 
  4.  * @author yingmu 
  5.  * @version 2010-7-20 下午01:00:55 
  6.  */  
  7. public class SolrPropertyDO {  
  8.     private String auction_id;  
  9.     private String opt_tag;  
  10.     private String exp_tag;  
  11.     private String title;  
  12.     private String desc;  
  13.     private String brand;  
  14.     private String category;  
  15.     private String price;  
  16.     private String add_prov;  
  17.     private String add_city;  
  18.     private String quality;  
  19.     private String flag;  
  20.     private String sales;  
  21.     private String sellerrate;  
  22.     private String selleruid;  
  23.     private String ipv15;  
  24.   
  25.     public String getAuction_id() {  
  26.         return auction_id;  
  27.     }  
  28.   
  29.     public void setAuction_id(String auctionId) {  
  30.         auction_id = auctionId;  
  31.     }  
  32.   
  33.     ……  
  34.   
  35.     public String getExp_tag() {  
  36.         return exp_tag;  
  37.     }  
  38.   
  39.     public void setExp_tag(String expTag) {  
  40.         exp_tag = expTag;  
  41.     }  
  42. }  

那么我们在定义搜索对象时候,就按照如下设置:
[java]  view plain copy print ?
  1. SolrPropertyDO propertyDO = new SolrPropertyDO();  
  2.         propertyDO.setAdd_city("(杭州AND成都)OR北京");  
  3.         propertyDO.setTitle("丝绸OR剪刀");  
  4.          ……  
Java代码   收藏代码
  1. SolrPropertyDO propertyDO = new SolrPropertyDO();  
  2.         propertyDO.setAdd_city("(杭州AND成都)OR北京");  
  3.         propertyDO.setTitle("丝绸OR剪刀");  
  4.          ……  

设置排序条件,也是类似的做法:

 

[java]  view plain copy print ?
  1. SolrPropertyDO compositorDO = new SolrPropertyDO();  
  2.         compositorDO.setPrice ("desc");  
  3.         compositorDO.setQuality ("asc");  
  4.          ……  
Java代码   收藏代码
  1. SolrPropertyDO compositorDO = new SolrPropertyDO();  
  2.         compositorDO.setPrice ("desc");  
  3.         compositorDO.setQuality ("asc");  
  4.          ……  

 将定义好的两个对象扔给后面的接口就可以了。

     接口函数querySolrResult传入四个参数,其中包含搜索字段对象,排序条件对象。为了提供类似limit的操作,用于分页查询,提供了startIndex和pageSize。
     函数querySolrResultCount是单纯为了获得搜索条数,配合分页使用。
    以下是定义的接口:

 

[java]  view plain copy print ?
  1. package org.uppower.tnt.biz.core.manager.blog;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;  
  6.   
  7. /** 
  8.  * @author yingmu 
  9.  * @version 2010-7-20 下午03:51:15 
  10.  */  
  11. public interface SolrjOperator {  
  12.   
  13.     /** 
  14.      * 获得搜索结果 
  15.      *  
  16.      * @param propertyDO 
  17.      * @param compositorDO 
  18.      * @param startIndex 
  19.      * @param pageSize 
  20.      * @return 
  21.      * @throws Exception 
  22.      */  
  23.     public List<Object> querySolrResult(Object propertyDO,  
  24.             Object compositorDO, Long startIndex, Long pageSize)  
  25.             throws Exception;  
  26.   
  27.     /** 
  28.      * 获得搜索结果条数 
  29.      *  
  30.      * @param propertyDO 
  31.      * @param compositorDO 
  32.      * @return 
  33.      * @throws Exception 
  34.      */  
  35.     public Long querySolrResultCount(SolrPropertyDO propertyDO,  
  36.             Object compositorDO) throws Exception;  
  37.   
  38. }  
Java代码   收藏代码
  1. package org.uppower.tnt.biz.core.manager.blog;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;  
  6.   
  7. /** 
  8.  * @author yingmu 
  9.  * @version 2010-7-20 下午03:51:15 
  10.  */  
  11. public interface SolrjOperator {  
  12.   
  13.     /** 
  14.      * 获得搜索结果 
  15.      *  
  16.      * @param propertyDO 
  17.      * @param compositorDO 
  18.      * @param startIndex 
  19.      * @param pageSize 
  20.      * @return 
  21.      * @throws Exception 
  22.      */  
  23.     public List<Object> querySolrResult(Object propertyDO,  
  24.             Object compositorDO, Long startIndex, Long pageSize)  
  25.             throws Exception;  
  26.   
  27.     /** 
  28.      * 获得搜索结果条数 
  29.      *  
  30.      * @param propertyDO 
  31.      * @param compositorDO 
  32.      * @return 
  33.      * @throws Exception 
  34.      */  
  35.     public Long querySolrResultCount(SolrPropertyDO propertyDO,  
  36.             Object compositorDO) throws Exception;  
  37.   
  38. }  

 实现逻辑为,首先将传入的两个实体对象,解析为<K,V>结构的Map当中,将解析完成的Map放入solrj实际的搜索对象当中。返回的对象为solrj的API提供的SolrDocument,其中结果数量为直接返回SolrDocumentList对象的getNumFound()
    具体实现类:

 

[java]  view plain copy print ?
  1. package org.uppower.tnt.biz.core.manager.blog;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7. import java.util.TreeMap;  
  8.   
  9. import org.apache.solr.common.SolrDocumentList;  
  10.   
  11. import org.uppower.tnt.biz.core.manager.isearch.common.SolrjCommonUtil;  
  12. import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;  
  13. import org.uppower.tnt.biz.core.manager.isearch.solrj.SolrjQuery;  
  14.   
  15. /** 
  16.  * @author yingmu 
  17.  * @version 2010-7-20 下午03:51:15 
  18.  */  
  19. public class DefaultSolrOperator implements SolrjOperator {  
  20.       
  21.     private Logger logger = LoggerFactory.getLogger(this.getClass());  
  22.     private SolrjQuery solrjQuery;  
  23.   
  24.     public void setSolrjQuery(SolrjQuery solrjQuery) {  
  25.         this.solrjQuery = solrjQuery;  
  26.     }  
  27.   
  28.     @Override  
  29.     public List<Object> querySolrResult(Object propertyDO,  
  30.             Object compositorDO, Long startIndex, Long pageSize)  
  31.             throws Exception {  
  32.         Map<String, String> propertyMap = new TreeMap<String, String>();  
  33.         //排序有顺序,使用TreeMap   
  34.         Map<String, String> compositorMap = new TreeMap<String, String>();  
  35.         try {  
  36.             propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);  
  37.             compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);  
  38.         } catch (Exception e) {  
  39.             logger.error("SolrjCommonUtil.getSearchProperty() is error !"+ e);  
  40.         }  
  41.         SolrDocumentList solrDocumentList = solrjQuery.query(propertyMap, compositorMap,  
  42.                 startIndex, pageSize);  
  43.         List<Object> resultList = new ArrayList<Object>();  
  44.         for (int i = 0; i < solrDocumentList.size(); i++) {  
  45.             resultList.add(solrDocumentList.get(i));  
  46.         }  
  47.         return resultList;  
  48.     }  
  49.   
  50.     @Override  
  51.     public Long querySolrResultCount(SolrPropertyDO propertyDO,  
  52.             Object compositorDO) throws Exception {  
  53.         Map<String, String> propertyMap = new TreeMap<String, String>();  
  54.         Map<String, String> compositorMap = new TreeMap<String, String>();  
  55.         try {  
  56.             propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);  
  57.             compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);  
  58.         } catch (Exception e) {  
  59.             logger.error("SolrjCommonUtil.getSearchProperty() is error !" + e);  
  60.         }  
  61.         SolrDocumentList solrDocument = solrjQuery.query(propertyMap, compositorMap,  
  62.                 nullnull);  
  63.         return solrDocument.getNumFound();  
  64.     }  
  65.   
  66. }  
Java代码   收藏代码
  1. package org.uppower.tnt.biz.core.manager.blog;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7. import java.util.TreeMap;  
  8.   
  9. import org.apache.solr.common.SolrDocumentList;  
  10.   
  11. import org.uppower.tnt.biz.core.manager.isearch.common.SolrjCommonUtil;  
  12. import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;  
  13. import org.uppower.tnt.biz.core.manager.isearch.solrj.SolrjQuery;  
  14.   
  15. /** 
  16.  * @author yingmu 
  17.  * @version 2010-7-20 下午03:51:15 
  18.  */  
  19. public class DefaultSolrOperator implements SolrjOperator {  
  20.       
  21.     private Logger logger = LoggerFactory.getLogger(this.getClass());  
  22.     private SolrjQuery solrjQuery;  
  23.   
  24.     public void setSolrjQuery(SolrjQuery solrjQuery) {  
  25.         this.solrjQuery = solrjQuery;  
  26.     }  
  27.   
  28.     @Override  
  29.     public List<Object> querySolrResult(Object propertyDO,  
  30.             Object compositorDO, Long startIndex, Long pageSize)  
  31.             throws Exception {  
  32.         Map<String, String> propertyMap = new TreeMap<String, String>();  
  33.         //排序有顺序,使用TreeMap  
  34.         Map<String, String> compositorMap = new TreeMap<String, String>();  
  35.         try {  
  36.             propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);  
  37.             compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);  
  38.         } catch (Exception e) {  
  39.             logger.error("SolrjCommonUtil.getSearchProperty() is error !"+ e);  
  40.         }  
  41.         SolrDocumentList solrDocumentList = solrjQuery.query(propertyMap, compositorMap,  
  42.                 startIndex, pageSize);  
  43.         List<Object> resultList = new ArrayList<Object>();  
  44.         for (int i = 0; i < solrDocumentList.size(); i++) {  
  45.             resultList.add(solrDocumentList.get(i));  
  46.         }  
  47.         return resultList;  
  48.     }  
  49.   
  50.     @Override  
  51.     public Long querySolrResultCount(SolrPropertyDO propertyDO,  
  52.             Object compositorDO) throws Exception {  
  53.         Map<String, String> propertyMap = new TreeMap<String, String>();  
  54.         Map<String, String> compositorMap = new TreeMap<String, String>();  
  55.         try {  
  56.             propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);  
  57.             compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);  
  58.         } catch (Exception e) {  
  59.             logger.error("SolrjCommonUtil.getSearchProperty() is error !" + e);  
  60.         }  
  61.         SolrDocumentList solrDocument = solrjQuery.query(propertyMap, compositorMap,  
  62.                 nullnull);  
  63.         return solrDocument.getNumFound();  
  64.     }  
  65.   
  66. }  

其中,对象的解析式利用反射原理,将实体对象中不为空的值,以映射的方式,转化为一个Map,其中排序对象在转化的过程中,使用TreeMap,保证其顺序性。
    解析公共类实现如下:

 

[java]  view plain copy print ?
  1. package org.uppower.tnt.biz.core.manager.blog.common;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6. import java.util.HashMap;  
  7. import java.util.Map;  
  8.   
  9. /** 
  10.  * @author yingmu 
  11.  * @version 2010-7-20 下午01:07:15 
  12.  */  
  13. public class SolrjCommonUtil {  
  14.   
  15.     public static Map<String, String> getSearchProperty(Object model)  
  16.             throws NoSuchMethodException, IllegalAccessException,  
  17.             IllegalArgumentException, InvocationTargetException {  
  18.         Map<String, String> resultMap = new TreeMap<String, String>();  
  19.         // 获取实体类的所有属性,返回Field数组   
  20.         Field[] field = model.getClass().getDeclaredFields();  
  21.         for (int i = 0; i < field.length; i++) { // 遍历所有属性   
  22.             String name = field[i].getName(); // 获取属性的名字   
  23.             // 获取属性的类型   
  24.             String type = field[i].getGenericType().toString();  
  25.             if (type.equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名   
  26.                 Method m = model.getClass().getMethod(  
  27.                         "get" + UpperCaseField(name));  
  28.                 String value = (String) m.invoke(model); // 调用getter方法获取属性值   
  29.                 if (value != null) {  
  30.                     resultMap.put(name, value);  
  31.                 }  
  32.             }  
  33.         }  
  34.         return resultMap;  
  35.     }  
  36.   
  37.     // 转化字段首字母为大写   
  38.     private static String UpperCaseField(String fieldName) {  
  39.         fieldName = fieldName.replaceFirst(fieldName.substring(01), fieldName  
  40.                 .substring(01).toUpperCase());  
  41.         return fieldName;  
  42.     }  
  43.   
  44. }  
Java代码   收藏代码
  1. package org.uppower.tnt.biz.core.manager.blog.common;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6. import java.util.HashMap;  
  7. import java.util.Map;  
  8.   
  9. /** 
  10.  * @author yingmu 
  11.  * @version 2010-7-20 下午01:07:15 
  12.  */  
  13. public class SolrjCommonUtil {  
  14.   
  15.     public static Map<String, String> getSearchProperty(Object model)  
  16.             throws NoSuchMethodException, IllegalAccessException,  
  17.             IllegalArgumentException, InvocationTargetException {  
  18.         Map<String, String> resultMap = new TreeMap<String, String>();  
  19.         // 获取实体类的所有属性,返回Field数组  
  20.         Field[] field = model.getClass().getDeclaredFields();  
  21.         for (int i = 0; i < field.length; i++) { // 遍历所有属性  
  22.             String name = field[i].getName(); // 获取属性的名字  
  23.             // 获取属性的类型  
  24.             String type = field[i].getGenericType().toString();  
  25.             if (type.equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名  
  26.                 Method m = model.getClass().getMethod(  
  27.                         "get" + UpperCaseField(name));  
  28.                 String value = (String) m.invoke(model); // 调用getter方法获取属性值  
  29.                 if (value != null) {  
  30.                     resultMap.put(name, value);  
  31.                 }  
  32.             }  
  33.         }  
  34.         return resultMap;  
  35.     }  
  36.   
  37.     // 转化字段首字母为大写  
  38.     private static String UpperCaseField(String fieldName) {  
  39.         fieldName = fieldName.replaceFirst(fieldName.substring(01), fieldName  
  40.                 .substring(01).toUpperCase());  
  41.         return fieldName;  
  42.     }  
  43.   
  44. }  

搜索直接调用solr客户端solrj,基本逻辑为循环两个解析之后的TreeMap,设置到SolrQuery当中,最后直接调用solrj的API,获得搜索结果。最终将搜索结构以List<Object>的形式返回。
    具体实现:

 

[java]  view plain copy print ?
  1. package org.uppower.tnt.biz.core.manager.blog.solrj;  
  2.   
  3. import java.net.MalformedURLException;  
  4. import java.util.Map;  
  5.   
  6. import org.apache.solr.client.solrj.SolrQuery;  
  7. import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
  8. import org.apache.solr.client.solrj.response.QueryResponse;  
  9. import org.apache.solr.common.SolrDocumentList;  
  10.   
  11. /** 
  12.  * @author yingmu 
  13.  * @version 2010-7-20 下午02:57:04 
  14.  */  
  15. public class SolrjQuery {  
  16.     private String url;  
  17.     private Integer soTimeOut;  
  18.     private Integer connectionTimeOut;  
  19.     private Integer maxConnectionsPerHost;  
  20.     private Integer maxTotalConnections;  
  21.     private Integer maxRetries;  
  22.     private CommonsHttpSolrServer solrServer = null;  
  23.     private final static String ASC = "asc";  
  24.   
  25.     public void init() throws MalformedURLException {  
  26.         solrServer = new CommonsHttpSolrServer(url);  
  27.         solrServer.setSoTimeout(soTimeOut);  
  28.         solrServer.setConnectionTimeout(connectionTimeOut);  
  29.         solrServer.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost);  
  30.         solrServer.setMaxTotalConnections(maxTotalConnections);  
  31.         solrServer.setFollowRedirects(false);  
  32.         solrServer.setAllowCompression(true);  
  33.         solrServer.setMaxRetries(maxRetries);  
  34.     }  
  35.   
  36.     public SolrDocumentList query(Map<String, String> propertyMap,  
  37.             Map<String, String> compositorMap, Long startIndex, Long pageSize)  
  38.             throws Exception {  
  39.         SolrQuery query = new SolrQuery();  
  40.         // 设置搜索字段   
  41.         if (null == propertyMap) {  
  42.             throw new Exception("搜索字段不可为空!");  
  43.         } else {  
  44.             for (Object o : propertyMap.keySet()) {  
  45.                 StringBuffer sb = new StringBuffer();  
  46.                 sb.append(o.toString()).append(":");  
  47.                 sb.append(propertyMap.get(o));  
  48.                 String queryString = addBlank2Expression(sb.toString());  
  49.                 query.setQuery(queryString);  
  50.             }  
  51.         }  
  52.         // 设置排序条件   
  53.         if (null != compositorMap) {  
  54.             for (Object co : compositorMap.keySet()) {  
  55.                 if (ASC == compositorMap.get(co)  
  56.                         || ASC.equals(compositorMap.get(co))) {  
  57.                     query.addSortField(co.toString(), SolrQuery.ORDER.asc);  
  58.                 } else {  
  59.                     query.addSortField(co.toString(), SolrQuery.ORDER.desc);  
  60.                 }  
  61.             }  
  62.         }  
  63.           
  64.         if (null != startIndex) {  
  65.             query.setStart(Integer.parseInt(String.valueOf(startIndex)));  
  66.         }  
  67.         if (null != pageSize && 0L != pageSize.longValue()) {  
  68.             query.setRows(Integer.parseInt(String.valueOf(pageSize)));  
  69.         }  
  70.         try {  
  71.             QueryResponse qrsp = solrServer.query(query);  
  72.             SolrDocumentList docs = qrsp.getResults();  
  73.             return docs;  
  74.         } catch (Exception e) {  
  75.             throw new Exception(e);  
  76.         }  
  77.     }  
  78.   
  79.     private String addBlank2Expression(String oldExpression) {  
  80.         String lastExpression;  
  81.         lastExpression = oldExpression.replace("AND"" AND ").replace("NOT",  
  82.                 " NOT ").replace("OR"" OR ");  
  83.         return lastExpression;  
  84.     }  
  85.   
  86.     public Integer getMaxRetries() {  
  87.         return maxRetries;  
  88.     }  
  89.   
  90.     ……  
  91.         
  92.         public void setMaxTotalConnections(Integer maxTotalConnections) {  
  93.         this.maxTotalConnections = maxTotalConnections;  
  94.     }  
  95. }  
Java代码   收藏代码
  1. package org.uppower.tnt.biz.core.manager.blog.solrj;  
  2.   
  3. import java.net.MalformedURLException;  
  4. import java.util.Map;  
  5.   
  6. import org.apache.solr.client.solrj.SolrQuery;  
  7. import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
  8. import org.apache.solr.client.solrj.response.QueryResponse;  
  9. import org.apache.solr.common.SolrDocumentList;  
  10.   
  11. /** 
  12.  * @author yingmu 
  13.  * @version 2010-7-20 下午02:57:04 
  14.  */  
  15. public class SolrjQuery {  
  16.     private String url;  
  17.     private Integer soTimeOut;  
  18.     private Integer connectionTimeOut;  
  19.     private Integer maxConnectionsPerHost;  
  20.     private Integer maxTotalConnections;  
  21.     private Integer maxRetries;  
  22.     private CommonsHttpSolrServer solrServer = null;  
  23.     private final static String ASC = "asc";  
  24.   
  25.     public void init() throws MalformedURLException {  
  26.         solrServer = new CommonsHttpSolrServer(url);  
  27.         solrServer.setSoTimeout(soTimeOut);  
  28.         solrServer.setConnectionTimeout(connectionTimeOut);  
  29.         solrServer.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost);  
  30.         solrServer.setMaxTotalConnections(maxTotalConnections);  
  31.         solrServer.setFollowRedirects(false);  
  32.         solrServer.setAllowCompression(true);  
  33.         solrServer.setMaxRetries(maxRetries);  
  34.     }  
  35.   
  36.     public SolrDocumentList query(Map<String, String> propertyMap,  
  37.             Map<String, String> compositorMap, Long startIndex, Long pageSize)  
  38.             throws Exception {  
  39.         SolrQuery query = new SolrQuery();  
  40.         // 设置搜索字段  
  41.         if (null == propertyMap) {  
  42.             throw new Exception("搜索字段不可为空!");  
  43.         } else {  
  44.             for (Object o : propertyMap.keySet()) {  
  45.                 StringBuffer sb = new StringBuffer();  
  46.                 sb.append(o.toString()).append(":");  
  47.                 sb.append(propertyMap.get(o));  
  48.                 String queryString = addBlank2Expression(sb.toString());  
  49.                 query.setQuery(queryString);  
  50.             }  
  51.         }  
  52.         // 设置排序条件  
  53.         if (null != compositorMap) {  
  54.             for (Object co : compositorMap.keySet()) {  
  55.                 if (ASC == compositorMap.get(co)  
  56.                         || ASC.equals(compositorMap.get(co))) {  
  57.                     query.addSortField(co.toString(), SolrQuery.ORDER.asc);  
  58.                 } else {  
  59.                     query.addSortField(co.toString(), SolrQuery.ORDER.desc);  
  60.                 }  
  61.             }  
  62.         }  
  63.           
  64.         if (null != startIndex) {  
  65.             query.setStart(Integer.parseInt(String.valueOf(startIndex)));  
  66.         }  
  67.         if (null != pageSize && 0L != pageSize.longValue()) {  
  68.             query.setRows(Integer.parseInt(String.valueOf(pageSize)));  
  69.         }  
  70.         try {  
  71.             QueryResponse qrsp = solrServer.query(query);  
  72.             SolrDocumentList docs = qrsp.getResults();  
  73.             return docs;  
  74.         } catch (Exception e) {  
  75.             throw new Exception(e);  
  76.         }  
  77.     }  
  78.   
  79.     private String addBlank2Expression(String oldExpression) {  
  80.         String lastExpression;  
  81.         lastExpression = oldExpression.replace("AND"" AND ").replace("NOT",  
  82.                 " NOT ").replace("OR"" OR ");  
  83.         return lastExpression;  
  84.     }  
  85.   
  86.     public Integer getMaxRetries() {  
  87.         return maxRetries;  
  88.     }  
  89.   
  90.     ……  
  91.         
  92.         public void setMaxTotalConnections(Integer maxTotalConnections) {  
  93.         this.maxTotalConnections = maxTotalConnections;  
  94.     }  
  95. }  

整个实现是在Spring的基础上完成的,其中SolrjQuery的init()方法在Spring容器启动是初始化。Init()方法内的属性,也是直接注入的。上层与下层之间也完全用注入的方式解决。具体配置就不贴不出来了,大家都会。

整个代码很简陋,但是几乎支持了你想要搜索的条件设置,而且不会暴露任何与solr相关的内容给上层调用,使整个搜索几乎以sql语言的思想在设置条件。


http://www.iteye.com/topic/315330


 

[java]  view plain copy print ?
  1. package org.nstcrm.person.util;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5. import java.net.MalformedURLException;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9. import java.util.TreeMap;  
  10.   
  11. import org.apache.solr.client.solrj.SolrQuery;  
  12. import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
  13. import org.apache.solr.client.solrj.response.QueryResponse;  
  14. import org.apache.solr.common.SolrDocumentList;  
  15.   
  16. public class SolrHttpServer {  
  17.     //private Logger logger = LoggerFactory.getLogger(this.getClass());   
  18.     private final static String URL = "http://localhost:8080/solr";  
  19.     private final static Integer SOCKE_TTIMEOUT = 1000// socket read timeout   
  20.     private final static Integer CONN_TIMEOUT = 100;  
  21.     private final static Integer MAXCONN_DEFAULT = 100;  
  22.     private final static Integer MAXCONN_TOTAL = 100;  
  23.     private final static Integer MAXRETRIES = 1;  
  24.     private static CommonsHttpSolrServer server = null;  
  25.     private final static String ASC = "asc";  
  26.       
  27.     public void init() throws MalformedURLException {  
  28.             server = new CommonsHttpSolrServer( URL );  
  29.             //server.setParser(new XMLResponseParser());   
  30.             server.setSoTimeout(SOCKE_TTIMEOUT);  
  31.             server.setConnectionTimeout(CONN_TIMEOUT);  
  32.             server.setDefaultMaxConnectionsPerHost(MAXCONN_DEFAULT);  
  33.             server.setMaxTotalConnections(MAXCONN_TOTAL);  
  34.             server.setFollowRedirects(false);  
  35.             server.setAllowCompression(true);  
  36.             server.setMaxRetries(MAXRETRIES);  
  37.     }  
  38.       
  39.     public static SolrDocumentList query(Map<String, String> property, Map<String, String> compositor, Integer pageSize) throws Exception {  
  40.         SolrQuery query = new SolrQuery();  
  41.         // 设置搜索字段   
  42.         if(null == property) {  
  43.             throw new Exception("搜索字段不可为空!");  
  44.         } else {  
  45.             for(Object obj : property.keySet()) {  
  46.                 StringBuffer sb = new StringBuffer();  
  47.                 sb.append(obj.toString()).append(":");  
  48.                 sb.append(property.get(obj));  
  49.                 String sql = (sb.toString()).replace("AND"" AND ").replace("OR"" OR ").replace("NOT"" NOT ");  
  50.                 query.setQuery(sql);  
  51.             }  
  52.         }  
  53.         // 设置结果排序   
  54.         if(null != compositor) {  
  55.             for(Object obj : compositor.keySet()) {  
  56.                 if(ASC == compositor.get(obj) || ASC.equals(compositor.get(obj))) {  
  57.                     query.addSortField(obj.toString(), SolrQuery.ORDER.asc);  
  58.                 } else {  
  59.                     query.addSortField(obj.toString(), SolrQuery.ORDER.desc);  
  60.                 }  
  61.             }  
  62.         }  
  63.         if(null != pageSize && 0 < pageSize) {  
  64.             query.setRows(pageSize);  
  65.         }  
  66.         QueryResponse qr = server.query(query);  
  67.         SolrDocumentList docList = qr.getResults();  
  68.         return docList;  
  69.     }  
  70.       
  71.     public static Map<String, String> getQueryProperty(Object obj) throws Exception {  
  72.         Map<String, String> result = new TreeMap<String, String>();  
  73.         // 获取实体类的所有属性,返回Fields数组   
  74.         Field[] fields = obj.getClass().getDeclaredFields();  
  75.         for(Field f : fields) {  
  76.             String name = f.getName();// 获取属性的名字   
  77.             String type = f.getGenericType().toString();  
  78.             if("class java.lang.String".equals(type)) {// 如果type是类类型,则前面包含"class ",后面跟类名   
  79.                 Method me = obj.getClass().getMethod("get" + UpperCaseField(name));  
  80.                 String tem = (String) me.invoke(obj);  
  81.                 if(null != tem) {  
  82.                     result.put(name, tem);  
  83.                 }  
  84.             }  
  85.         }  
  86.         return result;  
  87.     }  
  88.       
  89.     public static List<Object> querySolrResult(Object propertyObj, Object compositorObj, Integer pageSize) throws Exception {  
  90.         Map<String, String> propertyMap = new TreeMap<String, String>();  
  91.         Map<String, String> compositorMap = new TreeMap<String, String>();  
  92.         propertyMap = getQueryProperty(propertyObj);  
  93.         compositorMap = getQueryProperty(compositorObj);  
  94.         SolrDocumentList docList = query(propertyMap, compositorMap, pageSize);  
  95.         List<Object> list = new ArrayList<Object>();  
  96.         for(Object obj : docList) {  
  97.             list.add(obj);  
  98.         }  
  99.         return list;  
  100.     }  
  101.       
  102.     private static String UpperCaseField(String name) {  
  103.         return name.replaceFirst(name.substring(01), name.substring(01).toUpperCase());  
  104.     }  
  105.   
  106.     public CommonsHttpSolrServer getServer() {  
  107.         return server;  
  108.     }  
  109.   
  110.     public void setServer(CommonsHttpSolrServer server) {  
  111.         this.server = server;  
  112.     }  
  113.   
  114. }  
Java代码   收藏代码
  1. package org.nstcrm.person.util;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5. import java.net.MalformedURLException;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8. import java.util.Map;  
  9. import java.util.TreeMap;  
  10.   
  11. import org.apache.solr.client.solrj.SolrQuery;  
  12. import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
  13. import org.apache.solr.client.solrj.response.QueryResponse;  
  14. import org.apache.solr.common.SolrDocumentList;  
  15.   
  16. public class SolrHttpServer {  
  17.     //private Logger logger = LoggerFactory.getLogger(this.getClass());  
  18.     private final static String URL = "http://localhost:8080/solr";  
  19.     private final static Integer SOCKE_TTIMEOUT = 1000// socket read timeout  
  20.     private final static Integer CONN_TIMEOUT = 100;  
  21.     private final static Integer MAXCONN_DEFAULT = 100;  
  22.     private final static Integer MAXCONN_TOTAL = 100;  
  23.     private final static Integer MAXRETRIES = 1;  
  24.     private static CommonsHttpSolrServer server = null;  
  25.     private final static String ASC = "asc";  
  26.       
  27.     public void init() throws MalformedURLException {  
  28.             server = new CommonsHttpSolrServer( URL );  
  29.             //server.setParser(new XMLResponseParser());  
  30.             server.setSoTimeout(SOCKE_TTIMEOUT);  
  31.             server.setConnectionTimeout(CONN_TIMEOUT);  
  32.             server.setDefaultMaxConnectionsPerHost(MAXCONN_DEFAULT);  
  33.             server.setMaxTotalConnections(MAXCONN_TOTAL);  
  34.             server.setFollowRedirects(false);  
  35.             server.setAllowCompression(true);  
  36.             server.setMaxRetries(MAXRETRIES);  
  37.     }  
  38.       
  39.     public static SolrDocumentList query(Map<String, String> property, Map<String, String> compositor, Integer pageSize) throws Exception {  
  40.         SolrQuery query = new SolrQuery();  
  41.         // 设置搜索字段  
  42.         if(null == property) {  
  43.             throw new Exception("搜索字段不可为空!");  
  44.         } else {  
  45.             for(Object obj : property.keySet()) {  
  46.                 StringBuffer sb = new StringBuffer();  
  47.                 sb.append(obj.toString()).append(":");  
  48.                 sb.append(property.get(obj));  
  49.                 String sql = (sb.toString()).replace("AND"" AND ").replace("OR"" OR ").replace("NOT"" NOT ");  
  50.                 query.setQuery(sql);  
  51.             }  
  52.         }  
  53.         // 设置结果排序  
  54.         if(null != compositor) {  
  55.             for(Object obj : compositor.keySet()) {  
  56.                 if(ASC == compositor.get(obj) || ASC.equals(compositor.get(obj))) {  
  57.                     query.addSortField(obj.toString(), SolrQuery.ORDER.asc);  
  58.                 } else {  
  59.                     query.addSortField(obj.toString(), SolrQuery.ORDER.desc);  
  60.                 }  
  61.             }  
  62.         }  
  63.         if(null != pageSize && 0 < pageSize) {  
  64.             query.setRows(pageSize);  
  65.         }  
  66.         QueryResponse qr = server.query(query);  
  67.         SolrDocumentList docList = qr.getResults();  
  68.         return docList;  
  69.     }  
  70.       
  71.     public static Map<String, String> getQueryProperty(Object obj) throws Exception {  
  72.         Map<String, String> result = new TreeMap<String, String>();  
  73.         // 获取实体类的所有属性,返回Fields数组  
  74.         Field[] fields = obj.getClass().getDeclaredFields();  
  75.         for(Field f : fields) {  
  76.             String name = f.getName();// 获取属性的名字  
  77.             String type = f.getGenericType().toString();  
  78.             if("class java.lang.String".equals(type)) {// 如果type是类类型,则前面包含"class ",后面跟类名  
  79.                 Method me = obj.getClass().getMethod("get" + UpperCaseField(name));  
  80.                 String tem = (String) me.invoke(obj);  
  81.                 if(null != tem) {  
  82.                     result.put(name, tem);  
  83.                 }  
  84.             }  
  85.         }  
  86.         return result;  
  87.     }  
  88.       
  89.     public static List<Object> querySolrResult(Object propertyObj, Object compositorObj, Integer pageSize) throws Exception {  
  90.         Map<String, String> propertyMap = new TreeMap<String, String>();  
  91.         Map<String, String> compositorMap = new TreeMap<String, String>();  
  92.         propertyMap = getQueryProperty(propertyObj);  
  93.         compositorMap = getQueryProperty(compositorObj);  
  94.         SolrDocumentList docList = query(propertyMap, compositorMap, pageSize);  
  95.         List<Object> list = new ArrayList<Object>();  
  96.         for(Object obj : docList) {  
  97.             list.add(obj);  
  98.         }  
  99.         return list;  
  100.     }  
  101.       
  102.     private static String UpperCaseField(String name) {  
  103.         return name.replaceFirst(name.substring(01), name.substring(01).toUpperCase());  
  104.     }  
  105.   
  106.     public CommonsHttpSolrServer getServer() {  
  107.         return server;  
  108.     }  
  109.   
  110.     public void setServer(CommonsHttpSolrServer server) {  
  111.         this.server = server;  
  112.     }  
  113.   
  114. }  


 

[java]  view plain copy print ?
  1. Solr 1.4.1配置和SolrJ的用法  
  2. 一、  Solr基本安装和配置  
  3. 1,从官网镜像服务器下载最新版本apache-solr-1.4.1。下载地址:   
  4. http://apache.etoak.com//lucene/solr/,并解压缩   
  5. 2,在D盘建立一个SolrHome文件夹来存放solr的配置文件等,例如:在D盘WORK目录下穿件一个SolrHome文件夹: D:\WORK\SolrHome,  
  6. 3,在刚解压的apache-solr-1.4.1,找到apache-solr-1.4.1\example下找到solr文件夹,复制到SolrHome下.  
  7. 4,将apache-solr-1.4.1\dist\apache-solr-1.4.1.war中的apache-solr-1.4.1.war复制到tomcat中的\webapps下并重命名为solr,启动tomcat,解压war包后,停止tomcat.  
  8. 5,在解压后的solr中找到web.xml,打开:将<env-entry-value>的值设为SolrHome的目录地址  
  9.     <env-entry>  
  10.        <env-entry-name>solr/home</env-entry-name>  
  11.        <env-entry-value>D:\WORK\SolrHome\solr</env-entry-value>  
  12.        <env-entry-type>java.lang.String</env-entry-type>  
  13.     </env-entry>  
  14. 6,在D:\WORK\SolrHome\solr\conf找到solrconfig.xml文件,打开,修改  
  15.     <dataDir>${solr.data.dir:./solr/data}</dataDir>  
  16.  其中solr.data.dir存放的是索引目录.  
  17. 7,添加中文支持,修改tomcat的配置文件server.xml,如下:  
  18.             <Connector port="80" protocol="HTTP/1.1"   
  19.                maxThreads="150" connectionTimeout="20000"   
  20.                redirectPort="8443" URIEncoding="UTF-8"/>  
  21. 8,启动tomcat,IE中输入:http://localhost:80/solr 即可浏览solr服务器.   
  22. 二、Solr服务器复制的配置  
  23. 1,首先测试在本机上开启三个tomcat的服务器:一个端口是80,另一个是9888  
  24. 2,按照标题一的配置对第二和第三个tomcat服务器进行类似的配置,注意SolrHome的目录不要相同即可,其他的配置不变. 例如:以本机为例  
  25.   
  26.   
  27. tomcat命名         URL    SolrHome目录URI         web.xml配置  
  28. tomcat0 (master)    http://localhost:80/solr    D:\WORK\SolrHome\solr   <env-entry-value>D:\WORK\SolrHome\solr</env-entry-value>   
  29. tomcat1 (slave) http://localhost:9888/solr  E:\WORK\SolrHome\solr   <env-entry-value>E:\WORK\SolrHome\solr</env-entry-value>   
  30. tomcat2  
  31. (salve) http://localhost:9008/solr  F:\WORK\SolrHome\solr   <env-entry-value>F:\WORK\SolrHome\solr</env-entry-value>   
  32.   
  33.   
  34.   
  35.   
  36. 3,以上两步配置好之后,在主服务器tomcat0(master)的SolrHome中找到solrconfig.xml文件,加入如下配置.  
  37.     <requestHandler name="/replication" class="solr.ReplicationHandler" >  
  38.     <lst name="master">  
  39.       <str name="replicateAfter">commit</str>  
  40.       <str name="replicateAfter">startup</str>  
  41.       <str name="confFiles">schema.xml,stopwords.txt</str>  
  42.     </lst>  
  43.  </requestHandler>  
  44. 在从服务器tomcat1(slave)和tomcat1(slave)的SolrHome中找到solrconfig.xml文件加入如下配置:  
  45.     <requestHandler name="/replication" class="solr.ReplicationHandler" >    
  46.         <lst name="slave">    
  47.           <str name="masterUrl">http://localhost/solr/replication</str>     
  48.           <str name="pollInterval">00:00:60</str>    
  49.         </lst>    
  50.     </requestHandler>  
  51. 4,在tomcat0上创建索引,使用客户端solrj创建索引,jar包在apache-solr-1.4.1压缩包中.代码如下:  
  52.   public class SlorTest3 {  
  53.     private static CommonsHttpSolrServer  server = null;  
  54. //  private static SolrServer server = null;   
  55.     public SlorTest3(){  
  56.         try {  
  57.             server = new CommonsHttpSolrServer("http://localhost/solr");  
  58.             server.setConnectionTimeout(100);  
  59.             server.setDefaultMaxConnectionsPerHost(100);  
  60.             server.setMaxTotalConnections(100);  
  61.         } catch (IOException e) {  
  62.             e.printStackTrace();  
  63.         }  
  64.               
  65.     }  
  66.     @Test  
  67.     public void testIndexCreate(){  
  68.         List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();  
  69.         for(int i=300;i<500;i++){  
  70.             SolrInputDocument doc = new SolrInputDocument();  
  71.             doc.addField("zjid", i);  //需要在sechma.xml中配置字段   
  72.             doc.addField("title""云状空化多个气泡的生长和溃灭");  
  73.             doc.addField("ssid""ss"+i);  
  74.             doc.addField("dxid""dx"+i);  
  75.             docs.add(doc);  
  76.         }  
  77.             try {  
  78.                 server.add(docs);  
  79.                 server.commit();  
  80.                 System.out.println("----索引创建完毕!!!----");  
  81.             } catch (SolrServerException e) {  
  82.                 e.printStackTrace();  
  83.             } catch (IOException e) {  
  84.                 e.printStackTrace();  
  85.             }  
  86.     }  
  87. }  
  88. 5,分别启动三台tomcat服务器.打开IE浏览器分别输入:其中localhost=192.168.169.121  
  89. http://localhost:9888/solr 点击 即可从主solr服务器上复制索引   
  90.      
  91.   
  92. 三、Solr服务器分发(shard)配置  
  93. 1,  开启四台tomcat服务器,其中三台在本机上,一台在远端.清单如下:  
  94.  注意:四台服务器的配置要相同.其中的schema.xml字段配置一定要一致.  
  95.   
  96. Name         URL    SolrHome目录URI     
  97. tomcatQuery http://localhost:80/solr    D:\WORK\SolrHome\solr      
  98. tomcat0 (shard) http://localhost:9888/solr  E:\WORK\SolrHome\solr      
  99. tomcat1 (shard) http://localhost:9008/solr  F:\WORK\SolrHome\solr      
  100. tomcat2 (shard) http://192.168.169.48:9888/solr D:\WORK\SolrHome\solr      
  101.   
  102.   
  103.   
  104. 2,  配置较简单,只需要在tomcatQuery上的SoleHome的solrconfig.xml文件中修改  
  105. 其他的solr服务器不需要配置。  
  106.   <requestHandler name="standard" class="solr.SearchHandler" default="true">  
  107.     <!-- default values for query parameters -->  
  108.      <lst name="defaults">  
  109.        <str name="echoParams">explicit</str>  
  110.        <str name="shards">localhost:9088/solr,localhost:9888/solr,192.168.169.48:9888/solr</str>  
  111.        <!--  
  112.        <int name="rows">10</int>  
  113.        <str name="fl">*</str>  
  114.        <str name="version">2.1</str>  
  115.         -->  
  116.      </lst>  
  117.   </requestHandler>  
  118. 3,  使用slorj的清除原有的索引.或者手动删除。  
  119. 4,  编写代码,将lucene建立的索引(1G左右,874400条记录),按照比例通过solrj分发到三台solr(shard)服务器上,代码如下:  
  120. public class IndexCreate{  
  121.     private static CommonsHttpSolrServer server;  
  122.     public  CommonsHttpSolrServer getServer(String hostUrl){  
  123.         CommonsHttpSolrServer server = null;  
  124.         try {  
  125.             server = new CommonsHttpSolrServer(hostUrl);  
  126.             server.setConnectionTimeout(100);  
  127.             server.setDefaultMaxConnectionsPerHost(100);  
  128.             server.setMaxTotalConnections(100);  
  129.         } catch (IOException e) {  
  130.             System.out.println("请检查tomcat服务器或端口是否开启!");  
  131.         }  
  132.         return server;  
  133.     }  
  134.     @SuppressWarnings("deprecation")  
  135.     public void readerHostCreate(String[] hosts) throws CorruptIndexException, IOException{  
  136.         IndexReader reader = IndexReader.open("c:\\index");  
  137.         System.out.println("总记录数: "+reader.numDocs());  
  138.         int hostNum = hosts.length;  
  139.         int lengh = reader.numDocs()/hostNum; //根据主机数平分索引长度   
  140.         int j = reader.numDocs()%hostNum;     //取余   
  141.         for(int i = 0;i<hosts.length;i++){  
  142.             long startTime = new Date().getTime();  
  143.             String url = hosts[i].substring(hosts[i].indexOf("//")+2,hosts[i].lastIndexOf("/"));  
  144.             System.out.println("第"+(i+1)+"次,在主机:"+url+" 上创建索引,创建时间"+new Date());  
  145.             if(i==(hosts.length-1)){  
  146.                 hostlist(reader,lengh*i,lengh*(i+1)+j,hosts[i]);  
  147.               
  148.             }else{  
  149.                 hostlist(reader,lengh*i,lengh*(i+1),hosts[i]);  
  150.             }  
  151.             System.out.println("结束时间"+new Date());  
  152.             long endTime = new Date().getTime();  
  153.             long ms = (endTime-startTime)%60000-(((endTime-startTime)%60000)/1000)*1000;  
  154.             System.out.println("本次索引创建完毕,一共用了"+(endTime-startTime)/60000+"分" +  
  155.                     ""+((endTime-startTime)%60000)/1000+"秒"+ms+"毫秒");  
  156.             System.out.println("****************************");  
  157.         }  
  158.         reader.close();  
  159.     }  
  160.     @SuppressWarnings("static-access")  
  161.     public void hostlist(IndexReader reader,int startLengh,int endLengh,String hostUrl) throws CorruptIndexException, IOException{  
  162.         List<BookIndex> beans = new LinkedList<BookIndex>();  
  163.         int count = 0;  
  164.         this.server = getServer(hostUrl);  
  165.         for(int i=startLengh;i<endLengh;i++){  
  166.             Document doc = reader.document(i);  
  167.             BookIndex book = new BookIndex();  
  168.             book.setZjid(doc.getField("zjid").stringValue());  
  169.             book.setTitle(doc.getField("title").stringValue());  
  170.             book.setSsid(doc.getField("ssid").stringValue());  
  171.             book.setDxid(doc.getField("dxid").stringValue());  
  172.             book.setBookname(doc.getField("bookname").stringValue());  
  173.             book.setAuthor(doc.getField("author").stringValue());  
  174.             book.setPublisher(doc.getField("publisher").stringValue());  
  175.             book.setPubdate(doc.getField("pubdate").stringValue());  
  176.             book.setYear(doc.getField("year").stringValue());  
  177.             book.setFenlei(doc.getField("fenlei").stringValue());  
  178.             book.setscore1(doc.getField("score").stringValue());  
  179.             book.setIsbn(doc.getField("isbn").stringValue());  
  180.             book.setFenleiurl(doc.getField("fenleiurl").stringValue());  
  181.             book.setMulu(doc.getField("mulu").stringValue());  
  182.             book.setIsp(doc.getField("isp").stringValue());  
  183.             book.setIep(doc.getField("iep").stringValue());  
  184.             beans.add(book);  
  185.             if(beans.size()%3000==0){  
  186.                 createIndex(beans,hostUrl,server);  
  187.                 beans.clear();  
  188.                 System.out.println("---索引次数:"+(count+1)+"---");  
  189.                 count++;  
  190.             }  
  191.         }  
  192.         System.out.println("beansSize 的大小 "+beans.size());  
  193.         if(beans.size()>0){  
  194.             createIndex(beans,hostUrl,server);  
  195.             beans.clear();  
  196.         }  
  197.           
  198.     }  
  199.     public void createIndex(List<BookIndex> beans,String hostUrl,CommonsHttpSolrServer server){  
  200.         try {  
  201.                 server.addBeans(beans);  
  202.                 server.commit();  
  203.         } catch (SolrServerException e) {  
  204.             e.printStackTrace();  
  205.         } catch (IOException e) {  
  206.             e.printStackTrace();  
  207.         }  
  208.     }  
  209.     public static void main(String[] args) throws CorruptIndexException, IOException{  
  210.         IndexCreate as = new IndexCreate();  
  211.         String[] hosts = new String[] {"http://192.168.169.121:9888/solr","http://192.168.169.121:9088/solr","http://192.168.169.48:9888/solr"};  
  212.         long startTime = new Date().getTime();  
  213.         as.readerHostCreate(hosts);  
  214.         long endTime = new Date().getTime();  
  215.         System.out.println("-------------------");  
  216.         long ms = (endTime-startTime)%60000-(((endTime-startTime)%60000)/1000)*1000;  
  217.         System.out.println("全部索引创建完毕,一共用了"+(endTime-startTime)/60000+"分" +  
  218.                 ""+((endTime-startTime)%60000)/1000+"秒"+ms+"毫秒");  
  219.     }  
  220.   
  221. }  
  222. JavaBean类BookIndex.java代码如下:  
  223. 说明变量名与sechma.xml中的配置要相同.注意:不能使用score这个变量或者字段,与slor配置冲突,报exception。  
  224. import org.apache.solr.client.solrj.beans.Field;  
  225.   
  226. public class BookIndex {  
  227.     @Field    
  228.     private String zjid ;  
  229.     @Field    
  230.     private String title;  
  231.     @Field    
  232.     private String ssid;  
  233.     @Field    
  234.     private String dxid;  
  235.     @Field   
  236.     private String bookname;  
  237.     @Field   
  238.     private String author;  
  239.     @Field   
  240.     private String publisher;  
  241.     @Field   
  242.     private String pubdate;  
  243.     @Field   
  244.     private String year;  
  245.     @Field   
  246.     private String fenlei;  
  247.     @Field   
  248.     private String score1;  
  249.     @Field   
  250.     private String isbn;  
  251.     @Field   
  252.     private String fenleiurl;  
  253.     @Field   
  254.     private String mulu;  
  255.     @Field   
  256.     private String isp;  
  257.     @Field   
  258.     private String iep;  
  259.     public getters();//get方法   
  260.     public setters();//set方法   
  261. }  
  262.   
  263.   
  264. 5,  同时开启四台服务器,运行上面代码:  
  265. 6,  打开IE查询  
  266. 打开:http://localhost/solr   
  267. 打开:http://localhost:9888/solr   
  268. 打开http://localhost:9008/solr   
  269. 打开http://192.168.168.48:9888/solr   
  270.   
  271. 四、Solr的Multicore(分片)配置  
  272. 第一步,将apache-solr-1.4.1\example下的multicore复制到先前配置的solr/home下。  
  273.     其中multicore下的solr.xml配置如下:  
  274. <solr persistent="false">  
  275.    <cores adminPath="/admin/cores">  
  276.     <core name="core0" instanceDir="core0">    
  277.       <property name="dataDir" value="/data/core0" />    
  278.     </core>  
  279.     <core name="core1" instanceDir="core1">  
  280.       <property name="dataDir" value="/data/core1" />    
  281.     </core>  
  282.     <core name="core2" instanceDir="core2">  
  283.       <property name="dataDir" value="/data/core2" />    
  284.     </core>  
  285.   </cores>  
  286. </solr>  
  287. 第二步,修改Tomcat 6.0\webapps\solr\WEB-INF下的web.xml文件如下  
  288. <env-entry-value>D:\WORK\SolrHome\multicore</env-entry-value>  
  289. 第三步,开启服务器,打开IEhttp://localhost/solr   
  290.    
  291. 五、SolrJ的用法  
  292. 1,SolrJ的用法  
  293.   solrJ是与solr服务器交互的客户端工具.使用solrJ不必考虑solr服务器的输出格式,以及对文档的解析。solrJ会根据用户发送的请求将数据结果集(collection)返回给用户.  
  294. 2,使用SolrJ建立索引  
  295.   事例代码:  
  296. //得到连接solr服务器的CommonsHttpSolrServer对象.通过这个对象处理用户提交的请求:   
  297.  CommonsHttpSolrServer server = new CommonsHttpSolrServer("http://localhost:9888/solr");  
  298. public void testIndexCreate(){  
  299.         List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();  
  300. // SolrInputDocumentle类似与Document类,用于创建索引文档,和向文档中添加字段   
  301.         for(int i=300;i<500;i++){  
  302.             SolrInputDocument doc = new SolrInputDocument();  
  303.             doc.addField("zjid", i+"_id");    
  304.             doc.addField("title", i+"_title");  
  305.             doc.addField("ssid""ss_"+i);  
  306.             doc.addField("dxid""dx_"+i);  
  307.             docs.add(doc);  
  308.         }  
  309.             try {  
  310.                 server.add(docs);  
  311.                 server.commit();//以更新(update)的方式提交   
  312.                 System.out.println("----索引创建完毕!!!----");  
  313.             } catch (SolrServerException e) {  
  314.                 e.printStackTrace();  
  315.             } catch (IOException e) {  
  316.                 e.printStackTrace();  
  317.             }  
  318.     }  
  319. 以javaBean的方式创建索引:  
  320. public class BookIndex {  
  321.     @Field  
  322.     private String zjid;  
  323.     @Field  
  324.     private String zhangjie;  
  325.     @Field  
  326.     private String ssid;  
  327.     @Field  
  328.     private String qwpos;  
  329.     @Field  
  330.     private String publishDate;  
  331.     @Field  
  332.     private String mulu;  
  333.     @Field  
  334.     private String fenleiurl;  
  335.     @Field  
  336.     private String fenlei;  
  337.     @Field  
  338.     private String dxid;  
  339.     @Field  
  340.     private String author;  
  341.     @Field  
  342.     private String address;  
  343.     @Field  
  344.     private String bookname;  
  345. …………………  
  346. }  
  347. public void testBean(){  
  348.         List<BookIndex> beans = new ArrayList<BookIndex>();  
  349.         for(int i=0;i<10;i++){  
  350.             BookIndex book = new BookIndex();  
  351.             book.setZjid(i+"id");  
  352.             book.setTitle(i+"title");  
  353.             //set方法   
  354.             beans.add(book);  
  355.         }  
  356.         try {  
  357.             server.addBeans(beans);  
  358.             server.commit();  
  359.             System.out.println("----索引创建完毕!!!----");  
  360.         } catch (SolrServerException e) {  
  361.             e.printStackTrace();  
  362.         } catch (IOException e) {  
  363.             e.printStackTrace();  
  364.         }  
  365.     }  
  366. 3,  SolrJ常见的查询   
  367.   a,  查询索引中的全部字段的内容:  SolrQuery query = new SolrQuery("*:*");  
  368.    事例代码:  
  369.    public void testQuery1(){  
  370.         SolrQuery query = new SolrQuery("*:*");  
  371.         query.setStart(20);//设置起始位置   
  372.         query.setRows(10); //查询组数   
  373.         QueryResponse response = null;   
  374.         try {  
  375.             response = server.query(query);//响应向服务器提交的查询请求   
  376.             System.out.println(response);  
  377.         } catch (SolrServerException e) {  
  378.             e.printStackTrace();  
  379.         }  
  380.           
  381.         List<SolrDocument> docs = response.getResults();//得到结果集   
  382.         for(SolrDocument doc:docs){//遍历结果集   
  383.             for(Iterator iter = doc.iterator();iter.hasNext();){  
  384. Map.Entry<String, Object> entry = (Entry<String, Object>)iter.next();  
  385.                 System.out.print("Key :"+entry.getKey()+"  ");  
  386.                 System.out.println("Value :"+entry.getValue());  
  387.             }  
  388.             System.out.println("------------");  
  389.         }     
  390. }  
  391. b, 查询某一字段的内容  
  392.     String queryString  = “zjid:5_id”;//写法为字段名:查询的内容   
  393.     SolrQuery query = new SolrQuery(queryString);  
  394. c, 查询copyField的内容  
  395.    copyField是查询的默认字段,当不指明查询字段的field的时。查询的请求会在copyField匹配: 详细参见schema..xml的配置.  
  396.     String queryString  = “XXX”  
  397.    SolrQuery query = new SolrQuery(queryString);  
  398. 4,  索引删除  
  399. 事例代码 :  
  400.  public void testClear() {  
  401.         server.setRequestWriter(new BinaryRequestWriter());//提高性能采用流输出方式   
  402.         try {  
  403.             server.deleteByQuery("*:*");  
  404.             server.commit();  
  405.             System.out.println("----清除索引---");  
  406.         } catch (SolrServerException e) {  
  407.             e.printStackTrace();  
  408.         } catch (IOException e) {  
  409.             e.printStackTrace();  
  410.         }  
  411.     }  
  412. 5,  高亮的使用Highlight  
  413. public List<Book> getQueryString(String queryString,int start,int pageSize) {  
  414.         SolrQuery query = new SolrQuery(queryString);  
  415.         query.setHighlight(true); //开启高亮组件   
  416.         query.addHighlightField("mulu");//高亮字段   
  417.         query.setHighlightSimplePre("<font color=\"red\">");//标记   
  418.         query.setHighlightSimplePost("</font>");  
  419.         query.set("hl.usePhraseHighlighter"true);  
  420.         query.set("hl.highlightMultiTerm"true);  
  421.         query.set("hl.snippets"3);//三个片段,默认是1   
  422.         query.set("hl.fragsize"50);//每个片段50个字,默认是100   
  423.         //   
  424.         query.setStart(start); //起始位置 …分页   
  425.         query.setRows(pageSize);//文档数   
  426.           
  427.         try {  
  428.             response = server.query(query);  
  429.         } catch (SolrServerException e) {  
  430.             e.printStackTrace();  
  431.         }  
  432.         List<BookIndex> bookLists = response.getBeans(BookIndex.class);  
  433.         Map<String,Map<String,List<String>>> h1 = response.getHighlighting();  
  434.           
  435.         List<Book> books = new ArrayList<Book>();  
  436.         for(BookIndex bookIndex : bookLists){  
  437.             Map<String,List<String>>  map = h1.get(bookIndex.getZjid());  
  438. //以文档的唯一id作为Map<String,Map<String,List<String>>>的key值.   
  439.             Book book = new Book();  
  440.             //copy字段   
  441.             book.setBookname(bookIndex.getBookname());  
  442.             book.setZjid(bookIndex.getZjid());  
  443.             if(map.get("mulu")!=null){  
  444.                 List<String> strMulu = map.get("mulu");  
  445.                 StringBuffer buf  = new StringBuffer();  
  446.                 for(int i =0;i<strMulu.size();i++){  
  447.                     buf.append(strMulu.get(i));  
  448.                     buf.append("...");  
  449.                     if(i>3){  
  450.                         break;  
  451.                     }  
  452.                 }  
  453.                 book.setSummary(buf.toString());  
  454.             }else{  
  455.                 if(bookIndex.getMulu().length()>100){  
  456.                     book.setSummary(bookIndex.getMulu().substring(0,100)+"...");  
  457.                 }else{  
  458.                     book.setSummary(bookIndex.getMulu()+"...");  
  459.                 }  
  460.                   
  461.             }  
  462.                 books.add(book);  
  463.         }  
  464.         return books;  
  465.       
  466.     }  
  467. 6, 分组Fact  
  468. //需要注意的是参与分组的字段是不需要分词的,比如:产品的类别.kind   
  469. public void testFact(){  
  470.         String queryString = "kind:儿童图书";  
  471.         SolrQuery query = new SolrQuery().setQuery(queryString);  
  472.         query.setFacet(true); //开启分组   
  473.         query.addFacetField("bookname");//分组字段   
  474. query.addFacetField("title");  
  475.         query.setFacetMinCount(1);  
  476. query.addSortField( "zjid", SolrQuery.ORDER.asc );//排序字段   
  477.   
  478.         query.setRows(10);  
  479.         QueryResponse response = null;  
  480.         try {  
  481.             response = server.query(query);  
  482.             System.out.println(response);  
  483.         } catch (SolrServerException e) {  
  484.             e.printStackTrace();  
  485.         }  
  486.         List<FacetField> facets = response.getFacetFields();  
  487.         for (FacetField facet : facets) {  
  488.           System.out.println("Facet:" + facet);  
  489.         }  
  490.           
  491.     }   
  492.   
  493. 六、一个简单的web引用:  
  494.  首先说明的是索引来源,是根据已有的lucene索引上开发的,又因为lucene的索引直接用solrJ应用效果不好,会出现很多问题,找不到类似的解决办法,比如全字段查询,和高亮分组等,和多级索引目录…。但用solrJ创建的索引不存在类似的问题.  
  495.  大致的思路是,读取已有的lucene索引 ,再用solrJ创建索引并分发到多台机器上,最后再做开发.  
  496.  第一步:读取lucene的多级索引目录,用solrJ创建和分发索引;  
  497. 需注意的是:要加大虚拟机的内存,因为采用的map做为缓存,理论上虚拟机的内存大,map的存储的索引文档数也就多.主要是针对内存溢出.  
  498.   代码 :  
  499. package org.readerIndex;  
  500. import org.apache.solr.client.solrj.beans.Field;  
  501. public class BookIndex2 {  
  502.     @Field  
  503.     private String zjid;  
  504.     @Field  
  505.     private String zhangjie;  
  506.     @Field  
  507.     private String ssid;  
  508.     @Field  
  509.     private String qwpos;  
  510.     @Field  
  511.     private String publishDate;  
  512.     @Field  
  513.     private String mulu;  
  514.     @Field  
  515.     private String fenleiurl;  
  516.     @Field  
  517.     private String fenlei;  
  518.     @Field  
  519.     private String dxid;  
  520.     @Field  
  521.     private String author;  
  522.     @Field  
  523.     private String address;  
  524.     @Field  
  525.     private String bookname;  
  526.     public String getZjid() {  
  527.         return zjid;  
  528.    …………………………………………  
  529.     }  
  530. package org.readerIndex;  
  531.   
  532. import java.io.File;  
  533. import java.io.IOException;  
  534. import java.text.SimpleDateFormat;  
  535. import java.util.ArrayList;  
  536. import java.util.Date;  
  537. import java.util.List;  
  538.   
  539.   
  540. import org.apache.lucene.document.Document;  
  541. import org.apache.lucene.index.CorruptIndexException;  
  542. import org.apache.lucene.index.IndexReader;  
  543. import org.apache.lucene.store.LockObtainFailedException;  
  544. import org.apache.solr.client.solrj.SolrServerException;  
  545. import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
  546.   
  547.   
  548.   
  549.   
  550. public class ReaderIndex {  
  551.     public  CommonsHttpSolrServer getServer(String hostUrl){  
  552.         CommonsHttpSolrServer server = null;  
  553.         try {  
  554.             server = new CommonsHttpSolrServer(hostUrl);  
  555.             server.setConnectionTimeout(100);  
  556.             server.setDefaultMaxConnectionsPerHost(100);  
  557.             server.setMaxTotalConnections(100);  
  558.         } catch (IOException e) {  
  559.             System.out.println("请检查tomcat服务器或端口是否开启!");  
  560.         }  
  561.         return server;  
  562.     }  
  563.     public void indexDocuements(String path,String[] hostUrls) throws CorruptIndexException, LockObtainFailedException, IOException{  
  564.         File pareFile = new File(path);  
  565.         List<String> list = new ArrayList<String>();  
  566.         getFile(pareFile,list); //递归方法得到路径保存到list中   
  567.         System.out.println("***程序一共递归到"+list.size()+"个索引目录***");  
  568.         int arevageSize = list.size()/hostUrls.length;// 根据主机数平分目录   
  569.         int remainSize  = list.size()%hostUrls.length;//取余   
  570.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  571.         for(int i=0;i<hostUrls.length;i++){  
  572.             Date startDate = new Date();  
  573.             String url = hostUrls[i].substring(hostUrls[i].indexOf("//")+2,hostUrls[i].lastIndexOf("/"));  
  574.             System.out.println("第"+(i+1)+"次,在主机:"+url+" 上创建索引,创建时间  "+sdf.format(startDate));  
  575.             if(i==(hostUrls.length-1)){  
  576.                 list(list,arevageSize*i,arevageSize*(i+1)+remainSize,hostUrls[i]);  
  577.             }else{  
  578.                 list(list,arevageSize*i,arevageSize*(i+1),hostUrls[i]);  
  579.             }  
  580.             Date endDate = new Date();  
  581.             System.out.println("本次索引结束时间为:"+sdf.format(endDate));  
  582.         }  
  583.   
  584.     }  
  585.     public void list(List<String> list,int start,int end,String url){  
  586.         CommonsHttpSolrServer server = getServer(url);  
  587.         for(int j=start;j<end;j++){  
  588.             try {  
  589.                 long startMs = System.currentTimeMillis();  
  590.                 hostCreate(list.get(j),server);  
  591.                 long endMs = System.currentTimeMillis();  
  592.                 System.out.println("程序第"+(j+1)+"个目录处理完毕,目录路径:"+list.get(j)+", 耗时"+(endMs-startMs)+"ms");  
  593.             } catch (CorruptIndexException e) {  
  594.                 e.printStackTrace();  
  595.             } catch (IOException e) {  
  596.                 e.printStackTrace();  
  597.             }  
  598.         }  
  599.     }  
  600.     public void getFile(File fileDirectory,List<String> list){  
  601.         if(fileDirectory.isDirectory()){  
  602.             File[] files = fileDirectory.listFiles();  
  603.             for(File file :files){  
  604.             getFile(file,list);  
  605.             }  
  606.         }else if(fileDirectory.isFile()){  
  607.             String filePath = fileDirectory.getPath();  
  608.             String path = filePath.replace('\\', '/');  
  609.             if(path.endsWith(".cfs")){  
  610.                 int lastIndex = path.lastIndexOf("/");  
  611.                 String directory = path.substring(0,lastIndex);  
  612.                 list.add(directory);  
  613.             }  
  614.         }  
  615.     }  
  616.     @SuppressWarnings("deprecation")  
  617.     public void hostCreate(String directory,CommonsHttpSolrServer server) throws CorruptIndexException, IOException{  
  618.         IndexReader reader = IndexReader.open(directory);  
  619.         List<BookIndex2> beans = new ArrayList<BookIndex2>();  
  620.         for(int i=0;i<reader.numDocs();i++){  
  621.             Document doc = reader.document(i);  
  622.             BookIndex2 book = new BookIndex2();  
  623.             book.setZjid(doc.getField("zjid").stringValue());  
  624.             book.setAddress(doc.getField("address").stringValue());  
  625.             book.setAuthor(doc.getField("author").stringValue());  
  626.             book.setbookname(doc.getField("bookname").stringValue());  
  627.             book.setDxid(doc.getField("dxid").stringValue());  
  628.             book.setFenlei(doc.getField("fenlei").stringValue());  
  629.             book.setFenleiurl(doc.getField("fenleiurl").stringValue());  
  630.             book.setMulu(doc.getField("mulu").stringValue());  
  631.             book.setPublishDate(doc.getField("publishDate").stringValue());  
  632.             book.setQwpos(doc.getField("qwpos").stringValue());  
  633.             book.setSsid(doc.getField("ssid").stringValue());  
  634.             book.setZhangjie(doc.getField("zhangjie").stringValue());  
  635.             beans.add(book);  
  636.             }  
  637.         createIndex(beans,server);  
  638.         beans.clear();  
  639.         reader.close();  
  640.     }  
  641.     public void createIndex(List<BookIndex2> beans,CommonsHttpSolrServer server){  
  642.         try {  
  643.                 server.addBeans(beans);  
  644.                 server.commit();  
  645. //              server.optimize();   
  646.         } catch (SolrServerException e) {  
  647.             e.printStackTrace();  
  648.         } catch (IOException e) {  
  649.             e.printStackTrace();  
  650.         }  
  651.     }  
  652.       
  653.     public static void main(String[] args) throws CorruptIndexException, IOException{  
  654.         ReaderIndex reader = new ReaderIndex();  
  655.         String path = "D:\\91";  
  656.         String[] hosts = new String[] {"http://192.168.169.121:9888/solr","http://192.168.169.121:9088/solr","http://192.168.169.48:9888/solr"};  
  657.           
  658.         long startTime = new Date().getTime();  
  659.         reader.indexDocuements(path,hosts);  
  660.         long endTime = new Date().getTime();  
  661.         System.out.println("-------------------");  
  662.         long ms = (endTime-startTime)%60000-(((endTime-startTime)%60000)/1000)*1000;  
  663.         System.out.println("全部文档索引完毕,一共用了"+(endTime-startTime)/60000+"分" +  
  664.                 ""+((endTime-startTime)%60000)/1000+"秒"+ms+"毫秒");  
  665.           
  666.     }  
  667.           
  668.       
  669. }  
  670.   
  671.   
  672.   
  673.   
  674.   
  675.   
  676.   
  677.   
  678.   

猜你喜欢

转载自blog.csdn.net/wushuchu/article/details/52690989