第十章 ES与Spring的集成 ╰半夏微凉° 2023-03-01 11:39 8阅读 0赞 # **一、综述** # ## **1、常见的Elasticsearch Java API有四类client连接方式:** ## ## **1.1、TransportClient(不推荐)** ## Elasticsearch原生的api,TransportClient可以支持2.x,5.x版本,TransportClient 将会在Elasticsearch 7.0弃用并在8.0中完成删除。 ### **1.2、RestClient,ES官方推荐使用** ### ### **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][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.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>7.7.0</version> </dependency> </dependencies> ### **1.2、配置访问es的请求** ### Map<String,String> 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.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.7.0</version> </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<String,Object> message =* *new* *HashMap<>();* *message.put(**"type"**,**"text"**);* *Map<String,Object> properties =* *new* *HashMap<>();* *properties.put(**"message"**,message);* *Map<String,Object> 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<String, Object> message = new HashMap<>(); message.put("type", "text"); Map<String, Object> properties = new HashMap<>(); properties.put("message", message); Map<String, Object> 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进行文档的索引,相关的请求体可以通过多种方法生成 ![20200724162041936.png][] 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的集成这个章节看到。 ![20200724162004543.png][] # **三、SpringBoot集成REST Client** # ## **1、环境配置** ## 具体代码在模块springboot-highlevel模块下: ### **1.1、引入maven依赖:** ### *<!-- es-->* <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.7.0</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.7.0</version> </dependency> 为方便我们的使用,我们还会引入一些其他的组件,比如fastjson和Swagger2: *<!-- fastjson-->* <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.69</version> </dependency> *<!-- Swagger2 -->* <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </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)); List<? extends 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 [https_www.elastic.co_guide_en_elasticsearch_client_java-rest_current_index.html]: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html [20200724162041936.png]: /images/20230208/4def8782002a476d83f3d2947e0408b7.png [20200724162004543.png]: /images/20230208/974628b9019848aca9cdd1c4ebfee613.png
相关 系统集成|第十九章(笔记) 目录 第十九章 风险管理 19.1 风险管理的概述及相关概念 19.2 主要过程 19.2.1 规划风险管理 喜欢ヅ旅行/ 2023年10月16日 14:47/ 0 赞/ 70 阅读
相关 系统集成|第十八章(笔记) 目录 第十八章 安全管理 18.1 信息安全管理 18.2 信息系统安全 18.3 物理安全管理 18.4 人 红太狼/ 2023年10月16日 14:43/ 0 赞/ 72 阅读
相关 系统集成|第十七章(笔记) 目录 第十七章 变更管理 17.1 项目变更的基本概念 17.2 变更管理的基本原则 17.3 角色职位与工作程序 本是古典 何须时尚/ 2023年10月16日 14:39/ 0 赞/ 28 阅读
相关 系统集成|第十五章(笔记) 目录 第十五章 采购管理 14.1 概述及相关概念 14.2 主要过程 14.2.1 编制采购计划 逃离我推掉我的手/ 2023年10月16日 14:18/ 0 赞/ 50 阅读
相关 系统集成|第十四章(笔记) 目录 第十四章 合同管理 14.1 概述及相关概念 14.2 项目合同 14.3 《合同法》 14.4 《仲裁 ﹏ヽ暗。殇╰゛Y/ 2023年10月16日 14:15/ 0 赞/ 39 阅读
相关 系统集成|第十三章(笔记) 目录 第十三章 干系人管理 13.1 概述与相关概念 13.2 主要过程 13.2.1 识别干系人 ╰半橙微兮°/ 2023年10月16日 14:08/ 0 赞/ 59 阅读
相关 系统集成|第十二章(笔记) 目录 第十二章 沟通管理 12.1 沟通的基本概念 12.2 主要过程 12.2.1 规划沟通管理 ゞ 浴缸里的玫瑰/ 2023年10月16日 13:31/ 0 赞/ 70 阅读
相关 系统集成|第十一章(笔记) 目录 第十一章 项目人力资源管理 11.1 项目人力资源管理的定义及有关概念 11.2 主要过程 11.2.1 编制项 ゝ一纸荒年。/ 2023年10月16日 13:26/ 0 赞/ 70 阅读
相关 系统集成|第十章(笔记) 目录 第十章 质量管理 10.1 项目质量管理概论 10.2 主要过程 10.2.1 规划质量管理 左手的ㄟ右手/ 2023年10月16日 11:27/ 0 赞/ 71 阅读
相关 第十章 ES与Spring的集成 一、综述 1、常见的Elasticsearch Java API有四类client连接方式: 1.1、TransportClient(不推荐) Elasti ╰半夏微凉°/ 2023年03月01日 11:39/ 0 赞/ 9 阅读
还没有评论,来说两句吧...