官網(wǎng)
https://www.elastic.co/cn/
整合springboot看上一篇文章
版本
一定要對應(yīng)好版本,Elasticsearch 的不同版本變化是真大,
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/
組件版本說明
Springboot: 2.7.10
spring-data-elasticsearch: 4.4.10
spring-boot-starter-data-elasticsearch: 2.7.10
elasticsearch-java: 7.17.9
實現(xiàn)代碼地址
https://github.com/OrderDong/microservice-boot
分支:microservice-boot-1.0.6-es
microservice-boot-eleastic模塊
所有pom.xml引用
<!--elastic search 7.17.9 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!--高版本單獨使用elasticsearch client -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>7.17.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.0.1</version>
</dependency>
<!-- spring-data-elasticsearch 包含此包
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.9</version>
</dependency>-->
<!-- Reactive Infrastructure -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
</dependency>
es Spring Data Repositories
類似于spring data封裝的ORM框架,也可以理解為MVC的M層,當然,完全可以靈活應(yīng)用,也支持rest層
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/#repositories
例子:
//controller
@PostMapping("/saveVisitLog")
@ResponseBody
public String saveVisitLog(@RequestBody VisitLog visitLog){
VisitLog saveVisitLog = visitLogService.saveVisitLog(visitLog);
log.info("----saveVisitLog----:{}", JSON.toJSONString(saveVisitLog));
return JSON.toJSONString(saveVisitLog);
}
@GetMapping("/getVisitLogAll")
@ResponseBody
public String getVisitLogAll(){
List<VisitLog> logList = visitLogService.findAll();
log.info("----getVisitLogAll----:{}", JSON.toJSONString(logList));
return JSON.toJSONString(logList);
}
//service
@Override
public VisitLog saveVisitLog(VisitLog visitLog) {
return visitLogRepository.save(visitLog);
}
@Override
public List<VisitLog> findAll() {
Iterable<VisitLog> visitLogs = visitLogRepository.findAll();
List<VisitLog> logs = new ArrayList<>();
visitLogs.forEach(visitLog -> logs.add(visitLog));
return logs;
}
//dao層
@Repository
public interface VisitLogRepository extends ElasticsearchRepository<VisitLog, String> {
}
ElasticsearchRepository分析
CrudRepository最終繼承了這個對象,這個對象被按照規(guī)則封裝實現(xiàn)了具體的操作
我們可以看下ElasticsearchRepository實現(xiàn)了哪些方法:
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
es Spring Data Repositories 關(guān)鍵字
spring data封裝的ORM框架,很多接口繼承的方法,也可以自定義方法,需要按照封裝的規(guī)則自定義
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/#repositories.definition
例子:
//controller
//自定義查詢
@GetMapping("/getVisitLogByUserLoginId")
@ResponseBody
public String getVisitLogByUserLoginId(Integer userLoginId){
List<VisitLog> logList = visitLogService.findByUserLoginId(userLoginId);
log.info("----getVisitLogAll----:{}", JSON.toJSONString(logList));
return JSON.toJSONString(logList);
}
//service impl
@Override
public List<VisitLog> findByUserLoginId(Integer userLoginId) {
return visitLogRepository.findByUserLoginId(userLoginId);
}
//
@Repository
public interface VisitLogRepository extends ElasticsearchRepository<VisitLog, String> {
//自定義規(guī)則,By--關(guān)鍵字,UserLoginId字段,翻譯下,就是查詢-find 通過--By 字段--UserLoginId
//spring data repository會去解析,同樣的方式自行查reference文檔
List<VisitLog> findByUserLoginId(Integer userLoginId);
}
es Spring Data Repositories client 加載
當然,一般使用封裝好的也有一定的麻煩事情,也可以自己加載客戶端,使用spring data repository 加載,兩種方式,但是7.17的版本把這種方式去掉了,
https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/#elasticsearch.clients
rest風格客戶端
The Java High Level REST Clientis the default client of Elasticsearch,it is configured likes hown:
package org.lwd.microservice.boot.es.config;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
/**
* rest風格客戶端
* The Java High Level REST Client is the default client of Elasticsearch, it is configured like shown:
*
* @author weidong
* @version V1.0.0
* @since 2023/7/27
*/
@Configuration
public class EsRestHighLevelClientConfig extends AbstractElasticsearchConfiguration {
@Value("${spring.elasticsearch.uris}")
private String uris;
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(uris)
.build();
return RestClients.create(clientConfiguration).rest();
}
}
我們看下,那個bean可用(猜測一定被封裝好了),AbstractElasticsearchConfiguration
public abstract class AbstractElasticsearchConfiguration extends ElasticsearchConfigurationSupport {
/**
* Return the {@link RestHighLevelClient} instance used to connect to the cluster. <br />
*
* @return never {@literal null}.
*/
@Bean
public abstract RestHighLevelClient elasticsearchClient();
/**
* Creates {@link ElasticsearchOperations}.
*
* @return never {@literal null}.
*/
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter,
RestHighLevelClient elasticsearchClient) {
ElasticsearchRestTemplate template = new ElasticsearchRestTemplate(elasticsearchClient, elasticsearchConverter);
template.setRefreshPolicy(refreshPolicy());
return template;
}
}
不知道各位發(fā)現(xiàn)沒:@Bean(name = { “elasticsearchOperations”, “elasticsearchTemplate” })
用這個bean去操作
直接執(zhí)行dsl例子
//rest模版操作
@Autowired
ElasticsearchOperations elasticsearchOperations;
//rest客戶端模版
@GetMapping("/getHighTempt")
@ResponseBody
public String getHighTempt(){
Query query = new StringQuery("{ \"match\": { \"userLoginId\": 1 } } ");
query.setPageable(PageRequest.of(0, 10));
SearchHits<VisitLog> searchHits = elasticsearchOperations.search(query,VisitLog.class);
return JSON.toJSONString(searchHits);
}
響應(yīng)式客戶端-ReactiveElasticsearchClient
- The ReactiveElasticsearchClient is a non official driver based on WebClient.
- It uses the request/response objects provided by the Elasticsearch core project.
- Calls are directly operated on the reactive stack, not wrapping async (thread pool bound) responses into reactive types.
如果不知道什么是響應(yīng)式,自行百度
pom.xml
<!-- Reactive Infrastructure -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
</dependency>
例子
package org.lwd.microservice.boot.es.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.client.reactive.ReactiveRestClients;
import org.springframework.data.elasticsearch.config.AbstractReactiveElasticsearchConfiguration;
/**
* 響應(yīng)式客戶端
* The ReactiveElasticsearchClient is a non official driver based on WebClient.
* It uses the request/response objects provided by the Elasticsearch core project.
* Calls are directly operated on the reactive stack, not wrapping async (thread pool bound) responses into reactive types.
*
* @author weidong
* @version V1.0.0
* @since 2023/7/28
*/
@Configuration
public class EsReactiveRestClientConfig extends AbstractReactiveElasticsearchConfiguration {
@Value("${spring.elasticsearch.uris}")
private String uris;
@Bean
@Override
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(uris) //
.build();
return ReactiveRestClients.create(clientConfiguration);
}
}
//響應(yīng)式模版操作
@Autowired
ReactiveElasticsearchOperations reactiveElasticsearchOperations;
//響應(yīng)式客戶端
@GetMapping("/getReactiveTemp")
@ResponseBody
public String getReactiveTemp(){
Query query = new StringQuery("{ \"match\": { \"userLoginId\": 1 } } ");
query.setPageable(PageRequest.of(0, 10));
Flux<SearchHit<VisitLog>> result = reactiveElasticsearchOperations.search(query,VisitLog.class);
return JSON.toJSONString(result);
}
ES 原生方式加載客戶端
從 ElasticSearch7.17 這個版本開始,原先的 Java 高級客戶端
Java High Level REST Client 廢棄了,不支持了。老實說,ElasticSearch 算是我用過的所有 Java 工具中,更新最為激進的一個了,在 Es7 中廢棄了 TransportClient,7.17 又廢棄了 TransportClient,那么現(xiàn)在用啥呢?現(xiàn)在的客戶端叫做 Elasticsearch Java API Client。
Elasticsearch Java API Client 具有如下特性:
為所有 Elasticsearch APIs 提供強類型的請求和響應(yīng)。
所有 API 都有阻塞和異步版本。
使用構(gòu)建器模式,在創(chuàng)建復(fù)雜的嵌套結(jié)構(gòu)時,可以編寫簡潔而可讀的代碼。
通過使用對象映射器(如 Jackson 或任何實現(xiàn)了 JSON-B 的解析器),實現(xiàn)應(yīng)用程序類的無縫集成。
將協(xié)議處理委托給一個 http 客戶端,如 Java Low Level REST Client,它負責所有傳輸級的問題。HTTP 連接池、重試、節(jié)點發(fā)現(xiàn)等等由它去完成。
關(guān)于第三點,松哥吐槽一句,確實簡潔,但是可讀性一般般吧。
另外還有兩點需要注意:
Elasticsearch Java 客戶端是向前兼容的,即該客戶端支持與 Elasticsearch 的更大或相等的次要版本進行通信。
Elasticsearch Java 客戶端只向后兼容默認的發(fā)行版本,并且沒有做出保證。
pom.xml
<!--高版本單獨使用elasticsearch client -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>7.17.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.0.1</version>
</dependency>
加載原生客戶端
注意下,一定要用原生elasticsearch-java jar中的類文章來源:http://www.zghlxwxcb.cn/news/detail-622075.html
package org.lwd.microservice.boot.es.config;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 使用elasticsearch client 7.17.9
*
* @author weidong
* @version V1.0.0
* @since 2023/7/31
*/
@Configuration
public class EsRestClientConfig {
@Value("${spring.elasticsearch.uris}")
private String uris;
@Bean
public ElasticsearchClient initSyncRestClient() {
RestClient restClient = RestClient.builder(HttpHost.create(uris)).build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
return client;
}
}
controller使用
@Autowired
ElasticsearchClient elasticsearchClient;
//elasticsearch client 7.17.9
@GetMapping("/getRestTemp")
@ResponseBody
public String getRestTemp(){
StringReader sr = new StringReader(
"{\n" +
" \"query\": { \"match\": {\n" +
" \"userLoginId\": \"1\"\n" +
" }}" +
"}"
);
//查詢所有
/* StringReader sr = new StringReader(
"{\n" +
" \"query\": {\n" +
" \"match_all\" : {}\n" +
" }\n" +
"}\n"
);*/
SearchRequest request = new SearchRequest.Builder().index(Arrays.asList(new String[]{"visit_log"}))
.withJson(sr)
.build();
try {
SearchResponse<VisitLog> search = elasticsearchClient.search(request,VisitLog.class);
System.out.println("search.toString() = " + search.toString());
long took = search.took();
System.out.println("took = " + took);
boolean b = search.timedOut();
System.out.println("b = " + b);
ShardStatistics shards = search.shards();
System.out.println("shards = " + shards);
HitsMetadata<VisitLog> hits = search.hits();
TotalHits total = hits.total();
System.out.println("total = " + total);
Double maxScore = hits.maxScore();
System.out.println("maxScore = " + maxScore);
List<Hit<VisitLog>> list = hits.hits();
for (Hit<VisitLog> visitLogHit : list) {
System.out.println("visitLogHit.source() = " + JSON.toJSONString(visitLogHit.source()));
System.out.println("visitLogHit.score() = " + visitLogHit.score());
System.out.println("visitLogHit.index() = " + visitLogHit.index());
}
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
可以看到,直接把查詢的 JSON 參數(shù)傳進來也是可以的。這樣我們就可以先在 Kibana 中寫好腳本,然后直接將腳本拷貝到 Java 代碼中來執(zhí)行就行了。文章來源地址http://www.zghlxwxcb.cn/news/detail-622075.html
驗證結(jié)果
request [POST http://10.255.20.231:9200/visit_log/_search?typed_keys=true] returned 1 warnings: [299 Elasticsearch-7.17.9-ef48222227ee6b9e70e502f0f0daa52435ee634d "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html to enable security."]
search.toString() = SearchResponse: {"took":0,"timed_out":false,"_shards":{"failed":0.0,"successful":1.0,"total":1.0,"skipped":0.0},"hits":{"total":{"relation":"eq","value":1},"hits":[{"_index":"visit_log","_id":"2","_score":0.9808291,"_type":"_doc","_source":"org.lwd.microservice.boot.es.entity.VisitLog@1bbbdce9"}],"max_score":0.9808291}}
took = 0
b = false
shards = ShardStatistics: {"failed":0.0,"successful":1.0,"total":1.0,"skipped":0.0}
total = TotalHits: {"relation":"eq","value":1}
maxScore = 0.9808291
visitLogHit.source() = {"_class":"org.lwd.microservice.boot.es.entity.VisitLog","createTime":"2023-07-27 16:34:36","id":2,"initialRequest":"http://localhost:8023","msgContent":"test es add2","serverHostName":"weidong","serverIpAddress":"127.0.0.1","tableName":"VisitLog","userLoginId":"1"}
visitLogHit.score() = 0.9808291
visitLogHit.index() = visit_log
測試請求http文件-TestEs.http
## 新增日志
POST http://localhost:8023/es/saveVisitLog
Content-Type: application/json
{
"id": 3,
"tableName": "VisitLog",
"userLoginId": 3,
"serverIpAddress": "127.0.0.1",
"serverHostName": "weidong",
"initialRequest": "http://localhost:8023",
"msgContent": "test es add3",
"createTime": "2023-07-27 16:34:36"
}
### 獲取所有數(shù)據(jù)-不分頁
GET http://localhost:8023/es/getVisitLogAll
### 獲取所有數(shù)據(jù)-自定義查詢規(guī)則
GET http://localhost:8023/es/getVisitLogByUserLoginId?userLoginId=1
### 獲取所有數(shù)據(jù)-high rest
GET http://localhost:8023/es/getHighTempt
### 獲取所有數(shù)據(jù)-reactive rest
GET http://localhost:8023/es/getReactiveTemp
### 獲取所有數(shù)據(jù)-elasticsearch client 7.17.9
GET http://localhost:8023/es/getRestTemp
外傳
?? 原創(chuàng)不易,如若本文能夠幫助到您的同學
?? 支持我:關(guān)注我+點贊??+收藏??
?? 留言:探討問題,看到立馬回復(fù)
?? 格言:己所不欲勿施于人 揚帆起航、游歷人生、永不言棄!??
到了這里,關(guān)于Elasticsearch Java客戶端和Spring data elasticsearch-Elasticsearch文章三的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!