一、簡(jiǎn)介
在上篇?ElasticSearch?文章中,我們?cè)敿?xì)的介紹了 ElasticSearch 的各種 api 使用。
實(shí)際的項(xiàng)目開(kāi)發(fā)過(guò)程中,我們通常基于某些主流框架平臺(tái)進(jìn)行技術(shù)開(kāi)發(fā),比如 SpringBoot,今天我們就以 SpringBoot 整合 ElasticSearch 為例,給大家詳細(xì)的介紹 ElasticSearch 的使用!
SpringBoot 連接 ElasticSearch,主流的方式有以下四種方式
方式一:通過(guò)Elastic Transport Client客戶端連接 es 服務(wù)器,底層基于 TCP 協(xié)議通過(guò) transport 模塊和遠(yuǎn)程 ES 服務(wù)端通信,不過(guò),從 V7.0 開(kāi)始官方不建議使用,V8.0開(kāi)始正式移除。
方式二:通過(guò)Elastic Java Low Level Rest Client客戶端連接 es 服務(wù)器,底層基于 HTTP 協(xié)議通過(guò) restful API 來(lái)和遠(yuǎn)程 ES 服務(wù)端通信,只提供了最簡(jiǎn)單最基本的 API,類似于上篇文章中給大家介紹的 API 操作邏輯
方式三:通過(guò)Elastic Java High Level Rest Client客戶端連接 es 服務(wù)器,底層基于Elastic Java Low Level Rest Client客戶端做了一層封裝,提供了更高級(jí)得 API 且和Elastic Transport Client接口及參數(shù)保持一致,官方推薦的 es 客戶端。
方式四:通過(guò)JestClient客戶端連接 es 服務(wù)器,這是開(kāi)源社區(qū)基于 HTTP 協(xié)議開(kāi)發(fā)的一款 es 客戶端,官方宣稱接口及代碼設(shè)計(jì)比 ES 官方提供的 Rest 客戶端更簡(jiǎn)潔、更合理,更好用,具有一定的 ES 服務(wù)端版本兼容性,但是更新速度不是很快,目前 ES 版本已經(jīng)出到 V7.9,但是JestClient只支持 V1.0~V6.X 版 ?本的 ES。
還有一個(gè)需要大家注意的地方,那就是版本號(hào)的兼容!
在開(kāi)發(fā)過(guò)程中,大家尤其需要關(guān)注一下客戶端和服務(wù)端的版本號(hào),要盡可能保持一致,比如服務(wù)端 es 的版本號(hào)是6.8.2,那么連接 es 的客戶端版本號(hào),最好也是6.8.2,即使因項(xiàng)目的原因不能保持一致,客戶端的版本號(hào)必須在6.0.0 ~6.8.2,不要超過(guò)服務(wù)器的版本號(hào),這樣客戶端才能保持正常工作,否則會(huì)出現(xiàn)很多意想不到的問(wèn)題,假如客戶端是7.0.4的版本號(hào),此時(shí)的程序會(huì)各種報(bào)錯(cuò),甚至沒(méi)辦法用!
為什么要這樣做呢?主要原因就是 es 的服務(wù)端,高版本不兼容低版本;es6 和 es7 的某些 API 請(qǐng)求參數(shù)結(jié)構(gòu)有著很大的區(qū)別,所以客戶端和服務(wù)端版本號(hào)盡量保持一致。
廢話也不多說(shuō)了,直接上代碼!
二、代碼實(shí)踐
本文采用的SpringBoot版本號(hào)是2.1.0.RELEASE,服務(wù)端 es 的版本號(hào)是6.8.2,客戶端采用的是官方推薦的Elastic Java High Level Rest Client版本號(hào)是6.4.2,方便與SpringBoot的版本兼容。
2.1、導(dǎo)入依賴
<!--elasticsearch-->
<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>6.4.2</version>
</dependency>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>6.4.2</version>
</dependency>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>6.4.2</version>
</dependency>
2.2、配置環(huán)境變量
在application.properties全局配置文件中,配置elasticsearch自定義環(huán)境變量
elasticsearch.scheme=http
elasticsearch.address=127.0.0.1:9200
elasticsearch.userName=
elasticsearch.userPwd=
elasticsearch.socketTimeout=5000
elasticsearch.connectTimeout=5000
elasticsearch.connectionRequestTimeout=5000
2.3、創(chuàng)建 elasticsearch 的 config 類
@Configuration
public?class?ElasticsearchConfiguration?{private?static?final?Logger?log?=?LoggerFactory.getLogger(ElasticsearchConfiguration.class);private?static?final?int?ADDRESS_LENGTH?=?2;@Value("${elasticsearch.scheme:http}")private?String?scheme;@Value("${elasticsearch.address}")private?String?address;@Value("${elasticsearch.userName}")private?String?userName;@Value("${elasticsearch.userPwd}")private?String?userPwd;@Value("${elasticsearch.socketTimeout:5000}")private?Integer?socketTimeout;@Value("${elasticsearch.connectTimeout:5000}")private?Integer?connectTimeout;@Value("${elasticsearch.connectionRequestTimeout:5000}")private?Integer?connectionRequestTimeout;/***?初始化客戶端*?@return*/@Bean(name?=?"restHighLevelClient")public?RestHighLevelClient?restClientBuilder()?{HttpHost[]?hosts?=?Arrays.stream(address.split(",")).map(this::buildHttpHost).filter(Objects::nonNull).toArray(HttpHost[]::new);RestClientBuilder?restClientBuilder?=?RestClient.builder(hosts);//?異步參數(shù)配置restClientBuilder.setHttpClientConfigCallback(httpClientBuilder?->?{httpClientBuilder.setDefaultCredentialsProvider(buildCredentialsProvider());return?httpClientBuilder;});//?異步連接延時(shí)配置restClientBuilder.setRequestConfigCallback(requestConfigBuilder?->?{requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeout);requestConfigBuilder.setSocketTimeout(socketTimeout);requestConfigBuilder.setConnectTimeout(connectTimeout);return?requestConfigBuilder;});return?new?RestHighLevelClient(restClientBuilder);}/***?根據(jù)配置創(chuàng)建HttpHost*?@param?s*?@return*/private?HttpHost?buildHttpHost(String?s)?{String[]?address?=?s.split(":");if?(address.length?==?ADDRESS_LENGTH)?{String?ip?=?address[0];int?port?=?Integer.parseInt(address[1]);return?new?HttpHost(ip,?port,?scheme);}?else?{return?null;}}/***?構(gòu)建認(rèn)證服務(wù)*?@return*/private?CredentialsProvider?buildCredentialsProvider(){final?CredentialsProvider?credentialsProvider?=?new?BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,?new?UsernamePasswordCredentials(userName,userPwd));return?credentialsProvider;}
}
至此,客戶端配置完畢,項(xiàng)目啟動(dòng)的時(shí)候,會(huì)自動(dòng)注入到Spring的ioc容器里面。
2.4、索引管理
es 中最重要的就是索引庫(kù),客戶端如何創(chuàng)建呢?請(qǐng)看下文!
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?創(chuàng)建索引(簡(jiǎn)單模式)*?@throws?IOException*/@Testpublic?void?createIndex()?throws?IOException?{CreateIndexRequest?request?=?new?CreateIndexRequest("cs_index");CreateIndexResponse?response?=?client.indices().create(request,?RequestOptions.DEFAULT);System.out.println(response.isAcknowledged());}/***?創(chuàng)建索引(復(fù)雜模式)*?可以直接把對(duì)應(yīng)的文檔結(jié)構(gòu)也一并初始化*?@throws?IOException*/@Testpublic?void?createIndexComplete()?throws?IOException?{CreateIndexRequest?request?=?new?CreateIndexRequest();//索引名稱request.index("cs_index");//索引配置Settings?settings?=?Settings.builder().put("index.number_of_shards",?3).put("index.number_of_replicas",?1).build();request.settings(settings);//映射結(jié)構(gòu)字段Map<String,?Object>?properties?=?new?HashMap();properties.put("id",?ImmutableBiMap.of("type",?"text"));properties.put("name",?ImmutableBiMap.of("type",?"text"));properties.put("sex",?ImmutableBiMap.of("type",?"text"));properties.put("age",?ImmutableBiMap.of("type",?"long"));properties.put("city",?ImmutableBiMap.of("type",?"text"));properties.put("createTime",?ImmutableBiMap.of("type",?"long"));Map<String,?Object>?mapping?=?new?HashMap<>();mapping.put("properties",?properties);//添加一個(gè)默認(rèn)類型System.out.println(JSON.toJSONString(request));request.mapping("_doc",mapping);CreateIndexResponse?response?=?client.indices().create(request,?RequestOptions.DEFAULT);System.out.println(response.isAcknowledged());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?刪除索引*?@throws?IOException*/@Testpublic?void?deleteIndex()?throws?IOException?{DeleteIndexRequest?request?=?new?DeleteIndexRequest("cs_index1");AcknowledgedResponse?response?=?client.indices().delete(request,?RequestOptions.DEFAULT);System.out.println(response.isAcknowledged());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?查詢索引*?@throws?IOException*/@Testpublic?void?getIndex()?throws?IOException?{//?創(chuàng)建請(qǐng)求GetIndexRequest?request?=?new?GetIndexRequest();request.indices("cs_index");//?執(zhí)行請(qǐng)求,獲取響應(yīng)GetIndexResponse?response?=?client.indices().get(request,?RequestOptions.DEFAULT);System.out.println(response.toString());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?檢查索引是否存在*?@throws?IOException*/@Testpublic?void?exists()?throws?IOException?{//?創(chuàng)建請(qǐng)求GetIndexRequest?request?=?new?GetIndexRequest();request.indices("cs_index");//?執(zhí)行請(qǐng)求,獲取響應(yīng)boolean?response?=?client.indices().exists(request,?RequestOptions.DEFAULT);System.out.println(response);}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?查詢所有的索引名稱*?@throws?IOException*/@Testpublic?void?getAllIndices()?throws?IOException?{GetAliasesRequest?request?=?new?GetAliasesRequest();GetAliasesResponse?response?=??client.indices().getAlias(request,RequestOptions.DEFAULT);Map<String,?Set<AliasMetaData>>?map?=?response.getAliases();Set<String>?indices?=?map.keySet();for?(String?key?:?indices)?{System.out.println(key);}}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?查詢索引映射字段*?@throws?IOException*/@Testpublic?void?getMapping()?throws?IOException?{GetMappingsRequest?request?=?new?GetMappingsRequest();request.indices("cs_index");request.types("_doc");GetMappingsResponse?response?=?client.indices().getMapping(request,?RequestOptions.DEFAULT);System.out.println(response.toString());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?IndexJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?添加索引映射字段*?@throws?IOException*/@Testpublic?void?addMapping()?throws?IOException?{PutMappingRequest?request?=?new?PutMappingRequest();request.indices("cs_index");request.type("_doc");//添加字段Map<String,?Object>?properties?=?new?HashMap();properties.put("accountName",?ImmutableBiMap.of("type",?"keyword"));Map<String,?Object>?mapping?=?new?HashMap<>();mapping.put("properties",?properties);request.source(mapping);PutMappingResponse?response?=?client.indices().putMapping(request,?RequestOptions.DEFAULT);System.out.println(response.isAcknowledged());}}
2.5、文檔管理
所謂文檔,就是向索引里面添加數(shù)據(jù),方便進(jìn)行數(shù)據(jù)查詢,詳細(xì)操作內(nèi)容,請(qǐng)看下文!
public?class?UserDocument?{private?String?id;private?String?name;private?String?sex;private?Integer?age;private?String?city;private?Date?createTime;//省略get、set...
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?DocJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?添加文檔*?@throws?IOException*/@Testpublic?void?addDocument()?throws?IOException?{//?創(chuàng)建對(duì)象UserDocument?user?=?new?UserDocument();user.setId("1");user.setName("里斯");user.setCity("武漢");user.setSex("男");user.setAge(20);user.setCreateTime(new?Date());//?創(chuàng)建索引,即獲取索引IndexRequest?request?=?new?IndexRequest();//?外層參數(shù)request.id("1");request.index("cs_index");request.type("_doc");request.timeout(TimeValue.timeValueSeconds(1));//?存入對(duì)象request.source(JSON.toJSONString(user),?XContentType.JSON);//?發(fā)送請(qǐng)求System.out.println(request.toString());IndexResponse?response?=?client.index(request,?RequestOptions.DEFAULT);System.out.println(response.toString());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?DocJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?更新文檔(按需修改)*?@throws?IOException*/@Testpublic?void?updateDocument()?throws?IOException?{//?創(chuàng)建對(duì)象UserDocument?user?=?new?UserDocument();user.setId("2");user.setName("程咬金");user.setCreateTime(new?Date());//?創(chuàng)建索引,即獲取索引UpdateRequest?request?=?new?UpdateRequest();//?外層參數(shù)request.id("2");request.index("cs_index");request.type("_doc");request.timeout(TimeValue.timeValueSeconds(1));//?存入對(duì)象request.doc(JSON.toJSONString(user),?XContentType.JSON);//?發(fā)送請(qǐng)求System.out.println(request.toString());UpdateResponse?response?=?client.update(request,?RequestOptions.DEFAULT);System.out.println(response.toString());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?DocJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?刪除文檔*?@throws?IOException*/@Testpublic?void?deleteDocument()?throws?IOException?{//?創(chuàng)建索引,即獲取索引DeleteRequest?request?=?new?DeleteRequest();//?外層參數(shù)request.id("1");request.index("cs_index");request.type("_doc");request.timeout(TimeValue.timeValueSeconds(1));//?發(fā)送請(qǐng)求System.out.println(request.toString());DeleteResponse?response?=?client.delete(request,?RequestOptions.DEFAULT);System.out.println(response.toString());}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?DocJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?查詢文檔是不是存在*?@throws?IOException*/@Testpublic?void?exists()?throws?IOException?{//?創(chuàng)建索引,即獲取索引GetRequest?request?=?new?GetRequest();//?外層參數(shù)request.id("3");request.index("cs_index");request.type("_doc");//?發(fā)送請(qǐng)求System.out.println(request.toString());boolean?response?=?client.exists(request,?RequestOptions.DEFAULT);System.out.println(response);}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?DocJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?通過(guò)ID,查詢指定文檔*?@throws?IOException*/@Testpublic?void?getById()?throws?IOException?{//?創(chuàng)建索引,即獲取索引GetRequest?request?=?new?GetRequest();//?外層參數(shù)request.id("1");request.index("cs_index");request.type("_doc");//?發(fā)送請(qǐng)求System.out.println(request.toString());GetResponse?response?=?client.get(request,?RequestOptions.DEFAULT);System.out.println(response.toString());}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes?=?ElasticSearchApplication.class)
public?class?DocJunit?{@Autowiredprivate?RestHighLevelClient?client;/***?批量添加文檔*?@throws?IOException*/@Testpublic?void?batchAddDocument()?throws?IOException?{//?批量請(qǐng)求BulkRequest?bulkRequest?=?new?BulkRequest();bulkRequest.timeout(TimeValue.timeValueSeconds(10));//?創(chuàng)建對(duì)象List<UserDocument>?userArrayList?=?new?ArrayList<>();userArrayList.add(new?UserDocument("張三",?"男",?30,?"武漢"));userArrayList.add(new?UserDocument("里斯",?"女",?31,?"北京"));userArrayList.add(new?UserDocument("王五",?"男",?32,?"武漢"));userArrayList.add(new?UserDocument("趙六",?"女",?33,?"長(zhǎng)沙"));userArrayList.add(new?UserDocument("七七",?"男",?34,?"武漢"));//?添加請(qǐng)求for?(int?i?=?0;?i?<?userArrayList.size();?i++)?{userArrayList.get(i).setId(String.valueOf(i));IndexRequest?indexRequest?=?new?IndexRequest();//?外層參數(shù)indexRequest.id(String.valueOf(i));indexRequest.index("cs_index");indexRequest.type("_doc");indexRequest.timeout(TimeValue.timeValueSeconds(1));indexRequest.source(JSON.toJSONString(userArrayList.get(i)),?XContentType.JSON);bulkRequest.add(indexRequest);}//?執(zhí)行請(qǐng)求BulkResponse?response?=?client.bulk(bulkRequest,?RequestOptions.DEFAULT);System.out.println(response.status());}}
三、小結(jié)
本文主要圍繞 SpringBoot 整合 ElasticSearch 接受數(shù)據(jù)的插入和搜索使用技巧,在實(shí)際的使用過(guò)程中,版本號(hào)尤其的重要,不同版本的 es,對(duì)應(yīng)的 api 是不一樣的。
總結(jié)
以上是生活随笔 為你收集整理的SpringBoot 整合 Elasticsearch 实现海量级数据搜索 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。