前沿
elasticsearch-rest-high-level-client在 7.15.0 中已弃用。
不推荐使用高级 REST 客户端,取而代之的是 Java API 客户端 。
spring-boot-starter-data-elasticsearch 也不推荐,虽然基础操作简化了很多,但是一旦使用了es高级特性,那么就如同进入了地狱,同时elasticsearch更新太快了spring-boot-starter-data-elasticsearch的版本根本就赶不上,导致升级会出现很多问题
现在在es官网推荐我们现在使用 Elasticsearch Java API 客户端
这个是相当于直接使用elasticsearch自身的接口Api所以不存在升级不兼容的问题
Java API 客户端官网地址
elasticsearch Api 操作大全 rest-api
需要的Maven
官网推荐依赖
经过各种的依赖冲突的解决,终于能跑起来了…
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.1.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</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>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
创建客户端
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200)).build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
//es 客户端
ElasticsearchClient client = new ElasticsearchClient(transport);
创建索引和映射分片等…
官方文档没有关于怎么设置映射和索引的配置的,自能自己研究,经过千辛万苦看底层源代码(一点注释都没有),了解代码编写的逻辑,经过我不懈的努力终于实现了以下的基础配置,其他的高级配置可以进行参考下配置进行扩展
//构建索引,并且起一个别名
CreateIndexResponse createResponse = client.indices()
.create(c -> c
.index("my-index") //创索引
.aliases("main-index", a -> a //创别名
.isWriteIndex(true)
)
// 映射字段属性
.mappings((m)-> m
.properties("name",Property.of(p->p.text(TextProperty.of(p1->p1.analyzer("ik_max_word").searchAnalyzer("ik_smart")))))
.properties("sku" ,Property.of(p->p.text(TextProperty.of(p1->p1.analyzer("ik_max_word").searchAnalyzer("ik_smart")))))
.properties("price",Property.of(p->p.integer(IntegerNumberProperty.of(p1->p1))) )
)
//设置分片 ,numberOfShards分片 ,Replicas副本
.settings((s)->s.numberOfShards("1").numberOfReplicas("2"))
);
System.out.println(createResponse.index());
自己进行二次封装
把官方文档看完后,我只想说一句,真难用, 经过3天的代码封装,基本能解决es的百分之90%的使用场景,代码压缩和简化程度至少优化了50%,同时保留了原有的代码特性, 特殊场景提供了对外客户端自己也可以进行二次开发,特殊的操作需要自己通过es的api接口手动进行修操作,在后端操作es一般就是增删改查数据,以及聚合,高亮等
结构
application.yml
es:
port: 9200
hostname: localhost
alals: true # 是否使用别名的方式访问
注解
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface DocId {
}
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface EsClass {
/**
* 索引: 前缀index + 默认类名( 自动转小写)
* 默认类名可以修改为我们自定义
* @return
*/
String index() default "";
/**
* 别名: 前缀alias + 默认类名( 自动转小写)
*默认类名可以修改为我们自定义
* @return
*/
String alias() default "" ;
/*
* 分片
*/
int shards()default 1;
/**
* 分片副本
* @return
*/
int replicas()default 1;
}
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface Field {
//默认属性名
String name()default "" ;
//数据类型
EsDataType type();
String analyzer()default ""; //分词
String searchAnalyzer()default ""; //搜索分词
}
枚举
不一定都能用,有些可能随着es版本的变化,去掉了,需要啥自行修改
public enum EsDataType {
TEXT("text"),
KEYWORD("keyword"),
FLOAT("float"),
LONG("long"),
INTEGER("integer"),
SHORT("short"),
DOUBLE("double"),
HALF_FLOAT("half_float"),
SCALED_FLOAT("scaled_float"),
BYTE("byte"),
DATE("date"),
BOOLEAN("boolean"),
RANGE("rang"),
BINARY("binary"),
ARRAY("array"),
OBJECT("object"),
NESTED("nested"),
GEO_POINT("geo_point"),
GEO_SHAPE("geo_shape"),
IP("ip"),
COMPLETION("completion"),
TOKEN_COUNT("token_count"),
ATTACHMENT("attachment"),
PERCOLATOR("percolator");
private String type;
EsDataType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
自定义es客户端工具类
package com.es8.utli;
import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.cat.aliases.AliasesRecord;
import co.elastic.clients.elasticsearch.cat.indices.IndicesRecord;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.indices.Alias;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.util.ObjectBuilder;
import com.alibaba.fastjson.JSONObject;
import com.es8.an.DocId;
import com.es8.an.EsClass;
import com.es8.esenum.EsDataType;
import com.obj.objcopy.ObjectCopyUtil;
import com.reflect.ReflectUtil;
import com.string.PatternCommon;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Component
public class Es8Client implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(Es8Client.class);
@Value("${es.port}")
private int prot;
@Value("${es.hostname}")
private String hostname;
@Value("${es.alals}")
private boolean alals;
private ElasticsearchClient client;
private ElasticsearchAsyncClient asyncClient;
private final String indexPrefix = "index-";
private final String aliasPrefix = "alias-";
// 同步客户端
public ElasticsearchClient getClient() {
return client;
}
//异步客户端
public ElasticsearchAsyncClient getAsyncClient() {
return asyncClient;
}
@Override
public void afterPropertiesSet() throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost(hostname, prot)).build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
//es 客户端
this.client = new ElasticsearchClient(transport);
this.asyncClient = new ElasticsearchAsyncClient(transport);
}
/**
* @return 是否成功
* @throws Exception
*/
public <T> boolean createIndexSettingsMappings(Class<T> tClass) throws Exception {
EsClass esClassAnnotation = ReflectUtil.getClassAnnotation(tClass, EsClass.class);
int shards = esClassAnnotation.shards();
int replicas = esClassAnnotation.replicas();
StringBuilder stringBuilder = new StringBuilder("{");
stringBuilder.append(""settings": {n" +
" "number_of_shards": " + shards + ",n" +
" "number_of_replicas": " + replicas + "n" +
" },");
stringBuilder.append(""mappings": {n" +
" "properties": ");
JSONObject jsonObject = new JSONObject();
Map<String, Annotation[]> fieldsAnnotation = ReflectUtil.getFieldsAnnotation(tClass);
for (Map.Entry<String, Annotation[]> stringEntry : fieldsAnnotation.entrySet()) {
String key = stringEntry.getKey();
Annotation[] value = stringEntry.getValue();
for (Annotation annotation1 : value) {
JSONObject jsonObject1 = new JSONObject();
if