详解spring中使用solr的代码实现

网友投稿 208 2023-05-12


详解spring中使用solr的代码实现

在介绍solr的使用方法之前,我们需要安装solr的服务端集群。基本上就是安装zookeeper,tomcat,jdk,solr,然后按照需要配置三者的配置文件即可。由于本人并没有具体操作过如何进行solr集群的搭建。所以关于如何搭建solr集群,读者可以去网上查看其它资料,有很多可以借鉴。这里只介绍搭建完solr集群之后,我们客户端是如何访问solr集群的。

之前介绍过,spring封装nosql和sql数据库的使用,都是通过xxxTemplate。solr也不例外。

我们需要引入solr的jar包

org.springframework.data

spring-data-solr

1.0.0.RELEASE

然后引入solr在spring中封装的配置

然后重写我们的SolrServiceImpl就可以了。

但是,本文我们不用spring中封装的xxxTemplate这种格式做讲解。个人在使用spring封装solr的方式的时候遇到了各种各样的问题,可能是能力太low架控不了吧。下面我们主要讲解下如何使用solr的原生api进行访问。

首先:

引入solr的原生代码api的jar包

org.apache.solr

solr-solrj

4.7.2

其次:

在spring的配置文件中配置我们solr的FactoryBean类,此类是作为我们编写自己业务service类的属性来操作solr。

solr.zkHost是我们配置的zookeeper集群

orderInfo是我们存储在solr中的数据结构bean

再次:

编写我们的SolrCloudServerFactoryBean类,其中使用了spring的FactoryBean,和InitializingBean。关于这两者的含义读者可以参考其他资料,基本意思是spring容器在注册该bean之前,需要进行的一些初始化操作。通过afterPropertiesSet方法可以看到我们在使用solr之前做的一些初始化操作。

package com.jd.fms.prism.solr.service;

import org.apache.http.client.HttpClient;

/**

* solrj spring integration

*

* @author bjchenrui

*/

public class SolrCloudServerFactoryBean implements FactoryBean, InitializingBean {

private CloudSolrServer cloudSolrServer;

private String zkHost;

private String defaultCollection;

private int maxConnections = 1000;

private int maxConnectionsPerhttp://Host = 500;

private int zkClientTimeout = 10000;

private int zkConnectTimeout = 10000;

private Lock lock = new ReentrantLock();

public SolrServer getObject() throws Exception {

return cloudSolrServer;

}

public Class getObjectType() {

return SolrServer.class;

}

public boolean isSingleton() {

return true;

}

public void afterPropertiesSet() throws Exception {

ModifiableSolrParams params = new ModifiableSolrParams();

params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, maxConnections);

params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, maxConnectionsPerHost);

HttpClient client = HttpClientUtil.createOfLQabClient(params);

LBHttpSolrServer lbServer = new LBHttpSolrServer(client);

lock.lock();

try {

if(cloudSolrServer == null) {

cloudSolrServer = new CloudSolrServer(zkHost, lbServer);

}

} finally {

lock.unlock();

}

cloudSolrServer.setDefaultCollection(defaultCollection);

cloudSolrServer.setZkClientTimeout(zkClientTimeout);

cloudSolrServer.setZkConnectTimeout(zkConnectTimeout);

}

public void setCloudSolrServer(CloudSolrServer cloudSolrServer) {

this.cloudSolrServer = cloudSolrServer;

}

public void setZkHost(String zkHost) {

this.zkHost = zkHost;

}

public void setDefaultCollection(String defaultCollection) {

this.defaultCollection = defaultCollection;

}

public void setMaxConnections(int maxConnections) {

this.maxConnections = maxConnections;

}

public void setMaxConnectionsPerHost(int maxConnectionsPerHost) {

this.maxConnectionsPerHost = maxConnectionsPerHost;

}

public void setZkClientTimeout(int zkClientTimeout) {

this.zkClientTimeout = zkClientTimeout;

}

public void setZkConnectTimeout(int zkConnectTimeout) {

this.zkConnectTimeout = zkConnectTimeout;

}

}

最后:

现在就可以编写我们的service类了,这里就是我们具体如何操作solr的地方。

package com.jd.fms.prism.solr.service.impl;

import com.jd.fms.prism.common.utils.DateUtil;

@Service("orderInfoSolrService")

public class OrderInfoNativeSolrServiceImpl {

private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.FORMATER11);

private static SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat(DateUtil.FORMATER4);

@Resource(name = "orderInfoSolrServer")

private SolrServer solrServer;

/**

* 创建索引

*

* @param orderInfo

*/

public void creatIndex(OrderInfo orderInfo) throws IOException, SolrServerException {

solrServer.addBean(orderInfo);

solrServer.commit();

}

/**

* 查询条件的生成。支持字段的精确查询,模糊查询,范围查询。

* @param orderIdfilter

* @param queryObj

* @param queryTimeList

* @param sorts

* @return

* @throws Exception

*/

public SolrQuery iniFilter(String orderIdfilter,OrderInfo queryObj,List queryTimeList, Sort... sorts) throws Exception {

SolrQuery sQuery = new SolrQuery();

String queryQ = "validTag:1";

sQuery.setQuery(queryQ);

StringBuilder filter = new StringBuilder();

if(null != orderIdfilter){

filter.append(orderIdfilter);

queryObj.setOrderId(null);

}

//添加过滤条件

Field[] fields = queryObj.getClass().getDeclaredFields();

String fieldName = "";

String fieldValue = "";

for (Field field:fields){

if(field.isAnnotationPresent(org.apache.solr.client.solrj.beans.Field.class)){

field.setAccessible(true);

fieldName = field.getName();

fieldValue = String.valueOf(field.get(queryObj));

if (null != fieldValue && !"null".equals(fieldValue) && !"".equals(fieldValue) && !"0.0".equals(fieldValue)){

//如果是会员类型,则添加模糊查询

if(fieldName.equals("memberId") || fieldName.equals("orderType")){

fieldValue = "*" + fieldValue + "*";

}

filter.append(fieldName + ":" + fieldValue).append(" AND ");

}

}

}

if(queryTimeList!=null && queryTimeList.size() > 0) {

Iterator iterator = queryTimeList.iterator();

while(iterator.hasNext()) {

QueryTime queryTime = iterator.next();

String beginDate = simpleDateFormat.format(queryTime.getBeginTime().getTime());

String endDate = simpleDateFormat.format(queryTime.getEndTime().getTime());

filter.append(queryTime.getFieldName() + ":" + "[" + beginDate + " TO " + endDate + "] AND ");

}

}

if(filter.length()>0){

filter.delete(filter.length()-5, filter.length());

}

sQuery.addFilterQuery(filter.toString());

if(sQuery.toString().equals("")){

sQuery.setQuery("*:*");

}

return sQuery;

}

/**

* 查询代码,可以看到我们可以在solr中做聚合,做排序。而且整个过程都是秒级的。

* @param map

* @param queryObj

* @param queryTimeList

* @param page

* @param sorts

* @return

* @throws Exception

*/

public Page query(Map map,OrderInfo queryObj, List queryTimeList, Pageable page, Sort... sorts) throws Exception {

SolrQuery sQuery = iniFilter(null,queryObj,queryTimeList);

//添加分页

if(page != null){

sQuery.setStart(page.getPageNumber()*page.getPageSize());

sQuery.setRows(page.getPageSize());

}

//添加排序

/*if (null != sorts){

sQuery.setSort("orderId",SolrQuery.ORDER.asc);

}*/

QueryResponse response = null;

sQuery.setGetFieldStatistics("orderPrice");

sQuery.setGetFieldStatistics("duePrice");

sQuery.setGetFieldStatistics("diffPrice");

try {

response = solrServer.query(sQuery);

} catch (SolrServerException e) {

e.printStackTrace();

}

SolrDocumentList list = response.getResults();

Map mapSum = response.getFieldStatsInfo();

String orderPriceSum = null;

if(mapSum.get("orderPrice") != null && !mapSum.get("orderPrice").toString().equals("") ){

orderPriceSum = mapSum.get("orderPrice").getSum().toString();

}

String duePriceSum = null;

if(mapSum.get("duePrice") != null && !mapSum.get("duePrice").toString().equals("") ){

duePriceSum = mapSum.get("duePrice").getSum().toString();

}

String diffPriceSum = null;

if(mapSum.get("diffPrice") != null && !mapSum.get("diffPrice").toString().equals("") ){

diffPriceSum = mapSum.get("diffPrice").getSum().toString();

}

List list1 = new ArrayList();

DocumentObjectBinder binder = new DocumentObjectBinder();

Iterator iterator = list.iterator();

while(iterator.hasNext()){

OrderInfo orderInfo = binder.getBean(OrderInfo.class, (SolrDocument) iterator.next());

list1.add(orderInfo);

}

map.put("orderPriceSum", orderPriceSum);

map.put("duePriceSum", duePriceSum);

map.put("diffPriceSum", diffPriceSum);

Page pageList = new PageImpl(list1,page,list.getNumFound());

return pageList;

}

/**

* 我们可以按照key值进行主键查询。

* @param id

* @return

* @throws Exception

*/

public List queryByOrderId(String id) throws Exception {

SolrQuery sQuery = new SolrQuery();

String filter = "orderId" + ":" + id;

sQuery.setQuery(filter);

QueryResponse response = null;

try {

response = solrServer.query(sQuery);

} catch (SolrServerException e) {

e.printStackTrace();

}

SolrDocumentList list = response.getResults();

List list1 = new ArrayList();

DocumentObjectBinder binder = new DocumentObjectBinder();

Iterator iterator = list.iterator();

while(iterator.hasNext()){

OrderInfo orderInfo = binder.getBean(OrderInfo.class, (SolrDocument) iterator.next());

list1.add(orderInfo);

}

return list1;

}

public void deleteAll(OrderInfo orderInfo) throws IOException, SolrServerException {

String sQuery = "*:*";

solrServer.deleteByQuery(sQuery);

}

public void deleteById(String id) {

}

public void createIndexBatch(List orderInfoList) throws IOException, SolrServerException {

solrServer.addBeans(orderInfoList);

solrServer.commit();

}

public void deleteBySolrQuery(String solrQuery) throws IOException, SolrServerException {

solrServer.deleteByQuery(solrQuery);

solrServer.commit();

}

public SolrServer getSolrServer() {

return solrServer;

}

public void setSolrServer(SolrServer solrServer) {

this.solrServer = solrServer;

}

}

当然solr的api不止于此,我们此处只是罗列了一些比较常用的使用方法。对于solr的查询,有以下几点需要注意。

1.    solr生成查询语句的时候,是有q查询和fq查询之分的。哪些查询条件放在q查询里,哪些查询条件放在fq查询里,对查询的效率还是有较大的影响的。一般固定不变的查询条件放在q查询里,经常变化的查询条件放在fq里。上述代码中validTag:1就放在了q查询里,循环里的字符串filter则放在了我们的fq查询里。

2.    solr查询时,要了解solr服务器集群的配置文件中使用的是什么样的分词器,不同分词器对模糊查询的结果是有影响的。比如常见的IK分词器和标准分词器(如果我们有一个字段的名称为:我是中国人,ik分词器在solr里的存储就成为了“我”,“中国人”,“中国”,“国人”。而标准分词器则会存储为“我”,“是”,“中”,“国”,“人”。如果我们使用全称查询,即查询:我是中国人,两者是没有问题的。但是使用模糊查询,比如查询“*我是*”,则两个分词器分词都查不出来结果,而如果我们的查询条件是“*中国人*”则在ik分词器下可以查询出结果,在标准分词器下查不出结果。)

3.    使用solr的过程中,需要定时执行solr的optimize函数来清理磁盘碎片,否则会影响读写效率。对于optimize的参数建议为(false,false,5)。

4.    写solr数据的时候,尽量使用createIndexBatch方法,这是因为solr在执行写入的时候,写入一条数据和写入多条数据都需要全量建索引,其执行时间是差不多的。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java生产者和消费者例子_动力节点Java学院整理
下一篇:详解Vue使用命令行搭建单页面应用
相关文章

 发表评论

暂时没有评论,来抢沙发吧~