`

全文搜索服务器solr之客户端 - solrj二次开发

阅读更多

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

    比如如下一个类:

 

  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. }  
package org.uppower.tnt.biz.core.manager.blog.dataobject;

/**
 * @author yingmu
 * @version 2010-7-20 下午01:00:55
 */
public class SolrPropertyDO {
	private String auction_id;
	private String opt_tag;
	private String exp_tag;
	private String title;
	private String desc;
	private String brand;
	private String category;
	private String price;
	private String add_prov;
	private String add_city;
	private String quality;
	private String flag;
	private String sales;
	private String sellerrate;
	private String selleruid;
	private String ipv15;

	public String getAuction_id() {
		return auction_id;
	}

	public void setAuction_id(String auctionId) {
		auction_id = auctionId;
	}

    ……

	public String getExp_tag() {
		return exp_tag;
	}

	public void setExp_tag(String expTag) {
		exp_tag = expTag;
	}
}

那么我们在定义搜索对象时候,就按照如下设置:
  1. SolrPropertyDO propertyDO = new SolrPropertyDO();  
  2.         propertyDO.setAdd_city("(杭州AND成都)OR北京");  
  3.         propertyDO.setTitle("丝绸OR剪刀");  
  4.          ……  
SolrPropertyDO propertyDO = new SolrPropertyDO();
		propertyDO.setAdd_city("(杭州AND成都)OR北京");
		propertyDO.setTitle("丝绸OR剪刀");
         ……

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

 

  1. SolrPropertyDO compositorDO = new SolrPropertyDO();  
  2.         compositorDO.setPrice ("desc");  
  3.         compositorDO.setQuality ("asc");  
  4.          ……  
SolrPropertyDO compositorDO = new SolrPropertyDO();
		compositorDO.setPrice ("desc");
		compositorDO.setQuality ("asc");
         ……

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

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

 

  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. }  
package org.uppower.tnt.biz.core.manager.blog;

import java.util.List;

import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;

/**
 * @author yingmu
 * @version 2010-7-20 下午03:51:15
 */
public interface SolrjOperator {

	/**
	 * 获得搜索结果
	 * 
	 * @param propertyDO
	 * @param compositorDO
	 * @param startIndex
	 * @param pageSize
	 * @return
	 * @throws Exception
	 */
	public List<Object> querySolrResult(Object propertyDO,
			Object compositorDO, Long startIndex, Long pageSize)
			throws Exception;

	/**
	 * 获得搜索结果条数
	 * 
	 * @param propertyDO
	 * @param compositorDO
	 * @return
	 * @throws Exception
	 */
	public Long querySolrResultCount(SolrPropertyDO propertyDO,
			Object compositorDO) throws Exception;

}

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

 

  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. }  
package org.uppower.tnt.biz.core.manager.blog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.solr.common.SolrDocumentList;

import org.uppower.tnt.biz.core.manager.isearch.common.SolrjCommonUtil;
import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;
import org.uppower.tnt.biz.core.manager.isearch.solrj.SolrjQuery;

/**
 * @author yingmu
 * @version 2010-7-20 下午03:51:15
 */
public class DefaultSolrOperator implements SolrjOperator {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	private SolrjQuery solrjQuery;

	public void setSolrjQuery(SolrjQuery solrjQuery) {
		this.solrjQuery = solrjQuery;
	}

	@Override
	public List<Object> querySolrResult(Object propertyDO,
			Object compositorDO, Long startIndex, Long pageSize)
			throws Exception {
		Map<String, String> propertyMap = new TreeMap<String, String>();
		//排序有顺序,使用TreeMap
		Map<String, String> compositorMap = new TreeMap<String, String>();
		try {
			propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);
			compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);
		} catch (Exception e) {
			logger.error("SolrjCommonUtil.getSearchProperty() is error !"+ e);
		}
		SolrDocumentList solrDocumentList = solrjQuery.query(propertyMap, compositorMap,
				startIndex, pageSize);
		List<Object> resultList = new ArrayList<Object>();
		for (int i = 0; i < solrDocumentList.size(); i++) {
			resultList.add(solrDocumentList.get(i));
		}
		return resultList;
	}

	@Override
	public Long querySolrResultCount(SolrPropertyDO propertyDO,
			Object compositorDO) throws Exception {
		Map<String, String> propertyMap = new TreeMap<String, String>();
		Map<String, String> compositorMap = new TreeMap<String, String>();
		try {
			propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);
			compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);
		} catch (Exception e) {
			logger.error("SolrjCommonUtil.getSearchProperty() is error !" + e);
		}
		SolrDocumentList solrDocument = solrjQuery.query(propertyMap, compositorMap,
				null, null);
		return solrDocument.getNumFound();
	}

}

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

 

  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. }  
package org.uppower.tnt.biz.core.manager.blog.common;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yingmu
 * @version 2010-7-20 下午01:07:15
 */
public class SolrjCommonUtil {

	public static Map<String, String> getSearchProperty(Object model)
			throws NoSuchMethodException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		Map<String, String> resultMap = new TreeMap<String, String>();
		// 获取实体类的所有属性,返回Field数组
		Field[] field = model.getClass().getDeclaredFields();
		for (int i = 0; i < field.length; i++) { // 遍历所有属性
			String name = field[i].getName(); // 获取属性的名字
			// 获取属性的类型
			String type = field[i].getGenericType().toString();
			if (type.equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名
				Method m = model.getClass().getMethod(
						"get" + UpperCaseField(name));
				String value = (String) m.invoke(model); // 调用getter方法获取属性值
				if (value != null) {
					resultMap.put(name, value);
				}
			}
		}
		return resultMap;
	}

	// 转化字段首字母为大写
	private static String UpperCaseField(String fieldName) {
		fieldName = fieldName.replaceFirst(fieldName.substring(0, 1), fieldName
				.substring(0, 1).toUpperCase());
		return fieldName;
	}

}

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

 

  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. }  
package org.uppower.tnt.biz.core.manager.blog.solrj;

import java.net.MalformedURLException;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;

/**
 * @author yingmu
 * @version 2010-7-20 下午02:57:04
 */
public class SolrjQuery {
	private String url;
	private Integer soTimeOut;
	private Integer connectionTimeOut;
	private Integer maxConnectionsPerHost;
	private Integer maxTotalConnections;
	private Integer maxRetries;
	private CommonsHttpSolrServer solrServer = null;
	private final static String ASC = "asc";

	public void init() throws MalformedURLException {
		solrServer = new CommonsHttpSolrServer(url);
		solrServer.setSoTimeout(soTimeOut);
		solrServer.setConnectionTimeout(connectionTimeOut);
		solrServer.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost);
		solrServer.setMaxTotalConnections(maxTotalConnections);
		solrServer.setFollowRedirects(false);
		solrServer.setAllowCompression(true);
		solrServer.setMaxRetries(maxRetries);
	}

	public SolrDocumentList query(Map<String, String> propertyMap,
			Map<String, String> compositorMap, Long startIndex, Long pageSize)
			throws Exception {
		SolrQuery query = new SolrQuery();
		// 设置搜索字段
		if (null == propertyMap) {
			throw new Exception("搜索字段不可为空!");
		} else {
			for (Object o : propertyMap.keySet()) {
				StringBuffer sb = new StringBuffer();
				sb.append(o.toString()).append(":");
				sb.append(propertyMap.get(o));
				String queryString = addBlank2Expression(sb.toString());
				query.setQuery(queryString);
			}
		}
		// 设置排序条件
		if (null != compositorMap) {
			for (Object co : compositorMap.keySet()) {
				if (ASC == compositorMap.get(co)
						|| ASC.equals(compositorMap.get(co))) {
					query.addSortField(co.toString(), SolrQuery.ORDER.asc);
				} else {
					query.addSortField(co.toString(), SolrQuery.ORDER.desc);
				}
			}
		}
		
		if (null != startIndex) {
			query.setStart(Integer.parseInt(String.valueOf(startIndex)));
		}
		if (null != pageSize && 0L != pageSize.longValue()) {
			query.setRows(Integer.parseInt(String.valueOf(pageSize)));
		}
		try {
			QueryResponse qrsp = solrServer.query(query);
			SolrDocumentList docs = qrsp.getResults();
			return docs;
		} catch (Exception e) {
			throw new Exception(e);
		}
	}

	private String addBlank2Expression(String oldExpression) {
		String lastExpression;
		lastExpression = oldExpression.replace("AND", " AND ").replace("NOT",
				" NOT ").replace("OR", " OR ");
		return lastExpression;
	}

	public Integer getMaxRetries() {
		return maxRetries;
	}

	……
      
        public void setMaxTotalConnections(Integer maxTotalConnections) {
		this.maxTotalConnections = maxTotalConnections;
	}
}

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

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


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


 

  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. }  
package org.nstcrm.person.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;

public class SolrHttpServer {
	//private Logger logger = LoggerFactory.getLogger(this.getClass());
	private final static String URL = "http://localhost:8080/solr";
	private final static Integer SOCKE_TTIMEOUT = 1000; // socket read timeout
	private final static Integer CONN_TIMEOUT = 100;
	private final static Integer MAXCONN_DEFAULT = 100;
	private final static Integer MAXCONN_TOTAL = 100;
	private final static Integer MAXRETRIES = 1;
	private static CommonsHttpSolrServer server = null;
	private final static String ASC = "asc";
	
	public void init() throws MalformedURLException {
			server = new CommonsHttpSolrServer( URL );
			//server.setParser(new XMLResponseParser());
			server.setSoTimeout(SOCKE_TTIMEOUT);
			server.setConnectionTimeout(CONN_TIMEOUT);
			server.setDefaultMaxConnectionsPerHost(MAXCONN_DEFAULT);
			server.setMaxTotalConnections(MAXCONN_TOTAL);
			server.setFollowRedirects(false);
			server.setAllowCompression(true);
			server.setMaxRetries(MAXRETRIES);
	}
	
	public static SolrDocumentList query(Map<String, String> property, Map<String, String> compositor, Integer pageSize) throws Exception {
		SolrQuery query = new SolrQuery();
		// 设置搜索字段
		if(null == property) {
			throw new Exception("搜索字段不可为空!");
		} else {
			for(Object obj : property.keySet()) {
				StringBuffer sb = new StringBuffer();
				sb.append(obj.toString()).append(":");
				sb.append(property.get(obj));
				String sql = (sb.toString()).replace("AND", " AND ").replace("OR", " OR ").replace("NOT", " NOT ");
				query.setQuery(sql);
			}
		}
		// 设置结果排序
		if(null != compositor) {
			for(Object obj : compositor.keySet()) {
				if(ASC == compositor.get(obj) || ASC.equals(compositor.get(obj))) {
					query.addSortField(obj.toString(), SolrQuery.ORDER.asc);
				} else {
					query.addSortField(obj.toString(), SolrQuery.ORDER.desc);
				}
			}
		}
		if(null != pageSize && 0 < pageSize) {
			query.setRows(pageSize);
		}
		QueryResponse qr = server.query(query);
		SolrDocumentList docList = qr.getResults();
		return docList;
	}
	
	public static Map<String, String> getQueryProperty(Object obj) throws Exception {
		Map<String, String> result = new TreeMap<String, String>();
		// 获取实体类的所有属性,返回Fields数组
		Field[] fields = obj.getClass().getDeclaredFields();
		for(Field f : fields) {
			String name = f.getName();// 获取属性的名字
			String type = f.getGenericType().toString();
			if("class java.lang.String".equals(type)) {// 如果type是类类型,则前面包含"class ",后面跟类名
				Method me = obj.getClass().getMethod("get" + UpperCaseField(name));
				String tem = (String) me.invoke(obj);
				if(null != tem) {
					result.put(name, tem);
				}
			}
		}
		return result;
	}
	
	public static List<Object> querySolrResult(Object propertyObj, Object compositorObj, Integer pageSize) throws Exception {
		Map<String, String> propertyMap = new TreeMap<String, String>();
		Map<String, String> compositorMap = new TreeMap<String, String>();
		propertyMap = getQueryProperty(propertyObj);
		compositorMap = getQueryProperty(compositorObj);
		SolrDocumentList docList = query(propertyMap, compositorMap, pageSize);
		List<Object> list = new ArrayList<Object>();
		for(Object obj : docList) {
			list.add(obj);
		}
		return list;
	}
	
	private static String UpperCaseField(String name) {
		return name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
	}

	public CommonsHttpSolrServer getServer() {
		return server;
	}

	public void setServer(CommonsHttpSolrServer server) {
		this.server = server;
	}

}


 

  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.   
  679.   
  680.   
  681. 第二步,进行简单的web应用.  
  682.    
分享到:
评论
1 楼 bobbell 2014-12-24  
I have setup a test liferay environment and a Solr search engine. I installed the plugin according to the wiki and Solr is indexing all the content from Wiki, Blogs and forums.

When I do the search on wiki and blogs the results are correct, but when doing a search on the forums I get no results.

Running a sniffer between the Solr server and liferay I see the search query and Solr is returning valid results but for some reason the search function in the forums is not showing any results.

Is anybody else seeing this behavior? Anybody with some pointers on how to solve this or what other information will be useful to solve it or to open a ticket in liferay bug tracking tool?

Thank you very much.

java barcode generator

相关推荐

Global site tag (gtag.js) - Google Analytics