springboot集成elasticsearch

java代码与elasticsearch进行交互

jest客户端方式

1、依赖

      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
        </dependency>

补充:

JNA(Java Native Access):建立在JNI之上的Java开源框架,SUN主导开发,用来调用C、C++代码,尤其是底层库文件(windows中叫dll文件,linux下是so【shared object】文件)。

JNI是Java调用原生函数的唯一机制,JNA就是建立在JNI之上,JNA简化了Java调用原生函数的过程。JNA提供了一个动态的C语言编写的转发器(实际上也是一个动态链接库,在Linux-i386中文件名是:libjnidispatch.so)可以自动实现Java与C之间的数据类型映射。从性能上会比JNI技术调用动态链接库要低。

2、.yml配置文件

server:
  port: 7081
 
spring:
  elasticsearch:
    jest:
      uris:
      - http://192.168.226.133:9200
      read-timeout: 5000

3、定义实体类和接口

@Data
public class Entity implements Serializable {

    private static final long serialVersionUID = -763638353551774166L;
    public static final String INDEX_NAME = "index_entity";
    public static final String TYPE = "tstype";
    
    private Long id;
    private String name;

    public Entity() {
        super();
    }

    public Entity(Long id, String name) {
        this.id = id;
        this.name = name;
    }

}
public interface CityESService {
	
	void saveEntity(Entity entity);
	
	void saveEntity(List<Entity> entityList);
	
	List<Entity> searchEntity(String searchContent);
}

4、实现接口:

    直接注入JestClient客户端对象

    @Autowired
    private JestClient jestClient;

@Service
public class CityESServiceImpl implements CityESService{
	
	private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class);
	
	@Autowired
	private JestClient jestClient;
	
	@Override
	public void saveEntity(Entity entity) {
		Index index = new Index.Builder(entity).index(Entity.INDEX_NAME).type(Entity.TYPE).build();
		try {
			jestClient.execute(index);
			LOGGER.info("ES 插入完成");
		} catch (IOException e) {
			e.printStackTrace();
			LOGGER.error(e.getMessage());
		}
	}
	
	
	/**
	 * 批量保存内容到ES
	 */
	@Override
	public void saveEntity(List<Entity> entityList) {
		Bulk.Builder bulk = new Bulk.Builder();
		for(Entity entity : entityList) {
			Index index = new Index.Builder(entity).index(Entity.INDEX_NAME).type(Entity.TYPE).build();
			bulk.addAction(index);
		}		
		try {
			jestClient.execute(bulk.build());
			LOGGER.info("ES 插入完成");
		} catch (IOException e) {
			e.printStackTrace();
			LOGGER.error(e.getMessage());
		}
	}
	
	/**
	 * 在ES中搜索内容
	 */
	@Override
	public List<Entity> searchEntity(String searchContent){
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		//searchSourceBuilder.query(QueryBuilders.queryStringQuery(searchContent));
		//searchSourceBuilder.field("name");
		searchSourceBuilder.query(QueryBuilders.matchQuery("name",searchContent));
		Search search = new Search.Builder(searchSourceBuilder.toString())
				.addIndex(Entity.INDEX_NAME).addType(Entity.TYPE).build();
		try {
			JestResult result = jestClient.execute(search);
			return result.getSourceAsObjectList(Entity.class);
		} catch (IOException e) {
			LOGGER.error(e.getMessage());
			e.printStackTrace();
		}
		return null;		
	}
}

这里插入数据的方式给了两种,一种是单次API直接插入,一种是利用ES的bulk批量插入。

Spring Data 客户端

Spring Data ElasticSearch必须与ElasticSearch版本相匹配,否则在对接时ES端会报版本不匹配错误,例如我ES是5.6.1版本,Spring boot是1.5.6版本,错误如下:

Spring Boot 1.5.6版本对应的Spring Data ElasticSearch是2.1.6版本,不支持5.X的ES,所以报错。到本博文撰写为止,Spring Boot的RELEASE版本最新的是1.5.8,对应的Spring Data ElasticSearch是2.1.8,仍不支持5.X的ES,所以如果一定要使用Java客户端方式集成ES只能放弃Spring Boot直接使用Spring Data和Spring MVC,或者降低ES的版本使之与Spring boot匹配。
1、依赖

     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
	</dependencies>

2、配置文件

server:
  port: 7081
 
spring:
  data:
    elasticsearch:
      cluster-nodes: 192.168.226.133:9300
      cluster-name: my-es
      repositories:
        enabled: true

注意这里是9300端口

3、Controller、主程序、Service接口同Jest项目不变

     实体类稍作变化,指定ES中的index和type:

@Document(indexName="index_entity", type="tstype")

多一个Repository接口,无需实现类,spring data标准用法:

/**
 * Entity ES操作类
 * @author yejingtao
 *
 */
public interface EntityRepository extends ElasticsearchRepository<Entity,Long>{
 
}

4、service实现

@Service
public class CityESServiceImpl implements CityESService{
	
	private static final Logger LOGGER = LoggerFactory.getLogger(CityESServiceImpl.class);
	
	int PAGE_SIZE = 15; //默认分页大小
	
	int PAGE_NUMBER = 0; //默认当前分页
	
	String SCORE_MODE_SUM = "sum"; //权重分求和模式
	
	Float MIN_SCORE = 10.0F; //由于无相关性的分值默认为1, 设置权重分最小值为10
	
	@Autowired
	EntityRepository entityRepository;
	
	/**
	 * 保存内容到ES
	 */
	@Override
	public Long saveEntity(Entity entity) {
		Entity entityResult = entityRepository.save(entity);
		return entityResult.getId();
	}
	
	/**
	 * 在ES中搜索内容
	 */
	@Override
	public List<Entity> searchEntity(int pageNumber, int pageSize, String searchContent){
		if(pageSize==0) {
			pageSize = PAGE_SIZE;
		}
		if(pageNumber<0) {
			pageNumber = PAGE_NUMBER;
		}
		
		SearchQuery searchQuery = getEntitySearchQuery(pageNumber,pageSize,searchContent);
		
		LOGGER.info("\n searchCity: searchContent [" + searchContent + "] \n DSL  = \n " 
				+ searchQuery.getQuery().toString());
 
		
		Page<Entity> cityPage = entityRepository.search(searchQuery);
		return cityPage.getContent();
	}
	
	/**
	 * 组装搜索Query对象
	 * @param pageNumber
	 * @param pageSize
	 * @param searchContent
	 * @return
	 */
	private SearchQuery getEntitySearchQuery(int pageNumber, int pageSize, String searchContent) {
		FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
				.add(QueryBuilders.matchPhraseQuery("name", searchContent),
						ScoreFunctionBuilders.weightFactorFunction(1000))
				//.add(QueryBuilders.matchPhraseQuery("other", searchContent),
						//ScoreFunctionBuilders.weightFactorFunction(1000))
				.scoreMode(SCORE_MODE_SUM).setMinScore(MIN_SCORE);
		//设置分页,否则只能按照ES默认的分页给
		Pageable pageable = new PageRequest(pageNumber, pageSize);
		return new NativeSearchQueryBuilder().withPageable(pageable).withQuery(functionScoreQueryBuilder).build();
	}
	
}

这两种方式,从设计上来讲属于两种思路,Spring Data的思路就是将ElasticSearch当自家的数据仓库来管理,直接通过Java客户端代码操作ES;Jest的思路是将ElasticSearch当为独立的服务端,自己作为客户端用兼容性最强的RestFul格式来与之交互。

Jest方式,第一兼容性好,不需要考虑版本的问题。第二,从ElasticSearch本身的设计上来分析,9200是对外服务端口,9300是内部管理和集群通信端口,请求9200获取搜索服务更符合ES的设计初衷,不会影响集群内部的通信。

参考:

 SpringBoot集成ElasticSearch5.X:https://blog.csdn.net/qq_28988969/article/details/78933673?utm_source=blogxgwz3

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值