pom
< ?xml version = "1.0" encoding = "UTF-8" ?>
< project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >
< modelVersion> 4.0 .0 < /modelVersion>
< parent>
< groupId> org.springframework.boot< /groupId>
< artifactId> spring-boot-starter-parent< /artifactId>
< version> 3.1 .1 < /version>
< relativePath/> < ! -- lookup parent from repository -->
< /parent>
< groupId> com.xxx< /groupId>
< artifactId> elastic< /artifactId>
< version> 0.0 .1-SNAPSHOT< /version>
< name> elastic< /name>
< description> Demo project for Spring Boot< /description>
< properties>
< java.version> 1 7 < /java.version>
< /properties>
< dependencies>
< dependency>
< groupId> org.springframework.boot< /groupId>
< artifactId> spring-boot-starter< /artifactId>
< /dependency>
< dependency>
< groupId> org.springframework.boot< /groupId>
< artifactId> spring-boot-starter-test< /artifactId>
< scope> test< /scope>
< /dependency>
< dependency>
< groupId> org.elasticsearch.plugin< /groupId>
< artifactId> x-pack-sql-jdbc< /artifactId>
< version> 8.7 .1 < /version>
< /dependency>
< dependency>
< groupId> co.elastic.clients< /groupId>
< artifactId> elasticsearch-java< /artifactId>
< version> 8.7 .1 < /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>
< dependency>
< groupId> org.springframework.boot< /groupId>
< artifactId> spring-boot-starter-web< /artifactId>
< version> 3.1 .1 < /version>
< /dependency>
< dependency>
< groupId> org.apache.logging.log4j< /groupId>
< artifactId> log4j-api< /artifactId>
< version> 2.17 .2 < /version>
< /dependency>
< dependency>
< groupId> org.apache.logging.log4j< /groupId>
< artifactId> log4j-core< /artifactId>
< version> 2.17 .2 < /version>
< /dependency>
< dependency>
< groupId> org.projectlombok< /groupId>
< artifactId> lombok< /artifactId>
< version> 1.18 .28 < /version>
< /dependency>
< /dependencies>
< build>
< plugins>
< plugin>
< groupId> org.springframework.boot< /groupId>
< artifactId> spring-boot-maven-plugin< /artifactId>
< /plugin>
< /plugins>
< /build>
< /project>
spring:
elasticsearch:
rest:
enable: true
host: 9b4xxxxxxb829199076e3602b516.us-central1.gcp.cloud.es.io
port: 443
username: elastic
password: 密码
index: indexName
配置ElasticSearchConfig
package com.xxx.elastic.config;
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
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.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
//import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
/**
* es8的Java客户端配置
*/
@Configuration
//@Slf4j
public class ElasticSearchConfig {
@Value( "${spring.elasticsearch.rest.host} " )
private String host ;
@Value( "${spring.elasticsearch.rest.enable} " )
private boolean enable ;
@Value( "${spring.elasticsearch.rest.port} " )
private int port;
@Value( "${spring.elasticsearch.rest.username} " )
private String userName;
@Value( "${spring.elasticsearch.rest.password} " )
private String passWord;
// @Value( "${spring.elasticsearch.rest.crtName} " )
// private String tempCrtName;
private static String crtName;
// @PostConstruct
// private void init ( ) {
// crtName = tempCrtName;
// }
/**
* 解析配置的字符串,转为HttpHost对象数组
*
* @return
*/
private HttpHost toHttpHost ( ) {
HttpHost httpHost = new HttpHost( host, port, "https" ) ;
return httpHost;
}
/**
* 同步客户端
* @return
* @throws Exception
*/
@Bean
public ElasticsearchClient clientBySync( ) throws Exception {
ElasticsearchTransport transport = getElasticsearchTransport( userName, passWord, toHttpHost( )) ;
return new ElasticsearchClient( transport) ;
}
/**
* 异步客户端
* @return
* @throws Exception
*/
@Bean
public ElasticsearchAsyncClient clientByAsync( ) throws Exception {
ElasticsearchTransport transport = getElasticsearchTransport( userName, passWord, toHttpHost( )) ;
return new ElasticsearchAsyncClient( transport) ;
}
/**
* 传输对象
* @return
* @throws Exception
*/
@Bean
public ElasticsearchTransport getTransport( ) throws Exception {
return getElasticsearchTransport( userName, passWord, toHttpHost( )) ;
}
private static SSLContext buildSSLContext ( ) {
ClassPathResource resource = new ClassPathResource( crtName) ;
SSLContext sslContext = null;
try {
CertificateFactory factory = CertificateFactory.getInstance( "X.509" ) ;
Certificate trustedCa;
try ( InputStream is = resource.getInputStream( )) {
trustedCa = factory.generateCertificate( is) ;
}
KeyStore trustStore = KeyStore.getInstance( "pkcs12" ) ;
trustStore.load( null, null) ;
trustStore.setCertificateEntry( "ca" , trustedCa) ;
SSLContextBuilder sslContextBuilder = SSLContexts.custom( )
.loadTrustMaterial( trustStore, null) ;
sslContext = sslContextBuilder.build( ) ;
} catch ( CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException |
KeyManagementException e) {
// log.error( "ES连接认证失败" , e) ;
}
return sslContext;
}
private static ElasticsearchTransport getElasticsearchTransport( String username, String passwd, HttpHost.. . hosts) {
// 账号密码的配置
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider( ) ;
credentialsProvider.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials( username, passwd )) ;
// 自签证书的设置,并且还包含了账号密码
RestClientBuilder.HttpClientConfigCallback callback = httpAsyncClientBuilder -> httpAsyncClientBuilder
// .setSSLContext( buildSSLContext( ))
.setSSLHostnameVerifier( NoopHostnameVerifier.INSTANCE )
.setDefaultCredentialsProvider( credentialsProvider) ;
// 用builder创建RestClient对象
RestClient client = RestClient
.builder( hosts)
.setHttpClientConfigCallback( callback)
.build( ) ;
return new RestClientTransport( client, new JacksonJsonpMapper( )) ;
}
}
import lombok.Data;
/**
* @Date 2023 /7/15 12 :24
*/
@Data
public class User {
private Integer Id;
private String Username;
private String Sex;
private Integer Age;
}
package com.xxx.elastic.config;
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.Result;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.transport.ElasticsearchTransport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class ESController {
@Autowired
private ElasticsearchClient syncClient;
@Autowired
private ElasticsearchAsyncClient asyncClient;
@Autowired
private ElasticsearchTransport transport;
@GetMapping( "/init" )
public void initElastic( ) throws Exception{
//获取索引客户端对象
ElasticsearchIndicesClient indices = syncClient.indices( ) ;
//创建索引 采用构建器的方式构建( 在创建之前需要先判断该索引是否存在)
boolean exists = indices.exists( u -> u.index( "userhahah" )) .value( ) ;
if ( exists) {
System.out.println( "该索引已存在!!" ) ;
} else {
CreateIndexResponse createIndexResponse = indices.create( c -> c.index( "userhahah" )) ;
boolean acknowledged = createIndexResponse.acknowledged( ) ;
System.out.println( acknowledged) ;
}
//查询索引
GetIndexResponse getResponse = indices.get( g -> g.index( "userhahah" )) ;
System.out.println( "查询索引:" +getResponse) ;
//删除索引
DeleteIndexResponse deleteResponse = indices.delete( d -> d.index( "userhahah" )) ;
System.out.println( "删除索引:" +deleteResponse.acknowledged( )) ;
}
// 创建文档
@GetMapping( "/initwd" )
public void initElasticwd( ) throws Exception{
//获取索引客户端对象
ElasticsearchIndicesClient indices = syncClient.indices( ) ;
//创建文档
User user = new User( ) ;
user.setId( 1001 ) ;
user.setUsername( "阿桃" ) ;
user.setSex( "男" ) ;
user.setAge( 26 ) ;
Result result = syncClient.create( c -> c.index( "userhahah" ) .id( "1001" ) .document( user)) .result( ) ;
System.out.println( "创建文档:" +result) ;
//批量创建文档
List< User> users = new ArrayList<> ( ) ; //假设有数据
syncClient.bulk( b -> { //批量创建操作
users.forEach( u -> { //遍历需要创建的数据
b.operations(
o -> o.create( c -> c.index( "userhahah" ) .id( u.getId( ) .toString( )) .document( u))
) ;
} ) ;
return b;
} ) ;
//删除文档
syncClient.delete( d -> d.index( "userhahah" ) .id( "1001" )) ;
//查询文档
HitsMetadata< Object> hits = syncClient.search( s -> {
s.query( q -> q.match(
m -> m.field( "username" ) .query( "阿桃" )
)) ;
return s;
} , Object.class) .hits( ) ;
transport.close( ) ; //同步操作时需要关闭,异步时不需要关闭
}
@GetMapping( "/initAsync" )
public void initAsyncElastic( ) throws Exception{
//获取索引异步客户端对象
ElasticsearchIndicesAsyncClient indices = asyncClient.indices( ) ;
//异步调用无法直接获取操作反馈,只能通过回调进行判断
//情况一
indices.create( c -> c.index( "newUser" )) .whenComplete(
( response,error) -> {
if( null != response) {
System.out.println( response.acknowledged( )) ;
} else {
System.out.println( error) ;
}
}
) ;
//情况二 thenApply中获取过acknowledged以后后续不用再获取了
//thenApply是在创建完成后执行的,在whenComplete之前
indices.create( c -> c.index( "newUser" )) .thenApply( response -> response.acknowledged( ))
.whenComplete(
( response,error) -> {
if( response.equals( true)) {
System.out.println( response) ;
} else {
System.out.println( error) ;
}
}
) ;
}
}
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.GetResponse;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.HighlightField;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient;
import com.xxx.elastic.config.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@SpringBootTest
class ElasticApplicationTests {
@Autowired
private ElasticsearchClient esClient;
@Test
void contextLoads( ) throws IOException {
//获取索引客户端对象
// esClient.indices( ) .create( c -> c
// .index( "products" )
// ) ;
Product product = new Product( "bk-1" , "City-bike" , 123 ) ;
IndexResponse response = esClient.index( i -> i
.index( "products" )
.id( product.getSku( ))
.document( product)
) ;
System.out.println( "Indexed with version " + response.version( )) ;
GetResponse< Product> getresponse = esClient.get( g -> g
.index( "products" )
.id( product.getSku( )) ,
Product.class
) ;
if ( getresponse.found( )) {
Product getproduct = getresponse.source( ) ;
System.out.println( "Product name " + getproduct.getName( )) ;
} else {
System.out.println( "Product not found" ) ;
}
}
@Test
void contextLoa( ) throws IOException {
String searchText = "Updated" ;
SearchResponse< Product> response = esClient.search( s -> s
.index( "products" )
.query( q -> q
.match( t -> t
.field( "name" )
.query( searchText)
)
) ,
Product.class
) ;
// HitsMetadata< Product> hits = response.hits( ) ;
System.out.println( "111" ) ;
}
@Test
void contextLo( ) throws IOException {
esClient.delete( d -> d.index( "products" ) .id( "bk-1" )) ;
}
@Test
void context( ) throws IOException {
Product product = new Product( "bk-1" , "Updated name" , 12356 ) ;
esClient.update( u -> u
.index( "products" )
.id( product.getSku( ))
.doc( product)
, Product.class) ;
}
}