SpringMvc整合elasticsearch的代码实现

 

                             SpringMvc整合elasticsearch

1、elasticsearch(以下简称es)的特性可以简单归结为以下三点:

  • 一个分布式的实施文档存储,每个字段可以被索引与搜索;
  • 一个分布式实时分析搜索引擎;
  • 可以胜任上百个服务节点的扩展,并支持PB级别的结构化或者非结构化数据;

2、es对于版本的兼容性要求较高,因此应特别主要版本的兼容。

  1. es官网可以下载最新版本的es压缩包(https://www.elastic.co/downloads/elasticsearch),解压后即可使用。
  2. \elasticsearch-6.3.2\bin\elasticsearch.bat   通过该路径启动es服务。
  3. 浏览器输入http://localhost:9200/?pretty检查服务是否启动,正常启动如下:

   4、引入maven依赖包(切记版本对应)。

   <elasticsearch.version>6.3.2</elasticsearch.version>

<!-- 引入Elasticsearch相关jar包-->
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>

3、java端代码:可自行整理配置文件

1、ElasticsConfig建立es连接,HttpHost参数可为数组,集群分布多个ip端口时可重新该方法。

package com.fcbox.fms.elasticSearch;

import com.fcbox.fms.disconf.AppConfig;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class ElasticsConfig {

    @Autowired
    private AppConfig appConfig;

    /**
     * 初始化
     */
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        return getEsClientDecorator().getRestHighLevelClient();
    }

    @Bean
    @Scope("singleton")
    public ESClientDecorator getEsClientDecorator() {
        //可以配置集群 通过逗号隔开
        return new ESClientDecorator(new HttpHost("localhost",9200));
    }

}

2、ESClientDecorator es客户端连接

package com.fcbox.fms.elasticSearch;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class ESClientDecorator implements InitializingBean, DisposableBean {

    private RestHighLevelClient restHighLevelClient;

    private HttpHost httpHost;

    public ESClientDecorator(HttpHost httpHost) {
        this.httpHost = httpHost;
    }

    public RestHighLevelClient getRestHighLevelClient() {
        if (restHighLevelClient == null) {
            restHighLevelClient = new RestHighLevelClient(RestClient.builder(httpHost));
        }
        return restHighLevelClient;
    }


    @Override
    public void destroy() throws Exception {
        restHighLevelClient.close();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        restHighLevelClient = new RestHighLevelClient(RestClient.builder(httpHost));
    }

}

3、构建查询接口ISearchClient 和接口实现EsSearchClient

package com.fcbox.fms.elasticSearch.service;

import com.alibaba.fastjson.JSONObject;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;

import java.util.List;

public interface ISearchClient {

    /**
     * 搜索结果
     */
    List<JSONObject> search(SearchRequest request);

    List<String> searchString(SearchRequest request);
    /**
     * 搜索
     */
    <T> List<T> search(SearchRequest request, Class<T> tClass);

    /**
     *
     * @param index 数据库名称
     * @param type 数据库表名
     * @param id 数据库主键ID
     * @param t 实体class
     * @param <T>
     * @return
     */
	<T> IndexResponse saveEntity(String index, String type, String id, T t);

//    IndexResponse saveEntity(TestBean testBean);
}
package com.fcbox.fms.elasticSearch.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fcbox.fms.elasticSearch.service.ISearchClient;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service("searchClient")
public class EsSearchClient implements ISearchClient {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public List<JSONObject> search(SearchRequest request) {
        try {
            SearchResponse response = client.search(request);
            if (response.getHits() == null) {
                return null;
            }
            List<JSONObject> list = new ArrayList<>();
            response.getHits().forEach(item -> list.add(JSON.parseObject(item.getSourceAsString())));
            log.info("Hits",response.getHits().toString());
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<String> searchString(SearchRequest request) {
        try {
        	
            SearchResponse response = client.search(request);
            
            if (response.getHits() == null) {
                return null;
            }
            List<String> list = new ArrayList<>();
            response.getHits().forEach(item -> list.add(item.getSourceAsString()));
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public <T> List<T> search(SearchRequest request, Class<T> tClass) {
    	
        List<JSONObject> searchResponse = this.search(request);
        if (searchResponse == null) {
            return null;
        }
        List<T> list = new ArrayList<>(searchResponse.size());
        searchResponse.forEach(item -> list.add(JSON.parseObject(JSON.toJSONString(item), tClass)));
        return list;
    }

    @Override
    public <T> IndexResponse saveEntity(String index, String type, String id, T t) {
    	IndexResponse indexResponse = null;
    	try {
            IndexRequest indexRequest = new IndexRequest(index, type , id);
            indexRequest.source(JSON.toJSONString(t) , XContentType.JSON);
            /*BulkRequest bulkRequest = new BulkRequest();
            bulkRequest.add(indexRequest);
            Header basicHeader = new BasicHeader("Content-Type:application" , "json");*/
            //this.client.bulk(bulkRequest , basicHeader);
            indexResponse = this.client.index(indexRequest);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        return indexResponse;
    }
}

4、es插入、查询测试类:

package com.fcbox.fms.report.web.controller;

import com.fcbox.fms.base.web.controller.BaseController;
import com.fcbox.fms.domain.user.FmsUserDto;
import com.fcbox.fms.elasticSearch.service.ISearchClient;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("/testLocalController")
/**
 * es测试类
 * @since 2018-05-24
 * @author 002157
 * @version V1.0
 */
public class testLocalController extends BaseController {

	private final Logger LOG = LoggerFactory.getLogger(testLocalController.class);

	@Autowired
	private ISearchClient iSearchClient;



	@RequestMapping("/testEs")
	@ResponseBody
	public void testEs() throws Exception {

		//插入数据
		for(int i=11;i<20;i++){
			FmsUserDto user = new FmsUserDto();
			user.setName("es测试数据名称1");
			user.setCompanyname("测试企业2");
			user.setId(Long.valueOf(i+""));
			IndexResponse indexResponse = iSearchClient.saveEntity("mytest", "testBean", i+"",user );
			System.out.println(indexResponse.toString());
		}

		//es查询
		SearchRequest request  =new SearchRequest();
		//数据库名称
		request.indices("mytest");
		//表名
		request.types("testBean");
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		sourceBuilder.query(QueryBuilders.matchQuery("name", "数据"))
				.query(QueryBuilders.matchQuery("companyname", "开心"));
		//设置排序
		sourceBuilder.sort("id",SortOrder.DESC);
		//设置分页
		sourceBuilder.from(0);
		sourceBuilder.size(5);
		request.source(sourceBuilder);

		List<FmsUserDto> users	= iSearchClient.search(request, FmsUserDto.class);
		System.out.println("user :"+users.toString());



	}

	@RequestMapping("/testMoreEs")
	@ResponseBody
	public void testMoreEs() throws Exception {
		//多条件设置
		SearchRequest request  =new SearchRequest();
		request.indices("mytest");
		request.types("testBean");


		MatchPhraseQueryBuilder mpq1 = QueryBuilders.matchPhraseQuery("name","数据");
		MatchPhraseQueryBuilder mpq2 = QueryBuilders.matchPhraseQuery("companyname","企业");
		QueryBuilder qb2 = QueryBuilders.boolQuery().must(mpq1).must(mpq2);
		SearchSourceBuilder sourceBuilderm = new SearchSourceBuilder();
		sourceBuilderm.query(qb2);
		sourceBuilderm.sort("id",SortOrder.DESC);
		sourceBuilderm.from(0);
		sourceBuilderm.size(5);
		request.source(sourceBuilderm);
		List<FmsUserDto>  users	= iSearchClient.search(request, FmsUserDto.class);
		System.out.println("user :"+users.toString());
	}
}

5、es进行深度分页的性能是比较差的,当我们要拉取全量数据的时候,经常会用到scroll API 拉取全量数据。主要的思路是每次拉取少量的数据,同时返回一个scrollId,通过scrollid获取下一批数据循环。

@Test
    public void test3(){
        RestClient lowLevelRestClient = RestClient.builder(
                new HttpHost("172.16.73.50", 9200, "http")).build();
        RestHighLevelClient client =
                new RestHighLevelClient(lowLevelRestClient);
        SearchRequest searchRequest = new SearchRequest("bank");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchAllQueryBuilder mqb = QueryBuilders.matchAllQuery();
        searchSourceBuilder.query(mqb);
        searchSourceBuilder.size(10); 
        searchRequest.source(searchSourceBuilder);
        searchRequest.scroll(TimeValue.timeValueMinutes(1L)); 
        try {
            SearchResponse searchResponse = client.search(searchRequest);
            String scrollId = searchResponse.getScrollId(); 
            SearchHit[] hits = searchResponse.getHits().getHits();
            System.out.println("first scroll:");
            for (SearchHit searchHit : hits) {
                System.out.println(searchHit.getSourceAsString());
            }
            Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
            System.out.println("loop scroll:");
            while(hits != null && hits.length>0){
                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); 
                scrollRequest.scroll(scroll);
                searchResponse = client.searchScroll(scrollRequest);
                scrollId = searchResponse.getScrollId();
                hits = searchResponse.getHits().getHits();
                for (SearchHit searchHit : hits) {
                    System.out.println(searchHit.getSourceAsString());
                }
            }
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); 
            clearScrollRequest.addScrollId(scrollId);
            ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest);
            boolean succeeded = clearScrollResponse.isSucceeded();
            System.out.println("cleared:"+succeeded);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }

6、链接方式,有兴趣的可以从我的github下载下来看看,基本也就是上面贴出来的代码https://github.com/linqing5407/javaPro.git

猜你喜欢

转载自blog.csdn.net/lq18050010830/article/details/81665883