SpringBoot?整合?Elasticsearch?實(shí)現(xiàn)海量級(jí)數(shù)據(jù)搜索功能
今天給大家講講 SpringBoot 框架 整合 Elasticsearch 實(shí)現(xiàn)海量級(jí)數(shù)據(jù)搜索。
一、簡(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 操作邏輯Elastic Java High Level Rest Client Elastic Java Low Level Rest Client Elastic Transport Client
方式四:通過(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)看下文!
創(chuàng)建索引
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class IndexJunit {
@Autowired
private RestHighLevelClient client;
/**
* 創(chuàng)建索引(簡(jiǎn)單模式)
* @throws IOException
*/
@Test
public 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
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 刪除索引
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 查詢索引
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 檢查索引是否存在
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 查詢所有的索引名稱
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 查詢索引映射字段
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 添加索引映射字段
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 添加文檔
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 更新文檔(按需修改)
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 刪除文檔
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 查詢文檔是不是存在
* @throws IOException
*/
@Test
public 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);
}
}
通過(guò) ID 查詢指定文檔
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class DocJunit {
@Autowired
private RestHighLevelClient client;
/**
* 通過(guò)ID,查詢指定文檔
* @throws IOException
*/
@Test
public 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 {
@Autowired
private RestHighLevelClient client;
/**
* 批量添加文檔
* @throws IOException
*/
@Test
public 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 是不一樣的。
到此這篇關(guān)于SpringBoot 整合 Elasticsearch 實(shí)現(xiàn)海量級(jí)數(shù)據(jù)搜索的文章就介紹到這了,更多相關(guān)SpringBoot 整合 Elasticsearch 數(shù)據(jù)搜索內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot通過(guò)yml和xml文件配置日志輸出方法
這篇文章主要介紹了SpringBoot通過(guò)yml和xml文件配置日志輸出方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04
Java實(shí)現(xiàn)簡(jiǎn)單井字棋小游戲代碼實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單井字棋小游戲代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
使用Spring的JAVA Mail支持簡(jiǎn)化郵件發(fā)送功能
這篇文章主要為大家詳細(xì)介紹了使用Spring的JAVA Mail支持簡(jiǎn)化郵件發(fā)送功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04
SpringBoot報(bào)錯(cuò)Invalid?bound?statement?(not?found)問(wèn)題排查和解決方案
這篇文章主要介紹了SpringBoot報(bào)錯(cuò)Invalid?bound?statement?(not?found)問(wèn)題排查和解決方案,文中通過(guò)圖文結(jié)合的方式講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03
Mybatis-Plus實(shí)現(xiàn)公共字段自動(dòng)賦值的方法
這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)公共字段自動(dòng)賦值的方法,涉及到通用字段自動(dòng)填充的最佳實(shí)踐總結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
Spring Boot Thymeleaf實(shí)現(xiàn)國(guó)際化的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring Boot Thymeleaf實(shí)現(xiàn)國(guó)際化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
解析Mybatis連續(xù)傳遞多個(gè)參數(shù)的方法
MyBatis是一個(gè)支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射的優(yōu)秀持久層框架,這篇文章主要介紹了Mybatis連續(xù)傳遞多個(gè)參數(shù)的方法,需要的朋友可以參考下2016-08-08
springsecurity第三方授權(quán)認(rèn)證的項(xiàng)目實(shí)踐
Spring security 是一個(gè)強(qiáng)大的和高度可定制的身份驗(yàn)證和訪問(wèn)控制框架,本文主要介紹了springsecurity第三方授權(quán)認(rèn)證的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣可以了解一下2023-08-08
Java直接輸出對(duì)象變成@.....的問(wèn)題及解決
這篇文章主要介紹了Java直接輸出對(duì)象變成@.....的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
SWT(JFace)體驗(yàn)之FormLayout布局
SWT(JFace)體驗(yàn)之FormLayout布局示例代碼。2009-06-06

