2万字长文揭示SpringBoot整合ElasticSearch的高阶妙用!
今天我们来来讲解如何在Spring boot的项目中操作Elasticsearch,本章采用的API是官方的Java High Level REST Client v7.9.1。在学习本章以前,你最好已经掌握基本的Java后端开发知识并会使用Spring boot开发框架。由于篇幅的限制,本章只讲解比较常用的代码实现,很多代码可以复用,大家可以在实际项目中举一反三。
8.1 开发前的准备
去码云上下载本章的源代码,地址为https://gitee.com/shenzhanwang/Spring-elastic_search,然后将它导入IDE,它是一个标准的Spring boot工程,该工程的各个package说明如下:
(1)boot.spring.config:包含全局的配置类,例如允许接口跨域的配置。
(2)boot.spring.controller:包含各种后台接口的控制器。
(3)boot.spring,elastic.client:包含连接Elasticsearch的客户端配置类。
(4)boot.spring.elastic.service:包含读写Elasticsearch的通用方法服务,包含建索引、搜索和统计分析的三个服务类。
(5)boot.spring.pagemodel:包含主要用于下发到前端的对象类。
(6)boot.spring.po:包含索引字段结构的对象。
(7)boot.spring.util:包含常用的工具类。
在pom.xml中,需要引入相关的依赖:
org.elasticsearch.client elasticsearch-rest-high-level-client 7.9.1 org.elasticsearch elasticsearch 7.9.1 登录后复制
@Configuration public class Client { @Value("${es.url}") private String esUrl; @Bean RestHighLevelClient configRestHighLevelClient() throws Exception { String[] esUrlArr = esUrl.split(","); List httpHosts = new ArrayList(); for(String es : esUrlArr){ String[] esUrlPort = es.split(":"); httpHosts.add(new HttpHost(esUrlPort[0], Integer.parseInt(esUrlPort[1]), "http")); } return new RestHighLevelClient(RestClient.builder(httpHosts.toArray(new HttpHost[0]))); } }登录后复制
图8.1 工程首页
8.2 建立索引并导入数据
本节探讨如何使用Java代码创建索引的映射并写入数据到索引,演示的实例包括四个索引:使用最细粒度分析器进行分词的索引sougoulog、包含经纬度坐标点的索引shop、包含嵌套对象的索引city、包含Join字段的索引cityjoincountry。
8.2.1 创建映射
1.自定义分析器的映射sougoulog
创建sougoulog索引的映射接口在类IndexController中,你可以使用XContentBuilder对象非常优雅地创建json格式的映射,其中关键的代码如下:
@ApiOperation("创建索引sougoulog") @RequestMapping(value="/createIndexMapping",method = RequestMethod.GET) @ResponseBody MSG createMapping() throws Exception{ // 创建sougoulog索引映射 boolean exsit = indexService.existIndex("sougoulog"); if ( exsit == false ) { XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); { …... builder.startObject("analyzer"); { builder.startObject("my_analyzer"); { builder.field("filter", "my_filter"); builder.field("char_filter", ""); builder.field("type", "custom"); builder.field("tokenizer", "my_tokenizer"); } builder.endObject(); } builder.endObject(); …... builder.startObject("keywords"); { builder.field("type", "text"); builder.field("analyzer", "my_analyzer"); builder.startObject("fields"); { builder.startObject("keyword"); { builder.field("type", "keyword"); builder.field("ignore_above", "256"); } builder.endObject(); } builder.endObject(); } builder.endObject(); ...... } builder.endObject(); System.out.println(builder.prettyPrint()); indexService.createMapping("sougoulog", builder); } return new MSG("index success"); }登录后复制
@Override public void createMapping(String indexname, XContentBuilder mapping) { try { CreateIndexRequest index = new CreateIndexRequest(indexname); index.source(mapping); client.indices().create(index, RequestOptions.DEFAULT); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }登录后复制
2.包含经纬度坐标的映射
下面的接口createShopMapping创建了一个名为shop的索引,里面包含一个经纬度坐标字段,其部分代码如下:
@ApiOperation("创建shop索引") @RequestMapping(value="/createShopMapping",method = RequestMethod.GET) @ResponseBody MSG createShopMapping() throws Exception{ // 创建shop索引映射 boolean exsit = indexService.existIndex("shop"); if ( exsit == false ) { XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); { …… builder.startObject("location"); { builder.field("type", "geo_point"); } builder.endObject(); …… } builder.endObject(); System.out.println(builder.prettyPrint()); indexService.createMapping("shop",builder); } return new MSG("index success"); }登录后复制
3.包含嵌套对象的映射
下面的接口createCityMapping创建了一个名为city的索引,它包含一个嵌套对象,用于存放城市所属的国家数据,部分代码如下:
@ApiOperation("创建城市索引") @RequestMapping(value="/createCityMapping",method = RequestMethod.GET) @ResponseBody MSG createCityMapping() throws Exception{ // 创建shop索引映射 boolean exsit=indexService.existIndex("city"); if(exsit==false){ XContentBuilder builder=XContentFactory.jsonBuilder(); builder.startObject(); { …… builder.startObject("country"); { builder.field("type","nested"); builder.startObject("properties"); { …… } …… indexService.createMapping("city",builder); } return new MSG("index success"); } } }登录后复制
接口createJoinMapping创建一个带有join字段的索引cityjoincountry,该索引包含父关系country、子关系city,其创建方法也是类似的:
@ApiOperation("创建一对多关联索引") @RequestMapping(value="/createJoinMapping",method = RequestMethod.GET) @ResponseBody MSG createJoinMapping() throws Exception { // 创建shop索引映射 boolean exsit = indexService.existIndex("cityjoincountry"); if ( exsit == false ) { XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); { …… builder.startObject("joinkey"); { builder.field("type", "join"); builder.startObject("relations"); { builder.field("country", "city"); } builder.endObject(); } builder.endObject(); …… } builder.endObject(); indexService.createMapping("cityjoincountry",builder); } return new MSG("index success"); }登录后复制