SolrJ是Solr的客户端,简化开发量
这里需要jar包有:
solr-core-5.3.1.jar
solr-solrj-5.3.1.jar
SolrJ使用步骤
1 建立与Solr服务的连接
HttpSolrClient server = new HttpSolrClient("http://localhost:8080/solr/ims_advertiser_core");
- 1
2 配置参数
server.setSoTimeout(3000); // socket read timeout
server.setConnectionTimeout(1000);
server.setDefaultMaxConnectionsPerHost(1000);
server.setMaxTotalConnections(10);
server.setFollowRedirects(false); // defaults to false
server.setAllowCompression(true); // 允许压缩,减少数据量
server.setMaxRetries(1);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
3 填充搜索条件(以SolrQuery对象 )
下面填充相当于拼接的http请求:
http://localhost:8989/solr/select?q=tags:t5 AND t7&fl=auction_id&start=0&rows=4&sort=auction_id desc,auction_point asc 这个链接。
SolrQuery query = new SolrQuery();
query.setQuery("tags:t5 AND t7");
query.addField("auction_id");
query.setStart(0);
query.setRows(4);
query.addSortField("auction_id", SolrQuery.ORDER.desc);
query.addSortField("auction_point", SolrQuery.ORDER.asc);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
通过query对象填充搜索条件时,还可以键值对的形式填充,如:
query.set("start", 0); //从第条数据开始
query.set("rows",4); //共返回多少条数据
query.set("sort", "auction_idasc"); //按id升序排列。desc降序
- 1
- 2
- 3
后面我会在示例代码中写出另一种以Map方式填充搜索条件的方式,当然结果集的获取也会不一样。
4 结果集获取
QueryResponse response = server.query(query);
SolrDocumentList results = response.getResults();
- 1
- 2
- 3
QueryResponse这个对象,是对Response的一次封装。而response.getResults()获得的对象正是SolrJ帮我们做的最关键的操作。最终我们获得的对象SolrDocumentList,非常类似我们在jdbc里的ResultSet,得到结果后,只需一个遍历就行:
for(SolrDocument doc:results){
//....
}
- 1
- 2
- 3
SolrJ与拼接链接方式的区别
1 请求方面
不用SolrJ :
如果采用http直接访问的方法,我们必然会用到httpclient请求Solr服务器。其中所有的搜索条件都必须通过拼接一个负责冗长的url,例如:q=tags:t5 AND t7&fl=auction_id&start=0&rows=4&sort=auction_id desc&…&…&… ,通过GET的方式,请求服务器。
用SolrJ :
面对对象的思想,所有搜索条件均以setter属性的方式设置到其封装的对象当中。但是,实际上还是通过拼接url的方式,走http请求的方式再请求Solr服务器。
所以,有了Solrj,开发会省很多事,将很多开发中的体力活交给Solrj。但是直接拼接url的方式肯定比对象的方式灵活很多。因为不复杂,有兴趣的同学,可以给Solrj加个方法,直接在Solrj最终生成的url上加上任何字符串。
2 获取结果方面
不用SolrJ:
结果的返回形式是xml文件,每条记录都会以document节点的形式记录。如果要获得Object对象,我们一般会用Dom4j或者xStream等技术对结果的xml进行解析。
用SolrJ:
直接获得结果,无需解析xml。优点显而易见!
示例代码
当以Map方式 (这里的Map对象是paramMaps) 填充搜索条件时,需要用SolrParams 对象来获取QueryResponse
SolrParams params = new MapSolrParams(paramMaps);
QueryResponse resp = server.query(params);
- 1
- 2
完整示例:
/**
* SolrJ的增删改查
* @author 张春玲
* SolrJ是访问Solr 的Java客户端框架。使用SolrJ的前提是在tomcat里配置好了solr,并且将数据库数据导入到了solr_home里的core里
* 需将noggit-0.5.jar包 加入工程,防止下面的异常:
* Exception in thread "main" java.lang.NoClassDefFoundError: org/noggit/CharArr
*/
public class SolrJUtil {
/**
* Solr服务器路径
* http://localhost:8080/solr这部分直接在浏览器访问时,会出现solr管理界面
* ims_advertiser_core是solr_home里的core
*/
public static final String SOLR_URL="http://localhost:8080/solr/ims_advertiser_core";
/**
* Solr服务器客户端,因此说SolrJ是访问Solr 的Java客户端框架。来源solr-solrj-5.3.1.jar。HttpSolrServer过时了
*/
private HttpSolrClient server;
/**
* 构造方法
*/
public SolrJUtil(){
server = new HttpSolrClient(SOLR_URL);//根据solr路径连接solr服务器
server.setAllowCompression(true);//允许压缩,减少数据量
}
/**
* 查询:返回SolrJ查询Solr服务器的数据。 《已测试》----------------------------------------
* SolrJ的查询与在solr管理界面的查询是一样的,只是管理界面将所有字段做成了表格的形式,我们只需填值就行了,
* 而SolrJ不仅需要填值,还需要填对应的字段。SolrJ能查询的前提solr服务器已经将数据库的数据导入了。
* 一般开发都只用查询功能的,索引的更新基本上都是使用 crond。
*
* 高亮的前提是,core里schema.xml文件配置高亮字段时,需将该field的type属性改为分词器,如中文分词type="text_ik",且stored="true"。
*
* @param keyword 它是搜索时的关键字
* @return
*/
public List<String> search(String keyword){
List<String> autoList=new ArrayList<String>();
if (keyword== null || keyword.trim().length()==0) {
return autoList;
}
SolrQuery query = new SolrQuery();
QueryResponse response = null;
try {
//query.set("q","*:*"); //q表示查询关键词,*:*代表查询所有属性、所有值,即所有索引(index)
query.set("q", "keyword:"+keyword); //表示查询关键字里包含keyword的所有结果,这儿keyword为“东”
query.set("start", 0); //从第条数据开始
query.set("rows",5); //共返回多少条数据
query.set("sort", "advertiserId asc"); //按id升序排列。desc降序
query.set("spellcheck.build", "true"); //拼音检查
/* 设置高亮。
* 高亮的前提是,在core里schema.xml文件配置高亮字段时,需将该field的type属性改为分词器,如中文分词type="text_ik",且stored="true"。
*/
query.set("hl", "true"); // 开启高亮组件
query.set("spellcheck.build", "true"); //拼音检查
query.set("hl.fl","shortName,companyName"); // 高亮字段
query.set("hl.simple.pre","<font color='red'>");//高亮样式标签(开始标签):颜色
query.set("hl.simple.post", "</font>"); //高亮样式标签(结束标签)
response = server.query(query); //放进solr服务器,连接后返回相应数据
/* results是查回的多个javabean对象拼成的json串,格式如下:
* {numFound=35,start=0,docs=[
* SolrDocument{advertiserType=52, id=300, userName=135@qq.com, shortName=东方, disabled=2, advertiserId=82, _version_=1527113164097847296},
* SolrDocument{advertiserType=51, id=302, userName=1351@qq.com, shortName=东看, disabled=2, advertiserId=83, _version_=1527113164095750144},
* SolrDocument{advertiserType=51, id=306, userName=135@qq.com, shortName=东要, disabled=2, advertiserId=85, _version_=1527113164105187328},
* SolrDocument{advertiserType=51, id=308, userName=135@qq.com, shortName=工工, disabled=2, advertiserId=86, _version_=1527113164106235904},
* SolrDocument{advertiserType=52, id=310, userName=135@qq.com, shortName=东方不, disabled=2, advertiserId=87, _version_=1527113164107284480}
* ]}
*
*/
SolrDocumentList results = response.getResults();
System.out.println("查回的多个结果对象:"+results);
/* 高亮结果格式如下:
* {82={}, 83={shortName=[<font color='red'>东</font>看]}, 86={}, 87={}, 85={shortName=[<font color='red'>东</font>要]}}
* 可以看到,高亮结果是以advertiserId为键,以字段对应的结果为值的键值对,所以要想取到具体某个高亮结果,还需从results里先得到advertiserId,然后通过该ID去高亮结果取值。
* 高亮结果之所以能高亮,是因为在查回的结果里将关键字用样式包围了,如shortName=[<font color='red'>东</font>看]},这个样式能直接返回到页面。
*/
Map<String, Map<String, List<String>>> highLightResultMap = response.getHighlighting();
System.out.println("高亮结果:"+highLightResultMap);
for(SolrDocument doc:results){
//doc格式:SolrDocument{advertiserType=51, id=302, userName=1351@qq.com, shortName=东看, disabled=2, advertiserId=83, _version_=1527113164095750144}
if(highLightResultMap!=null){
Object advertiserId = doc.getFieldValue("advertiserId");//得到ID
Map<String, List<String>> map = highLightResultMap.get(advertiserId.toString());//通过ID去取结果
System.out.println("map:"+map);
if(map!=null){
//map格式:{shortName=[<font color='red'>东</font>要]}
List<String> list = map.get("shortName");
//list格式: [<font color='red'>东</font>看]
//System.out.println(list);
//获取高亮的单个结果,是先从单个查回结果里取到advertiserId的值,然后通过该值去高亮结果里取值
//List<String> highLightSnippets = highLightResultMap.get(doc.getFieldValue("advertiserId")).get("shortName");
if(list!=null&&list.size()>0){
for(int i =0 ; i < list.size() ;i++){
String temp = list.get(i);
// System.out.println("title高亮返回为: " + temp);
autoList.add(temp);
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return autoList;
}
/**
* 查询:SolrJ查询Solr服务器数据 [map封装参数方式] -----------------------------------
*
*/
public List<UserAdvertiser> search(String keyword, short advertiserType, short disabled, int pageNo, int pageSize)
throws Exception {
Map<String, String> maps = new HashMap<String, String>();
if(StringUtils.isEmpty(keyword)){
maps.put("q", "*:*");
}else{
maps.put("q", "keyword:" + keyword);
}
String qurey="";
if(advertiserType>0){
qurey="advertiserType:" + advertiserType;
if(disabled>0){
qurey=qurey + " AND disabled:" + disabled;
}
}else{
if(disabled>0){
qurey="disabled:" + disabled;
}
}
maps.put("fq",qurey);
maps.put("start", String.valueOf(pageNo));
maps.put("rows", String.valueOf(pageSize));
maps.put("sort", "advertiserId desc");//走索引时 按id排序
//设置高亮
maps.put("hl","true");
maps.put("hl.fl", "shortName");
maps.put("hl.simple.pre","<font color='red'>");
maps.put("hl.simple.post", "</font>");
SolrParams params = new MapSolrParams(maps);
QueryResponse resp = server.query(params);//添加进服务器
SolrDocumentList docsList=resp.getResults(); //得到匹配结果
Map<String, Map<String, List<String>>> highlighting = resp.getHighlighting();//得到高亮结果
if (docsList == null || docsList.size() == 0) {
return null;
}
List<UserAdvertiser> advList = new ArrayList<UserAdvertiser>();
UserAdvertiser vo = null;
for (SolrDocument doc : docsList) {
int advertiserId=Integer.parseInt(String.valueOf(doc.get("advertiserId")));
vo = new UserAdvertiser();
vo.setId(Integer.parseInt(String.valueOf(doc.get("id"))));
vo.setAdvertiserId(advertiserId);
vo.setAdvertiserType(Short.parseShort(String.valueOf(doc.get("advertiserType"))));
vo.setDisabled(Short.parseShort(String.valueOf(doc.get("disabled"))));
/*vo.setShortName(String.valueOf(doc.get("shortName")));//shortName字段要替换成高亮结果*/
vo.setUserName(String.valueOf(doc.get("userName")));
/*ListStat listStat=listStatDao.getCampaignCount(advertiserId);
if(listStat!=null){
vo.setCampaignNum(listStat.getCount());
}*/
Map<String, List<String>> map = highlighting.get(doc.get("advertiserId").toString());//得到ID
List<String> list_l = map.get("shortName");//通过ID去查回高亮结果
if(list_l!=null && list_l.get(0)!=null){
vo.setShortName(list_l.get(0));
}else{
//如果高亮结果为空,则用前面查回的匹配结果。
vo.setShortName(String.valueOf(doc.get("shortName")));
}
if(String.valueOf(doc.get("shortName")).trim().indexOf("[")!=-1
&&String.valueOf(doc.get("shortName")).trim().indexOf("]")!=-1) {//去中括号
String shortName = String.valueOf(doc.get("shortName")).trim();
vo.setShortName(shortName.substring(1,shortName.length()-1));
}
advList.add(vo);//将对象添加进list结果
}
return advList;
}
/**
* 添加
* @param advertiser
*/
public void add(UserAdvertiser advertiser){
SolrInputDocument doc = new SolrInputDocument();
doc.addField("advertiserId", advertiser.getAdvertiserId());
doc.addField("shortName", advertiser.getShortName());
try {
server.add(doc);
server.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 更新
*/
public void update(UserAdvertiser advertiser){
add(advertiser);//添加就是更新
}
/**
* 删除
*/
public void delete(){
try {
server.deleteByQuery("*:*");//删除所有
server.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}