第十章 ES与Spring的集成

一、综述

1、常见的Elasticsearch Java API有四类client连接方式:

1.1、TransportClient(不推荐)

Elasticsearch原生的api,TransportClient可以支持2.x,5.x版本,TransportClient 将会在Elasticsearch 7.0弃用并在8.0中完成删除。

1.2、RestClientES官方推荐使用

1.3、Jest(不推荐)

是Java社区开发的,是Elasticsearch的Java Http Rest客户端。

1.4、Spring Data Elasticsearch

与Spring生态对接,可以在web系统中整合到Spring中使用,与SpringBoot、SpringData版本容易冲突,而且往往很难跟上Elasticsearch版本的更新,比如SpringBoot目前的2.3.1.RELEASE,所支持Elasticsearch 7.6.2。

从使用上来说,Spring Data的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如 MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率,也就是说,Spring Data想要把对任何数据的访问都抽象为类似接口,这就导致了 Spring Data Elasticsearch在基本查询上没问题,但是复杂查询(模糊、通配符、match查询、聚集查询等)就显得力不从心了,此时,我们还是只能使用原生查询。

2、REST Client介绍

Java REST Client有Low Level和High Level两种:

Java Low Level REST Client:

使用该客户端需要将HTTP请求的body手动拼成JSON格式,HTTP响应也必须将返回的JSON数据手动封装成对象,使用上更为原始。

Java High Level REST Client:

该客户端基于Low Level客户端实现,提供API解决Low Level客户端需要手动转换数据格式的问题。

ES的官网已经提供了非常详尽的API参考手册,参见:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html

二、REST Client使用

1、Java Low Level REST Client

具体代码在模块es-low-level模块下

1.1、maven导入

<dependencies>
    <dependency>
        <groupId>org.elasticsearch.clientgroupId>
        <artifactId>elasticsearch-rest-clientartifactId>
        <version>7.7.0version>
    dependency>
dependencies>

1.2、配置访问es的请求

Map params = Collections.EMPTY_MAP;
String jsonString = "{" + "\"msg\":\"Java Low Level REST Client\""+ "}";
System.out.println(jsonString);
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
Request request = new Request("PUT","enjoy_test/_doc/6");
request.addParameters(params);
request.setEntity(entity);

1.3、发送请求并接收应答

Response response = restClient.performRequest(request);
System.out.println(response);
System.out.println(EntityUtils.toByteArray(response.getEntity()));

因为Java Low Level REST Client用法比较原始,在实际工作中用的比较少所以大概了解下用法即可,对应的类是TestEsLowSdk。

2、Java High Level REST Client

具体代码在模块es-high-level模块下

2.1、maven依赖导入

<dependency>
    <groupId>org.elasticsearch.clientgroupId>
    <artifactId>elasticsearch-rest-high-level-clientartifactId>
    <version>7.7.0version>
dependency>

代码对应的类是 TestEsHighSdk

2.2、创建访问客户端

RestClientBuilder restClientBuilder = RestClient.builder( new HttpHost("192.168.0.101",9200,"http"));

2.3、创建索引

/*创建索引*/
CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
/* 这里可以对索引对象进行属性设置 */
createIndexRequest.settings(Settings.builder()
.put("index.number_of_shards",3)
.put("index.codec","best_compression"));
Map message = new HashMap<>();
message.put("type","text");
Map properties = new HashMap<>();
properties.put("message",message);
Map mapping = new HashMap<>();
mapping.put("properties",properties);
createIndexRequest.mapping(mapping);
createIndexRequest.mapping("{" +"\"msg\":\"Java Low Level REST Client\""+"}", XContentType.JSON);
XContentBuilder.builder()
//
CreateIndexResponse createIndexResponse
        = restHighLevelClient.indices().create(createIndexRequest,RequestOptions.DEFAULT);
System.out.println(createIndexResponse.index());
System.out.println(createIndexResponse.isAcknowledged());

使用CreateIndexRequest进行索引创建,如果想要对索引进行静态配置,可以使用request.settings。配置索引的映射有好几种方式,比如我们想配置的索引映射是:

put /high_sdk/_mapping

{

  "properties": {

    " message": {

      "type": "text"

    }

  }

}

可以采用: 

request.mapping(

"{\n" + " \"properties\": {\n" +" \"message\": {\n" + " \"type\": \"text\"\n" + " }\n" + " }\n" + "}",

XContentType.JSON);

也可以采用: 

Map message = new HashMap<>();

message.put("type", "text");

Map properties = new HashMap<>();

properties.put("message", message);

Map mapping = new HashMap<>();

mapping.put("properties", properties);

request.mapping(mapping);

还可以采用:

XContentBuilder builder = XContentFactory.jsonBuilder();

builder.startObject();

{ builder.startObject("properties");

{ builder.startObject("message");

{ builder.field("type", "text");}

builder.endObject();

}

builder.endObject();

}

builder.endObject();

request.mapping(builder);

然后通过client.indices().create方法将请求发送给es即可,es的应答将通过CreateIndexResponse返回给我们。

2.4、索引(保存)文档

基本上和创建索引的思路是一样的

/*索引(保存)文档*/
IndexRequest indexRequest = new IndexRequest(indexName);
indexRequest.id(docId);

使用IndexRequest进行文档的索引,相关的请求体可以通过多种方法生成

 

第十章 ES与Spring的集成_第1张图片

XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
xContentBuilder.startObject();
{
    xContentBuilder.field("user","hankin");
    xContentBuilder.timeField("postData",new Date());
    xContentBuilder.field("message","Go ELK");
}
xContentBuilder.endObject();
indexRequest.source(xContentBuilder);
IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(index.getIndex());
System.out.println(index.getId());

然后通过client.index方法将请求发送给es即可,es的应答将通过CreateIndexResponse返回给我们。

2.5、查询文档

使用GetRequest进行查询,通过client.get方法将请求发送给es即可,es的应答将通过GetResponse返回给我们。

/*查询文档*/
GetRequest getRequest = new GetRequest(indexName, docId);
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println(" get indexname = "+getResponse.getIndex());
if(getResponse.isExists()){
    System.out.println("获取的文档:"+getResponse.getSourceAsString());
}else{
    System.out.println("文档不存在");
}

更多的与检索相关的类或者方法,我们将在和SpringBoot的集成这个章节看到。

 

第十章 ES与Spring的集成_第2张图片

三、SpringBoot集成REST Client

1、环境配置

具体代码在模块springboot-highlevel模块下:

1.1、引入maven依赖:


<dependency>
    <groupId>org.elasticsearchgroupId>
    elasticsearch
    7.7.0
dependency>
<dependency>
    <groupId>org.elasticsearch.clientgroupId>
    elasticsearch-rest-high-level-client
    7.7.0
dependency>

为方便我们的使用,我们还会引入一些其他的组件,比如fastjson和Swagger2:


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
    <version>1.2.69version>
dependency>

<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger2artifactId>
    <version>2.9.2version>
dependency>
<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger-uiartifactId>
    <version>2.9.2version>
dependency>

比较关键的类是:

  • AggsSearch:聚集搜索服务类
  • NormalSearch:一般搜索服务类
  • OperateDoc:操作文档的服务
  • OperateIndex:操作索引的服务

SendSearchRequest:通用的发送Search请求,并处理响应结果的服务。其中主要包括了索引的管理、文档的管理、_search接口基本用法、基于词项的查询、基于全文的查询、基于全文的模糊查询、组合查询、聚集查询的相关范例,详情参阅相关代码。

1.2、添加application.yml配置

server:
  port: 8899
elasticsearch:
  host: 192.168.0.101
  port: 9200

配置类代码实现:

@Configuration
public class ESConfig {
    @Value("${elasticsearch.host}")
    private String host;
    @Value("${elasticsearch.port}")
    private int port;
    @Bean
    public RestClientBuilder restClientBuilder() {
        HttpHost httpHost = new HttpHost(host, port, "http");
        RestClientBuilder restClientBuilder = RestClient.builder(httpHost);
        return restClientBuilder;
    }
    @Bean
    public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
        return new RestHighLevelClient(restClientBuilder);
    }
}

1.3、实体类代码

/**
 * 给前端页面返回的应答实体
 */
public class ResponseBean {
    //状态码
    private Integer code;
    //返回信息
    private String message;
    //返回的数据
    private Object data;
    public ResponseBean(Integer code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

保存文档的实体:

public class User {
    private String firstName;
    private String secondName;
    private String content;
    private Integer age;

1.4、启动类代码实现:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

2、测试代码实现

2.1、controller层代码实现

@Api(value = "ES测试接口", tags = { "ES测试接口"})
@RestController
@RequestMapping("/es")
@CrossOrigin(origins = "*", methods = { RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
public class ESController {
    @Resource
    private OperateIndex operateIndex;
    @Resource
    private OperateDoc operateDoc;
    @Resource
    private NormalSearch normalSearch;
    @Resource
    private AggsSearch aggsSearch;
    private  final Logger log = LoggerFactory.getLogger(ESConfig.class);
    private final static String KIBANA_SAMPLE_DATA_FLIGHTS = "kibana_sample_data_flights";
    private final static String KIBANA_SAMPLE_DATA_LOGS = "kibana_sample_data_logs";
    @ApiOperation(value = "es测试创建索引接口", notes = "es测试创建索引接口")
    @RequestMapping(value = "/index/creation", method = RequestMethod.POST)
    public ResponseBean createIndex(@RequestParam String indexName) {
        try {
            if (operateIndex.createIndex(indexName)) {
                return new ResponseBean(200, "创建成功", null);
            } else {
                return new ResponseBean(1002, "创建失败", null);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    @ApiOperation(value = "es测试是否存在索引接口", notes = "es测试是否存在索引接口")
    @RequestMapping(value = "/index/existence", method = RequestMethod.POST)
    public ResponseBean indexExists(@RequestParam String indexName) {
        boolean isExists = operateIndex.isIndexExists(indexName);
        String msg = isExists? "索引存在:"+indexName : "索引不存在:"+indexName ;
        return new ResponseBean(200, msg, isExists);
    }
    @ApiOperation(value = "es测试删除索引接口", notes = "es测试删除索引接口")
    @RequestMapping(value = "/index/erasure", method = RequestMethod.POST)
    public ResponseBean deleteIndex(@RequestParam String indexName) {
        boolean isDelete = operateIndex.deleteIndex(indexName);
        if (isDelete) {
            return new ResponseBean(200, "删除成功", null);
        } else {
            return new ResponseBean(10002, "删除失败", null);
        }
    }
    @ApiOperation(value = "es测试插入文档接口", notes = "es测试插入文档接口")
    @RequestMapping(value = "/doc/insertion", method = RequestMethod.POST)
    public ResponseBean insertDoc(@RequestBody User user,@RequestParam String indexName,
                                  @RequestParam  String docId) {
        return operateDoc.insertDoc(user,indexName,docId);
    }
    @ApiOperation(value = "es测试获取文档接口", notes = "es测试插入文档接口")
    @RequestMapping(value = "/doc/query", method = RequestMethod.GET)
    public ResponseBean getDoc(@RequestParam String indexName, @RequestParam String docId) {
        return operateDoc.getDoc(indexName,docId);
    }
    @ApiOperation(value = "es测试更新文档接口", notes = "es测试插入文档接口")
    @RequestMapping(value = "/doc/update", method = RequestMethod.POST)
    public ResponseBean updateDoc(@RequestParam String indexName, @RequestParam String docId,
                                  @RequestParam String fieldName,@RequestParam String fieldValue) {
        return operateDoc.updateDoc(indexName,docId,fieldName,fieldValue);
    }
    @ApiOperation(value = "es测试删除文档接口", notes = "es测试插入文档接口")
    @RequestMapping(value = "/doc/erasure", method = RequestMethod.POST)
    public ResponseBean deleteDoc(@RequestParam String indexName,@RequestParam String docId) {
        return operateDoc.deleteDoc(indexName,docId);
    }
    @ApiOperation(value = "_search接口基本用法", notes = "search接口基本用法")
    @RequestMapping(value = "/search/example", method = RequestMethod.POST)
    public ResponseBean searchExample() {
        return normalSearch.searchExample(KIBANA_SAMPLE_DATA_FLIGHTS);
    }
    @ApiOperation(value = "基于词项的查询", notes = "基于词项的term查询")
    @RequestMapping(value = "/search/term", method = RequestMethod.POST)
    public ResponseBean termsBasedSearch() {
        return normalSearch.termsBasedSearch(KIBANA_SAMPLE_DATA_FLIGHTS, "dayOfWeek");
    }
    @ApiOperation(value = "基于全文的查询", notes = "基于全文的multi_match查询")
    @RequestMapping(value = "/search/match", method = RequestMethod.POST)
    public ResponseBean matchBasedSearch() {
        return normalSearch.matchBasedSearch(KIBANA_SAMPLE_DATA_FLIGHTS,
                "AT","DestCountry", "OriginCountry");
    }
    @ApiOperation(value = "基于全文的模糊查询", notes = "基于全文的模糊查询")
    @RequestMapping(value = "/search/fuzzy", method = RequestMethod.POST)
    public ResponseBean fuzzySearch() {
        return normalSearch.fuzzySearch(KIBANA_SAMPLE_DATA_LOGS,"message","firefix");
    }
    @ApiOperation(value = "组合查询范例", notes = "组合查询之bool查询")
    @RequestMapping(value = "/search/combination-bool", method = RequestMethod.POST)
    public ResponseBean combinationSearch() {
        return normalSearch.boolSearch(KIBANA_SAMPLE_DATA_LOGS);
    }
    @ApiOperation(value = "聚集查询范例", notes = "聚集查询范例")
    @RequestMapping(value = "/search/aggsExample", method = RequestMethod.POST)
    public ResponseBean aggsExampleSearch() {
        return aggsSearch.aggsExampleSearch(KIBANA_SAMPLE_DATA_FLIGHTS);
    }
}

2.2、普通搜索业务代码实现:

@Service
public class NormalSearch {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    @Resource
    private SendSearchRequest sendSearchRequest;
    /**
     * get kibana_sample_data_flights/_search
     * {
     *     "from":100,
     *     "size":20,
     *     "query":{
     *        "match_all":{}
     *        },
     *     "_source":["Origin*","*Weather"],
     *     "sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
     * }
     */
    public ResponseBean searchExample(String indexName) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(5);
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        String[] includeFields = new String[]{ "Origin*","*Weather"};
        searchSourceBuilder.fetchSource(includeFields,null);
        searchSourceBuilder.sort(new FieldSortBuilder("DistanceKilometers").order(SortOrder.ASC));
        searchSourceBuilder.sort(new FieldSortBuilder("FlightNum").order(SortOrder.DESC));
        searchRequest.source(searchSourceBuilder);
        return sendSearchRequest.send(searchRequest, RequestOptions.DEFAULT);
    }
    /**
     * get kibana_sample_data_flights/_search
     * {
     *     "query":{
     *        "term":{
     *           "dayOfWeek":3
     *                }*   }
     * }
     */
    public ResponseBean termsBasedSearch(String indexName,String fieldName) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(fieldName,3);
        searchSourceBuilder.query(termQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        return sendSearchRequest.send(searchRequest,RequestOptions.DEFAULT);

    }
    /**
     * POST /kibana_sample_data_flights/_search
     * {
     *     "query": {
     *        "multi_match": {
     *           "query":"AT",
     *           "fields":["DestCountry", "OriginCountry"]
     *                }*   }
     * }
     */
    public ResponseBean matchBasedSearch(String indexName, Object text, String... fieldsName) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(text,fieldsName));
        searchRequest.source(searchSourceBuilder);
        return sendSearchRequest.send(searchRequest, RequestOptions.DEFAULT);
    }
    /**
     * 基于全文的模糊查询
     * get kibana_sample_data_logs/_search
     * {
     *     "query": {
     *         "fuzzy": {
     *             "message": {
     *                 "value": "firefix",
     *                 "fuzziness": "1"
     *             }
     *         }
     *     }
     * }
     */
    public ResponseBean fuzzySearch(String indexName, String fieldsName, String text) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // KIBANA_SAMPLE_DATA_LOGS, "message","firefix"
        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery(fieldsName, text);
        fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
        searchSourceBuilder.query(fuzzyQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        return sendSearchRequest.send(searchRequest, RequestOptions.DEFAULT);
    }
    /**
     * POST /kibana_sample_data_logs/_search
     * {
     *     "query": {
     *        "bool": {
     *           "must":[
     *                 {"match": { "message": "firefox"} }
     *           ],
     *           "should":[
     *                {"term": { "geo. src": "CN"}},
     *                {"term": { "geo. dest": "CN"}}
     *           ]
     *        }
     *     }
     * }
     */
    public ResponseBean boolSearch(String indexName) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("message","firefox"))
                .should(QueryBuilders.termQuery("geo.src","CN"))
                .should(QueryBuilders.termQuery("geo.dest","CN"));
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        return sendSearchRequest.send(searchRequest, RequestOptions.DEFAULT);
    }
}

2.3、文档操作类代码实现

@Service
public class OperateDoc {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    /**
     * 创建文档
     */
    public ResponseBean insertDoc(User user, String indexName, String docId) {
        IndexRequest indexRequest = new IndexRequest(indexName);
        String userJson = JSONObject.toJSONString(user);
        if(!docId.equals("noid")){
            indexRequest.id(docId);
        }
        indexRequest.source(userJson, XContentType.JSON);
        try {
            IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            if(indexResponse!=null){
                String id = indexResponse.getId();
                String index = indexResponse.getIndex();
                if(indexResponse.getResult() == DocWriteResponse.Result.CREATED){
                    System.out.println("新增文档成功");
                    return  new ResponseBean(200,"索引文档成功",id);
                }else if(indexResponse.getResult() == DocWriteResponse.Result.UPDATED){
                    System.out.println("覆盖文档成功");
                    return  new ResponseBean(200,"覆盖文档成功",null);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 查询文档
     */
    public ResponseBean getDoc(String indexName, String docId) {
        return new ResponseBean(200,"参考TestEsHighSdk",indexName+docId);
    }
    /**
     * 更新文档
     */
    public ResponseBean updateDoc(String indexName, String docId, String fieldName, String fieldValue) {
        try {
            XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
            xContentBuilder.startObject();
            {
                xContentBuilder.field(fieldName,fieldValue);
                //xContentBuilder.timeField()
            }
            xContentBuilder.endObject();
            UpdateRequest request = new UpdateRequest(indexName, docId).doc(xContentBuilder);
            request.docAsUpsert(true);
            request.fetchSource(true);/*在应答里包含当前文档的内容*/
            UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
            GetResult getResult = updateResponse.getGetResult();
            if(getResult.isExists()){
                String sourceAsString = getResult.sourceAsString();
                return new ResponseBean(200,"更新文档成功",sourceAsString);
            }else{
                return new ResponseBean(200,"更新文档失败",indexName+"/"+docId+"/"+fieldName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 删除文档
     */
    public ResponseBean deleteDoc(String indexName, String docId) {
        DeleteRequest deleteRequest = new DeleteRequest(indexName, docId);
        try {
            DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            if(deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND){
                return new ResponseBean(200,"删除不存在的文档",indexName+"/"+docId);
            }else{
                return new ResponseBean(200,"删除文档成功",indexName+"/"+docId);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

2.4、索引管理代码实现

@Service
public class OperateIndex {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    /**
     * 新建索引
     */
    public boolean createIndex(String indexName) throws IOException {
        XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
                .startObject().field("properties").startObject().field("firstName")
                .startObject().field("type", "keyword").endObject().field("secondName")
                .startObject().field("type", "keyword").endObject().field("age")
                .startObject().field("type", "integer").endObject().field("content")
                .startObject().field("type", "text").endObject()
                .endObject().endObject();
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
        createIndexRequest.mapping(xContentBuilder);
        CreateIndexResponse createIndexResponse
                = restHighLevelClient.indices().create(createIndexRequest,RequestOptions.DEFAULT);
        boolean acknowledeg = createIndexResponse.isAcknowledged();
        return acknowledeg;
    }
    /**
     * 查询是否存在
     */
    public boolean isIndexExists(String indexName) {
        GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
        getIndexRequest.humanReadable(true);
        boolean exists =   false;
        try {
            exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return exists;
    }
    /**
     * 删除索引
     */
    public boolean deleteIndex(String indexName) {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
        deleteIndexRequest.indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
        boolean acknowledged = false;
        try {
            AcknowledgedResponse delete =
                    restHighLevelClient.indices().delete(deleteIndexRequest,RequestOptions.DEFAULT);
            acknowledged = delete.isAcknowledged();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return acknowledged;
    }
}

2.5、聚集索引

@Service
public class AggsSearch {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    @Resource
    private SendSearchRequest sendSearchRequest;
    /**
     * POST /kibana_sample_data_flights/_search?filter_path=aggregations
     * {
     *     "query": {
     *        "term": {"OriginCountry": "CN"}
     *        },
     *     "aggs":
     *    {
     *        "date_price_histogram": {
     *           "date_histogram": {
     *              "field": "timestamp",
     *              "interval": "month"
     *            },
     *           "aggs": {
     *              "avg_price": {"avg": {"field": "FlightDelayMin"}}
     *            }
     *        }
     *    }
     * }
     */
    public ResponseBean aggsExampleSearch(String indexName) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);
        /*query部分*/
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query( QueryBuilders.termQuery("OriginCountry","CN"));
        /*聚集部分*/
        DateHistogramAggregationBuilder date_price_histogram = AggregationBuilders.dateHistogram("date_price_histogram");
        date_price_histogram.field("timestamp").fixedInterval(DateHistogramInterval.days(30));
        date_price_histogram.subAggregation(AggregationBuilders.avg("avg_price").field("FlightDelayMin")
        );
        searchSourceBuilder.aggregation(date_price_histogram);
        searchRequest.source(searchSourceBuilder);
        JSONArray jsonArray = new JSONArray();
        try {
            SearchResponse searchResponse = sendSearchRequest.sendAndProcessHits(searchRequest, RequestOptions.DEFAULT,jsonArray);
            Aggregations aggregations = searchResponse.getAggregations();
            for(Aggregation aggregation : aggregations){
                String aggString = JSON.toJSONString(aggregation);
                jsonArray.add(JSON.parseObject(aggString));
                Listextends Histogram.Bucket> buckets = ((Histogram) aggregation).getBuckets();
                for(Histogram.Bucket bucket:buckets){
                    System.out.println("--------------------------------------");
                    System.out.println(bucket.getKeyAsString());
                    System.out.println(bucket.getDocCount());
                    ParsedAvg parsedAvg = (ParsedAvg)bucket.getAggregations().getAsMap().get("avg_price");
                    System.out.println(parsedAvg.getValueAsString());
                }
            }
            return new ResponseBean(200,"查询文档成功",jsonArray);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseBean(200,"查询文档失败",null);
        }
    }
}

2.6、发送请求代码实现

@Service
public class SendSearchRequest {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    /**
    * 一般来说,非聚集的检索只需处理hits部分,直接将结果返回给前端
    */
    public ResponseBean send(SearchRequest searchRequest,RequestOptions options){
        JSONArray jsonArray = new JSONArray();
        try {
            sendAndProcessHits(searchRequest,options,jsonArray);
            return new ResponseBean(200,"查询文档",jsonArray);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseBean(200,"查询文档失败",null);
        }
    }
    /**
     * 处理返回结果中的hits部分
     */
    public SearchResponse sendAndProcessHits(SearchRequest searchRequest,
                 RequestOptions options,JSONArray jsonArray) throws IOException {
        SearchResponse search = restHighLevelClient.search(searchRequest, options);
        SearchHits hits = search.getHits();
        for(SearchHit hit:hits){
            String src = hit.getSourceAsString();
            JSONObject jsonObject = JSON.parseObject(src);
            jsonArray.add(jsonObject);
        }
        return search;
    }
}

代码参考地址:https://gitee.com/hankin_chj/es-platform.git

你可能感兴趣的:(Elastic,elasticsearch)