最近正在研究solr,solr分为服务性的搜索还嵌入式的搜索(不需要启动solr服务,直接和自己的程序整合在一块)。对于添加solr服务的搜索apache的官方说的很清楚,现在只是介绍下嵌入式的搜索。
1.配置下serverhome 在src下面。建立一个search.properties(可以自己命名)
serarchServerHome=E:\\Project\\centersitesolr\\WebRoot\\solr\\multicore\\ (此路径为存放索引的路径,book,core0,core1为不同的索引服务)
2.在给定的serverhome下 建立一个search.xml(名字可以自己命名,指定solr服务)
<?xml version='1.0' encoding='UTF-8'?> <solr persistent='true'>
<cores adminPath='/admin/cores'>
<core name='core1' instanceDir='core1/'/>
<core name='core0' instanceDir='core0/'/>
<core name='book' instanceDir='book/'/>
</cores>
</solr>
3.
先定义一个SearchServerException
package com.sendian.search.solr
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrServerException;
public class SearchServerException extends RuntimeException {
Logger logger = Logger.getLogger(SearchServerException.class);
public SearchServerException(String message) {
super(message);
logger.warn(message);
}
private static final long serialVersionUID = -6150092853751278477L;
}
4.定义一个factory
package com.sendian.search.solr;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrServer;
import com.sendian.search.solr.server.EmbeddedServerContainer;
public class SearchServerFactory {
private static Logger logger = Logger.getLogger(SearchServerFactory.class);
private static Map<String,SolrServer> searchServerMap = Collections.synchronizedMap(new HashMap<String,SolrServer>());
private EmbeddedServerContainer embeddedServerContainer;
public SolrServer getSearchServer(String searchName){
SolrServer solrServer = null;
if(!searchServerMap.containsKey(searchName)){
solrServer = embeddedServerContainer.getSolrCore(searchName);
if(solrServer!=null)
searchServerMap.put(searchName, solrServer);
}
logger.info("搜索服务:" + searchName);
return searchServerMap.get(searchName);
}
public EmbeddedServerContainer getEmbeddedServerContainer() {
return embeddedServerContainer;
}
public void setEmbeddedServerContainer(
EmbeddedServerContainer embeddedServerContainer) {
this.embeddedServerContainer = embeddedServerContainer;
}
}
5.定一个
EmbeddedServerContainer
package com.sendian.search.solr.server;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.CoreDescriptor;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrResourceLoader;
import org.xml.sax.SAXException;
import com.sendian.search.solr.SearchServerException;
public class EmbeddedServerContainer{
Logger logger = Logger.getLogger(EmbeddedServerContainer.class);
private static CoreContainer container;
private String searchServerHome;
public EmbeddedServerContainer( String searchServerHome ) throws ParserConfigurationException, IOException, SAXException{
setSearchServerHome(searchServerHome);
File f = new File( getSearchServerHome(), "search.xml" );
container = new Initializer().initialize();
container.load(getSearchServerHome(), f);
container.setPersistent(true);
logger.info("启动搜索server完成!");
}
public void shutdown(){
if(container==null)
throw new SearchServerException("不能关闭搜索server,server容器为空!!!");
if(container.isPersistent())
container.persist();
container.shutdown();
logger.info("搜索server关闭!");
}
public synchronized void persite(){
if(container==null)
throw new SearchServerException("持久化错误,Server容器不能为空!!!");
container.persist();
logger.info("搜索server持久化完成!");
}
public synchronized void addCore(String solrName,String instanceDir,boolean isPersist) throws ParserConfigurationException, IOException, SAXException{
CoreDescriptor p = new CoreDescriptor(container, solrName, instanceDir);
SolrCore core = container.create(p);
container.register(solrName, core, false);
if(isPersist)
container.persist();
}
public SolrServer getSolrCore(String solrName){
if(container.getCoreNames().contains(solrName))
return new EmbeddedSolrServer(container,solrName);
return null;
}
static class Initializer extends CoreContainer.Initializer {
public Initializer(){}
@Override
public CoreContainer initialize() {
return new CoreContainer(new SolrResourceLoader(SolrResourceLoader.locateInstanceDir()));
}
}
public CoreContainer getContainer() {
return container;
}
public String getSearchServerHome() {
return searchServerHome;
}
public void setSearchServerHome(String searchServerHome) {
this.searchServerHome = searchServerHome;
}
}
6.在需要的时候可以通过spring配置下。然后在SolrServer bookserver = searchServerFactory.getSearchServer("book");得到相应的server
SearchService.java
package com.sendian.subsite.service;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Date;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import com.sendian.search.solr.SearchServerFactory;
import com.sendian.subsite.entity.FacetBean;
import com.sendian.subsite.entity.DocBean;
import com.sendian.subsite.solr.SolrService;
import com.sendian.subsite.utils.Search;
import com.sendian.subsite.utils.SearchPage;
import com.sendian.utils.DateUtil;
import java.text.SimpleDateFormat;
public class SearchService {
private static Logger logger = Logger.getLogger(SearchService.class);
private static final String FACETFIELDBOOKCLASS = "csmCode";
//SolrServer bookserver = SolrServerFactory.getSolrServerInstance();
private SearchServerFactory searchServerFactory;
// SolrServer solrServer = new SolrService().getSolrAdmin();
public SearchPage getCSE(SolrQuery q, String ccode, int start,
int pageSize, boolean isFacet, Locale l) throws SolrServerException, ParseException {
SolrServer bookserver = searchServerFactory.getSearchServer("book");
SearchPage result = null;
q.setStart(start);
q.setRows(pageSize);
QueryRequest r = new QueryRequest(q);
r.setMethod(METHOD.POST);
logger.debug("查询字符:" + q.getQuery());
// System.out.println();
QueryResponse response = r.process(bookserver);
// QueryResponse response = r.process(solrServer);
List<DocBean> docs = getDocuments(response, l);
Map m = new HashMap();
m.put("docs", docs);
// m.put("facetQuery", getFacetQueryMap(response));
if (isFacet) {
List<FacetBean> bookTypes = getFacetCounts(getFacetMap(response,
FACETFIELDBOOKCLASS), ccode);
m.put("clc", bookTypes);
}
return result = new SearchPage(q.getQuery(), response.getQTime(),
response.getResults().getStart(), response.getResults()
.getNumFound(), pageSize, m);
}
public List<DocBean> getDocuments(QueryResponse response, Locale locale) throws ParseException{
SolrDocumentList l = response.getResults();
List<DocBean> docbeans = new ArrayList<DocBean>();
SolrDocument doc = null;
DocBean docbean = null;
// SimpleDateFormat aFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
if (l != null && l.size() > 0) {
Iterator<SolrDocument> iter = l.iterator();
while (iter.hasNext()) {
doc = iter.next();
docbean = new DocBean();
docbean.setAutherName(doc.getFieldValue("autherName") !=null?doc.getFieldValue("autherName").toString():"");
docbean.setBookId(doc.getFieldValue("bookId") !=null?doc.getFieldValue("bookId").toString():"");
docbean.setBookBrief(doc.getFieldValue("bookBrief") !=null?doc.getFieldValue("bookBrief").toString():"");
docbean.setPubDate(doc.getFieldValue("pubDate") !=null?((String)(doc.getFieldValue("pubDate"))):null);
docbean.setCsmCode(doc.getFieldValue("csmCode") !=null?doc.getFieldValue("csmCode").toString():"");
docbean.setPublishName(doc.getFieldValue("publishName") !=null?doc.getFieldValue("publishName").toString():"");
docbean.setBookCover(doc.getFieldValue("bookCover") !=null?doc.getFieldValue("bookCover").toString():"");
docbean.setClcCode(doc.getFieldValue("clcCode") !=null?doc.getFieldValue("clcCode").toString():"");
docbean.setUpperName(doc.getFieldValue("upperName") !=null?doc.getFieldValue("upperName").toString():"");
docbean.setAuthers(doc.getFieldValue("authors") !=null?doc.getFieldValue("authors").toString():"");
docbean.setBookStatus(doc.getFieldValue("bookStatus") !=null?doc.getFieldValue("bookStatus").toString():"");
docbean.setBookName(doc.getFieldValue("bookName") !=null?doc.getFieldValue("bookName").toString():"");
docbean.setBookPrice(doc.getFieldValue("bookPrice") !=null?doc.getFieldValue("bookPrice").toString():"");
docbean.setIsbn(doc.getFieldValue("isbn") !=null?doc.getFieldValue("isbn").toString():"");
docbeans.add(docbean);
}
}
return docbeans;
}
public DocBean findDocById(String docId, Locale locale)
throws SolrServerException, ParseException {
SolrServer bookserver = searchServerFactory.getSearchServer("book");
DocBean docbean = null;
SolrQuery q = new SolrQuery();
QueryRequest r = new QueryRequest(q);
q.setQuery("bookId:\"" + docId + '"');
r.setMethod(METHOD.POST);
QueryResponse response = r.process(bookserver);
List<DocBean> l = this.getDocuments(response, locale);
if (l.size() > 0)
return l.get(0);
return docbean;
}
public Map<String, Long> getFacetMap(QueryResponse response, String facet) {
Map<String, Long> map = new HashMap<String, Long>();
if (response.getFacetField(facet) == null)
return map;
List<Count> l = response.getFacetField(facet).getValues();
if (l != null && l.size() > 0) {
Iterator<Count> iter = l.iterator();
while (iter.hasNext()) {
Count c = iter.next();
map.put(c.getName(), c.getCount());
}
}
return map;
}
public List<FacetBean> getFacetCounts(Map<String, Long> map, String ccode) {
// Search search = new Search();
FacetBean facet = null;
List<FacetBean> l = new ArrayList<FacetBean>();
// Map<String,Integer> resultsmap = new HashMap<String,Integer>();
int length = 0;
if (ccode == null || ccode.length() < 3) {
length = 3;
} else {
length = ccode.length() + 3;
// resultsmap.put("current",map.get(ccode));
}
Set<CcodeObject> set = new HashSet<CcodeObject>();
getSubFacetSet(set, map, length);
Iterator<CcodeObject> iterSet = set.iterator();
while (iterSet.hasNext()) {
String keyccode = iterSet.next().getCcode();
// System.out.println("+"+keyccode);
facet = new FacetBean();
facet.setName(Search.getAttribute(keyccode).toString());
facet.setCount(sunCounts(map, keyccode));
facet.setId(keyccode);
l.add(facet);
/*
* if(l.size()>9) break;
*/
// resultsmap.put(keyccode,sunCounts(map,keyccode));
}
if (l.size() < 1 && (ccode != null && ccode.trim().length() > 0)) {
facet = new FacetBean();
facet.setName(Search.getAttribute(ccode).toString());
facet.setCount(sunCounts(map, ccode));
facet.setId(ccode);
l.add(facet);
}
Collections.sort(l);
return l;
}
private Map<String, Integer> getFacetQueryMap(QueryResponse response) {
Map<String, Integer> map = new HashMap<String, Integer>();
map = response.getFacetQuery();
return map;
}
private Long sunCounts(Map<String, Long> map, String ccode) {
int i = 0;
Iterator<Map.Entry<String, Long>> itermap = map.entrySet().iterator();
while (itermap.hasNext()) {
Map.Entry<String, Long> me = itermap.next();
String key = me.getKey();
Long value = me.getValue();
if (key.startsWith(ccode))
i = i + value.intValue();
}
return new Long(i);
}
public void getSubFacetSet(Set<CcodeObject> set, Map<String, Long> map,
int i) {
Iterator<String> keySet = map.keySet().iterator();
while (keySet.hasNext()) {
String key = keySet.next();
if (key.length() >= i) {
CcodeObject c = new CcodeObject();
c.setCcode(key.substring(0, i));
set.add(c);
}
}
}
class CcodeObject {
private String ccode;
@Override
public boolean equals(Object o) {
if (o == null)
return false;
CcodeObject os = (CcodeObject) o;
if (this.ccode.equals(os))
return true;
if (os.getCcode().startsWith(this.ccode))
return true;
if (this.ccode.length() > os.getCcode().length()
&& this.ccode.startsWith(os.getCcode())) {
this.ccode = os.getCcode();
return true;
} else {
return false;
}
}
@Override
public int hashCode() {
// TODO 自动生成方法存根
return BigDecimal.ROUND_CEILING;
}
public String getCcode() {
return this.ccode;
}
public void setCcode(String ccode) {
this.ccode = ccode;
}
}
/* public static Date dateFormat(Date d){
Date d =new Date(date);
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
return sd.format(d);
}*/
public SearchServerFactory getSearchServerFactory() {
return searchServerFactory;
}
public void setSearchServerFactory(SearchServerFactory searchServerFactory) {
this.searchServerFactory = searchServerFactory;
}
}