搜索引擎solr系列---与java的springboot项目连接配置

java与solr连接,调用查询的方式,我知道的有两种:

  solrj方式:这种方式写法较麻烦,倒不是因为难,就是简单的逻辑,有时候为了一个业务写一堆代码,所以solrj的这种方式还是比较灵活的,能实现你需要的变态业务需求。我发现它的一个小缺点,就是相对于solr-jpa那种方式,它的速度稍慢一点。
  jpa方式:这种方式除了速度快点,基本没什么代码,都是自己搞好的,只要按照它的方式写就OK了,写法其实就是平时的jpa写法。缺点,其实我也不确定,对于一些稍微复杂的业务需求,我不知道它如何实现,本来我是用的这种方式,最后改成了solrj方式。
  推荐solrj吧,虽然写法有点傻,但是至少它能满足你的不同变态的要求。

solrj搭建的连接方法:
1.我是自己建立的spring boot项目单独用来做solr查询的,结构如下:

这里写图片描述

  首先,因为solr的查询结果我封装成了对象,facade项目是用于将来其他项目引用solr查询时与返回值匹配上。rest项目有具体的controller接口和具体的连接solr的实现逻辑。rest项目的pom同时引用了facade项目,保证外部引用和自己调用的接口以及对象的一致。
  该项目仓促,还不知道以后怎么调用,打算改成dubbo发布出接口那种,现在还没改,主要写一下solrj的连接方式。其他都靠自己去设计了。

2.引入的jar包如下:
<!--parent标签是spring boot的统一引入的一种方式,如果你像我还有一个parent项目,那需要将下边的parent标签内容移到parent项目中,将其他的引入到rest项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
 <dependencies>
 <!--spring boot项目必须引入的依赖web-->
<dependency>           
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring boot项目引入的solr的依赖-->
<dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-solr</artifactId>
 </dependency>
 <!--下边的这个依赖可以不用引用,我是让前端给我传的参数是以HttpServletRequest形式传入的-->
 <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
 </dependency>
</dependencies>
3.这里不写我是如何在spring boot项目中放置的,源码在该文章最下边可以下载,只以一个main方法的形式,贴出solr的从连接到查询的部分。
package cloud.solr.domain;
//实体类
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.SolrDocument;
import java.io.Serializable;
@SolrDocument(solrCoreName="fbf") //solrj不需要加这个,加上也不报错,我主要是该项目jpa和solrj都可以,我就把实体类弄成了这样。
public class Fbf implements Serializable {
    @Id
    @Field
    private String poid; //主键需要加两个注解
    @Field 
    private String fbfbm; //普通的属性加Field注解即可
    @Field
    private String fbfmc;
//省略get和set方法
}
package cloud.solr.controller;
import cloud.solr.domain.Fbf;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.StringUtils;
import java.io.IOException;
import java.util.List;
import org.springframework.web.bind.annotation.*;
/**
 * Created by lsf on 2017/10/17.
 */
@RestController
@RequestMapping("/testSolr")
public class TestController {
public static void main(String[] args){
   /**
    * http://192.168.1.170:8983/solr/fbf   fbf是solr的一个core名称
    */
   HttpSolrClient solrClient = new HttpSolrClient("http://192.168.1.170:8983/solr/fbf");
   SolrQuery query = new SolrQuery();
   query.setSort("createtime",SolrQuery.ORDER.asc); //设置排序参数及排序规则
   String pageNo = "1";  //第几页
   String pageSize = "10"; //每页多少数据
   if(NumberUtils.isNumber(pageNo) && NumberUtils.isNumber(pageSize)){
       int startPage = Integer.valueOf(pageNo);
       int pageNum = Integer.valueOf(pageSize);
       query.setStart((startPage-1)*pageNum);//起始页,这里一定要注意,不能直接把pageNo赋值给start,start表示从第一个数据开始,第一条从0开始。
       query.setRows(pageNum);//每页显示数量
   }
   StringBuffer buffer = new StringBuffer();
   String fbfmc = "何寨街道季家村高北组"; //查询条件
   if(!StringUtils.isEmpty(fbfmc)){
       buffer.append("fbfmc:"+fbfmc); //如果你的fbfmc字段在solrHome/fbf/conf/manage-schema文件中定义的类型是text_ik,即已经分词了,那么这里可以这么写,如果你定义的是string类型,即没有分词,那这句话的append中的内容需要写成这样buffer.append("fbfmc:*"+fbfmc+"*"),这是solr的查询规则,没有分词最好是加上模糊查询符号"*"
       query.set("q",buffer.toString());
   }else{
       query.set("q","*:*"); //没有传入参数则全部查询
   }
   QueryResponse rsp = null;
   try {
       rsp = solrClient.query( query );
   } catch (Exception e) {
       e.printStackTrace();
   }
   SolrDocumentList results = rsp.getResults();
   System.out.println(results.getNumFound());//查询总条数,该总条数是符合该条件下的总条数,并不是pageSize的数量。
   List<Fbf> fbfList = rsp.getBeans(Fbf.class);//该方法将返回结果转换为对象,很方便。
   System.out.println(fbfList.get(0).getFbfmc());
    }
}

其他常用的方法:

添加方法---是调用solrClient.addBean(Fbf fbf);
根据id查询方法---是调用solrClient.getById(id); //注意它返回值是SolrDocument,可以直接返回给前端,就是key value那种形式。
删除方法---是调用solrClient.deleteById(id);
没有修改方法,只能结合删除和添加来完成修改操作。

说明:
 (1)关于solrj的查询出错,主要是查询参数的传入格式,就像上边的地方,如果fbfmc设置成了分词类型,千万不要再加*,如果是string类型就需要加上*才可以。
 (2)如果你不想再封装成对象,那么你可以直接给前端返回SolrDocumentList results = rsp.getResults();,也就是SolrDocumentList对象即可。
 (3)solrj的连接地址,要具体到某一个core名称上,比如上边的http://192.168.1.170:8983/solr/fbf 连接到了fbf这个core上。

spring boot solr jpa搭建的连接方法:
1.首先引入的jar包与上边的一样,具体也可以看我的项目,下载位置在最下边
2.找到spring boot项目的application.properties文件,添加如下代码:

这个是连接solr的客户端的地址

spring.data.solr.host=http://192.168.1.170:8983/solr
3.添加实体类、jpa查询逻辑类等(以下代码与我的项目源码稍有不同,具体参照项目的下边的写法,我稍微改动了下)
package cloud.solr.domain;
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.SolrDocument;
import java.util.Date;

@SolrDocument(solrCoreName="product") //jpa是在这里与具体的core关联的,所以这个必须加
public class Product {
    @Id
    @Field
    private String id; //主键必须加这两个注解
    @Field
    private String name; //其他属性加一个注解
    @Field
    private String pic;
    @Field
    private double price;
    @Field
    private long comment;
    //省略get和set方法
    }

controller类

package cloud.solr.controller;

import cloud.solr.controller.base.BaseController;
import cloud.solr.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;

/**
 * Created by Administrator on 2017/10/17.
 */
@RestController
public class ProductController extends BaseController{
@Autowired
ProductService productService;
//根据名称查询
@RequestMapping(value = "/selectByName",method = RequestMethod.GET)
@CrossOrigin
public Object SelectObjectByName(HttpServletRequest request){
    return productService.findByName(request.getParameter("name"));
}
//根据名称查询,并且分页
@RequestMapping(value = "/select",method = RequestMethod.GET)
@CrossOrigin
public Object SelectObject(HttpServletRequest request){
    try {
//getPageRequest方法在父类里写了,就是一个封装Pageable对象的方法,具体在下边贴出来。
        return productService.query(request.getParameter("name"),getPageRequest(request));
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
}

在父类中的getPageRequest方法

/**
* 获取分页请求
*/
protected PageRequest getPageRequest(HttpServletRequest request){
int page = 1;
int size = 10;
Sort sort = null;
try {
String sortName = request.getParameter("sortName");
String sortOrder = request.getParameter("sortOrder");
if(StringUtils.isNotBlank(sortName) ){
   if("desc".equalsIgnoreCase(sortOrder)){
       sort = new Sort(Sort.Direction.DESC, sortName);
   }else{
       sort = new Sort(Sort.Direction.ASC, sortName);
   }
}
page = Integer.parseInt(request.getParameter("pageNo")) - 1;
size = Integer.parseInt(request.getParameter("pageSize"));
} catch (Exception e) {
e.printStackTrace();
}
if(sort == null){
sort = new Sort(Sort.Direction.ASC, "id");
}
PageRequest pageRequest = new PageRequest(page, size, sort);
return pageRequest;
}

Service类

package cloud.solr.service;
import cloud.solr.domain.Product;
import cloud.solr.repository.ProductRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class ProductService {
    @Autowired
    ProductRepository productRepository;

    public List<Product> findByName(String name){
        if(StringUtils.isEmpty(name)){
            return new ArrayList<>();
        }
        return productRepository.findByName(name);
    }
    public void save(Product product){
        if(product != null) {
            productRepository.save(product);
        }
    }
    public Page<Product> query(String queryString, Pageable pageable) throws Exception {
        return productRepository.findByNameContaining(queryString, pageable);
    }
}

repository类(注意:重点来了

package cloud.solr.repository;
import cloud.solr.domain.Product;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;
import java.util.List;

public interface ProductRepository extends SolrCrudRepository<Product, String> {
//如果要与名字精确匹配,则如下写法,其中Name为具体的属性名称,如果包含查询,模糊查询则findByNameContaining即可。写法与jpa写法一致。也要注意下solrHome中的manage-schema文件对属性类型的配置是text_ik还是string类型。
List<Product> findByName(String name);

//可以把@Query注释掉findByNameContaining就变成了 name:*?0*,仅按名称匹配
//@Query(value = "name:*?0* or category:*?0*")
Page<Product> findByNameContaining(String name, Pageable pageable);
}

jpa的写法都是一样的,可以从网上看下具体的写法,最下边我可以下载的项目里jpa这种写法我给注释掉了,应该都很容易看懂的。

我的spring boot项目源码下载地址
下一篇写高亮查询

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茁壮成长的凌大大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值