Java 操作Solr搭建高性能搜索引擎

       目前比较适合Java的搜索引擎搭建一般会选用Solr,底层操作会使用Solrj交互,其实Solr也是基于Lucene。实施过程中发现网上很多关于Java集成Solr的文档都是基于Solr5+版本的,而对于Solr7+版本的文档很少,并且很多都是坑,所以花了不少时间把自己再部署过程中的经验分享出来。

      首先去官网 Apache Solr官网  下载Solr的7.1,然后上传至服务器,在bin目录下面有个执行文件,通过命令/bin/solr start -force 可以很方便的启动Solr7。

  接下去开始Solr的相关配置:

      1.在solr中新建一个项目,在bin目录下使用solr create -C '库名'

      2.编辑managed-schema配置文件,加入IK分词器,这个分词器对中文支持较好

   
    
    
   
     3.配置managed-schema加入字段的通配设置,

       使用这种通配方式配置后,你的程序代码Model中的属性字段可以写成XXX_ikBookStr等即可被Solr识别添加至索引,在查询时也能够使用此字段。
     4.将第一步创建的SolrCore copy到Solr根目录下面,此时访问你的Solr网站即可看到你的SolrCore

       

    5.至此Solr服务端已经搭建完成了,接下去要在程序里面进行编码,首先在pom.xml中引入Solr包支持

    6.然后再model的属性字段set方法上面加上@Field注解,这个注解是用来告诉Solr此字段需要被添加至索引中,但是值得注意的是此字段命名必须符合上面的通配设置规范

  7.接下去就是SpringBoot对于Solr的封装操作了,我是再次做了一次封装便捷实用,贴出我的代码

public class SolrRepository {
	@Autowired
	private SolrClient client;
	private QueryResponse response;
	private SolrDocumentList results;

	/**
	 * 
	 * 
	   TODO - 针对Solr进行数据查询
	   @param query 查询关键字
	   @param offset 起始位置
	   @param limit 每次查询条数
	   @param c 实体类对象
	   @param bool 是否关闭Solr链接
	   @param qf 搜索关键字匹配某些字段的打分比其他的字段要高
	   @param pf 对于某些字段,搜索字符串的密集度(phrase)的打分中占的比重
	   @param fl 指定需要返回的字段 逗号分隔
	   @param fq 指定过滤条件
	   @return
	   @throws Exception
	   2017年10月3日
	   mazkc
	 */
	public List getSolrData(String query,String offset,String limit,String c,Boolean bool,String qf,String pf,String solrFl,String fq) throws Exception {
		ModifiableSolrParams params = new ModifiableSolrParams();
		List beans = null;
		//如果limit为空 或者 超过限定抓取数量 那么返回null
		if(null == limit || "".equals(limit) || Integer.parseInt(limit) > FinalArgs.SERACH_LIMIT){
			return null;
		}
		params.set("q", query);
		params.set("wt", "json");
		params.set("start", "0");
		params.set("rows", "10");
		params = checkNotNull(params,offset,limit,qf,pf,solrFl,fq);
		response = client.query(params);
		if(null == c || "".equals(c)){
			beans = response.getResults();
		}else{
			beans = response.getBeans(Class.forName(c));
			if(null == beans || beans.size() == 0){
				beans = new ArrayList<>();
				beans.add(Class.forName(c).newInstance());
			}
		}
		commitAndCloseSolr(client,bool);
		return beans;
	}
	
	/**
	 * 
	 * 
	   TODO - 验证Solr查询是否有优化
	   @param params 参数关键字
	   @param offset 起始位置
	   @param limit 请求数据条数
	   @param qf 匹配权重
	   @param pf 出现字数权重
	   @param solrFl 需要返回的字段
	   @param fq 过滤哪些数据
	   @return
	   2017年10月17日
	   mazkc
	 */
	private ModifiableSolrParams checkNotNull(ModifiableSolrParams params,String offset,String limit,String qf,String pf,String solrFl,String fq){
		if(null != offset && !"".equals(offset)){
			params.set("start", offset);
		}
		if(null != limit && !"".equals(limit)){
			if(Integer.parseInt(limit) >= 200){
				limit = "200";
			}
			params.set("rows", limit);
		}
		if(null != qf && !"".equals(qf)){
			params.set("qf", qf);
		}
		if(null != pf && !"".equals(pf)){
			params.set("pf", pf);
		}
		if(null != solrFl && !"".equals(solrFl)){
			params.set("fl", solrFl);
		}
		if(null != fq && !"".equals(fq)){
			params.set("fq", fq);
		}
		params.set("defType", "edismax");
		return params;
	}
	
	/**
	 * 
	 * 
	   TODO - 针对集合数据对Solr进行数据索引
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public void saveSolrDataList(List li,Boolean bool) throws Exception {
		if(null != li && li.size() > 0){
			client.addBeans(li);
			commitAndCloseSolr(client,bool);
		}
	}
	
	/**
	 * 
	 * 
	   TODO - 根据索引ID查询solr数据
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public SolrDocument getSolrDataById(String id,Boolean bool) throws Exception {
		SolrDocument so = client.getById(id);
		commitAndCloseSolr(client,bool);
		return so;
	}
	
	/**
	 * 
	 * 
	   TODO - 针对单个数据对Solr进行数据索引
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public void saveSolrData(Object bean,Boolean bool) throws Exception {
		if(null != bean){
			client.addBean(bean);
			commitAndCloseSolr(client,bool);
		}
	}
	
	/**
	 * 
	 * 
	   TODO - 根据集合删除所有索引文档
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public void delSolrDataList(List li,Boolean bool) throws Exception {
		if(null != li && li.size() > 0){
			client.deleteById(li);
			commitAndCloseSolr(client,bool);
		}
	}
	
	/**
	 * 
	 * 
	   TODO - 批量删除所有索引文档
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public void delSolrDataAll(String query,Boolean bool) throws Exception {
		client.deleteByQuery(query);
		commitAndCloseSolr(client,bool);
	}
	
	/**
	 * 
	 * 
	   TODO - 根据ID删除所有索引文档
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public void delSolrDataId(String id,Boolean bool) throws Exception {
		client.deleteById(id);
		commitAndCloseSolr(client,bool);
	}
	
	/**
	 * 
	 * 
	   TODO - 根据索引ID更新索引数据
	   @param map
	   @throws Exception
	   2017年10月2日
	   mazkc
	 */
	public void updateSolrData(String queryId,HashMap map,Boolean bool) throws Exception {
		SolrInputDocument doc = new SolrInputDocument(); 
		SolrDocument sd = getSolrDataById(queryId, false);
		Iterator it = sd.keySet().iterator();
		String key = "";
		//获取所有源数据信息
		while(it.hasNext()){
			key = it.next();
			doc.addField(key, sd.getFieldValue(key));
		}
		Iterator itt = map.keySet().iterator();
		//将需要更新的数据补充进源数据
		while(itt.hasNext()){
			key = itt.next();
			doc.remove(key);
			doc.addField(key, map.get(key));
		}
		client.add(doc);
		commitAndCloseSolr(client,bool);
	}
	
	private SolrInputDocument checkDoc(HashMap map,SolrInputDocument doc){
		if(null != map && null != doc){
			String key = "";
			Iterator it = map.keySet().iterator();
			while(it.hasNext()){
				key = it.next();
				doc.addField(key, map.get(key));
			}
		}
		return doc;
	}
	
	/**
     * 提交以及关闭服务
     * 
     * @param solrClient
     * @throws Exception
     */
    public void commitAndCloseSolr(SolrClient client,Boolean bool)
            throws Exception {
    	if(null != client){
    		client.commit();
//    		if(bool){
//    			client.close();
//    		}
    	}
    }
}
 
  

你可能感兴趣的:(应用服务器技术,文档类,Solr,搜索引擎)