solr newSearcher 跟 firstSearcher的监听器扩展

自定义SolrEventListener实现searcher的autowarm策略


在solrconfig.xml上可以配置在newSearcher和firstSearcher的监听器,在事件触发时,可以做某些热身搜索,让Searcher做好准备提供服务,特别是服务重启的时候,如果没有做好热身,开始提供服务搜索时都很勉强。

但原生的配置比较麻烦,如果要做多个搜索请求时,单纯在配置文件上配置略显得麻烦:


 <listener event="newSearcher" class="solr.QuerySenderListener">
      <arr name="queries">
          <lst><str name="q">美女</str><str name="qt">standard</str><str name="sort">rtsTime desc</str></lst>
           <lst><str name="q">hadoop</str><str name="qt">standard</str><str name="sort">rtsTime desc</str></lst>
           <lst><str name="q">zoie</str><str name="qt">standard</str><str name="sort">rts desc</str></lst>
           <lst><str name="q">lucene</str><str name="qt">standard</str><str name="sort">pubdate desc</str></lst>		
	   <lst><str name="q">new searcher</str><str name="qt">standard</str><str name="sort">sourceId desc</str></lst>		
           <lst><str name="q">solr</str><str name="qt">standard</str><str name="sort">price desc</str></lst>			   
      </arr>
    </listener>



现在扩展写另一个事件监听器,可以指定需要加载的某些字段,在预热后加载字段缓存,用于排序或者函数搜索使用的。

增加每天的热词搜索,每行一个词,比如1000个词。


主要扩展的代码如下:




package org.apache.solr.core;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocList;
import org.apache.solr.search.SolrIndexSearcher;

/**
 * @author yzygenuine
 * 
 */
public class MyQuerySenderListener extends AbstractSolrEventListener {

	/**
	 * 查询词文件路径
	 */
	private final static String QUERYKEY_FILE = "queryKeyFile";

	/**
	 * 需要缓存的字段数组
	 */
	private final static String SORT_FILEDS = "sortFields";
	
	

	public MyQuerySenderListener(SolrCore core) {
		super(core);

	}

	@Override
	public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
		List<String> sortFields = (List<String>) args.get(SORT_FILEDS);
		final SolrIndexSearcher searcher = newSearcher;
		NamedList sortParams = null;
		if (sortFields != null && !sortFields.isEmpty()) {
			sortParams = new NamedList();
			for (int i = 0; i < sortFields.size(); i++) {
				sortParams.add(CommonParams.SORT, sortFields.get(i) + " desc");
			}
		}
		String queryKeyFilePath = (String) args.get(QUERYKEY_FILE);
		String qt=(String)args.get(CommonParams.QT);
		boolean isDone = false;
		if (queryKeyFilePath != null && !queryKeyFilePath.isEmpty()) {
			log.info("###############################queryKeyFilePath:" + queryKeyFilePath);
			File f = new File(queryKeyFilePath);
			if (f.exists() && f.canRead()) {
				try {
					List<String> keys = FileUtils.readLines(f, "utf-8");
					if (keys != null) {
						for (String k : keys) {
							if(k.isEmpty()||k.trim().isEmpty())continue;
							NamedList params = new NamedList();
							if (sortParams != null) {
								params.addAll(sortParams);
							}
							params.add(CommonParams.Q, k);
							if(qt!=null&&!qt.isEmpty()){
								params.add(CommonParams.QT, qt);
							}
							reqLocal(params, searcher, currentSearcher);
						}
						isDone = true;
					}
				} catch (Exception e) {
					log.error("", e);
					isDone = false;
				}
			}
		}
		if (!isDone) {
			try {
				log.info("just req sortFields params");
				reqLocal(sortParams, searcher, currentSearcher);
			} catch (IOException e) {
				log.error("", e);
			}
		}

		log.info("QuerySenderListener sending requests to " + newSearcher);
		for (NamedList nlst : (List<NamedList>) args.get("queries")) {
			try {
				reqLocal(nlst, searcher, currentSearcher);
			} catch (Exception e) {
			}
		}
		log.info("QuerySenderListener done.");

	}

	/**
	 * @param nlst
	 * @param newSearcher
	 * @param currentSearcher
	 * @throws IOException
	 */
	private void reqLocal(NamedList nlst, final SolrIndexSearcher newSearcher, final SolrIndexSearcher currentSearcher)
			throws IOException {
		if (nlst == null) {
			nlst = new NamedList();
		}
		NamedList params = addEventParms(currentSearcher, nlst);

		LocalSolrQueryRequest req = new LocalSolrQueryRequest(core, params) {
			@Override
			public SolrIndexSearcher getSearcher() {
				return newSearcher;
			}
			@Override
			public void close() {
			}
		};

		SolrQueryResponse rsp = new SolrQueryResponse();
		core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);

		NamedList values = rsp.getValues();
		for (int i = 0; i < values.size(); i++) {
			Object o = values.getVal(i);
			if (o instanceof DocList) {
				DocList docs = (DocList) o;
				for (DocIterator iter = docs.iterator(); iter.hasNext();) {
					newSearcher.doc(iter.nextDoc());
				}
			}
		}
		req.close();
	}
}



新的监听器的配置如下:

 <listener event="newSearcher" class="solr.MyQuerySenderListener">
   
    
      <arr name="sortFields">
        <str>title</str>
         <str>id</str>
      </arr>
      <str name="queryKeyFile">/Users/yzygenuine/56workspace/solr_jetty/solr/extConf/query.txt</str>
      
  
      <arr name="queries">
          <lst><str name="q">solr</str><str name="qt">standard</str><str name="sort">price desc</str></lst>
      </arr>

  
    </listener>



firstSearcher也可以同样配置




转贴请声明: 

solr newSearcher 跟 firstSearcher的监听器扩展




你可能感兴趣的:(exception,String,File,null,Solr,扩展)