最近在学习elasticsearch,因为当前使用的jdk是1.8的,所以安装了elasticsearch 7.17.16版本,安装方法网上教程很多,这里就不介绍了。找了好久的java工具类,没有找到合适的,所以打算自己写一个,参考官方文档,上代码
文档https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/installation.html
工具类使用思路
首先使用kibana创建index并给定mapping
然后使用代码工具类完成初始化导入数据和增删改查
安装
安装 elasticsearch 7.17.16
安装 kibana-7.17.16
安装 elasticsearch-analysis-ik
导包
<!-- https://mvnrepository.com/artifact/co.elastic.clients/elasticsearch-java -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>7.17.16</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
有 java.lang.NoClassDefFoundError: jakarta/json/JsonException 错误的话,增加导包:
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.0.1</version>
</dependency>
有java.lang.NoSuchMethodError: org.elasticsearch.client.RequestOptions$Builder.removeHeader(Ljava/lang/String;)Lorg/elasticsearch/client/RequestOptions$Builder; 错误的话
<!-- 覆盖springboot维护的版本 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.17.16</version>
</dependency>
书写工具类
定义es字段注解
@Retention(RetentionPolicy.RUNTIME)
public @interface EsField {
boolean isId() default false;
}
定义es类注解
@Retention(RetentionPolicy.RUNTIME)
public @interface EsIndex {
String index();
}
开箱即用,通用工具类
/**
* @author John
* @date 2023/12/18
*/
@SuppressWarnings("ALL")
public class EsClient<T> {
public static ElasticsearchClient elasticsearchClient;
public String index;
public Class obj;
public String idField;
public Set<String> fields;
static {
RestClient restClient = RestClient.builder(new HttpHost("ip", 9200)).build();
//集群引入
//restClient = RestClient.builder(new HttpHost("ip3", 9200),new HttpHost("ip2", 9200)).build();
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
elasticsearchClient = new ElasticsearchClient(transport);
}
public EsClient(Class<T> t) {
this.obj = t;
index = getIndex(obj);
idField = getIdField(obj);
fields = new LinkedHashSet<>();
Field[] classFields = obj.getDeclaredFields();
for (Field field : classFields) {
EsField idColumn = field.getAnnotation(EsField.class);
if (idColumn != null && idColumn.isId()) {
fields.add(field.getName());
if (idColumn.isId()){
idField = field.getName();
}
}
}
}
/**
* 获取索引名称
*
* @param c
* @return
*/
private String getIndex(Class c){
Annotation[] annotations = c.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof EsIndex){
return ((EsIndex) annotation).index().toLowerCase();
}
}
return c.getSimpleName().toLowerCase();
}
/**
* 获取id字段
*
* @return
*/
private String getIdField(Class c){
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
EsField idColumn = field.getAnnotation(EsField.class);
if (idColumn != null && idColumn.isId()) {
return field.getName();
}
}
return null;
}
/**
* 获取id字段
*
* @return
*/
private String getIdValue(T t)throws Exception{
Field field = t.getClass().getDeclaredField(idField);
field.setAccessible(true);
Object object = field.get(t);
return object.toString();
}
/**
* 创建索引
* @throws IOException
*/
public void push(T t) throws Exception {
String id = getIdValue(t);
IndexRequest<T> indexRequest = IndexRequest.of(b -> b
.index(index)
.id(id)
.document(t)
//刷新可以立刻搜索到,消耗性能
/*.refresh(Refresh.True)*/);
elasticsearchClient.index(indexRequest);
}
/**
* 索引信息查询
*
* @throws IOException
*/
public T query(String id) throws IOException {
GetResponse<T> response = elasticsearchClient.get(g -> g
.index(index)
.id(id)
, obj);
if (response.found()) {
return response.source();
}
return null;
}
/**
* query-json查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByQueryJson(int page, int pageSize, String json, SortOptions... sortOptions) throws Exception {
if (StringUtils.isBlank(json)) {
return HitsMetadata.of(h -> h.total(t -> t.relation(TotalHitsRelation.Eq).value(0)).hits(new ArrayList<>()));
}
return queryList(page, pageSize, Query.of(q -> q.withJson(new StringReader(json))), sortOptions);
}
/**
* 完整json查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByJson(String json) throws Exception {
if (StringUtils.isBlank(json)) {
return new HitsMetadata.Builder<T>().total(TotalHits.of(t -> t.value(0))).build();
}
SearchResponse<T> search = elasticsearchClient.search(s -> s
.index(index)
.withJson(new StringReader(json))
, obj);
return search.hits();
}
/**
* 前缀查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByPrefix(int page, int pageSize, String field, String keyword) throws Exception {
return queryList(page, pageSize, Query.of(q -> q.prefix(w -> w.field(field).value(keyword))));
}
/**
* 分词查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByMatch(int page, int pageSize, String field, String keyword) throws Exception {
return queryList(page, pageSize, Query.of(q -> q.match(w -> w.field(field).query(keyword))));
}
/**
* 分词查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByMatch(int page, int pageSize, String field, String keyword, String orderField, boolean isDesc) throws Exception {
return queryList(page, pageSize, Query.of(q -> q.match(w -> w.field(field).query(keyword))),
SortOptions.of(s -> s.field(f -> f.field(orderField).order(isDesc ? SortOrder.Desc : SortOrder.Asc))));
}
/**
* 不分词查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByTerm(int page, int pageSize, String field, String keyword) throws Exception {
return queryList(page, pageSize, Query.of(q -> q.term(w -> w.field(field).value(keyword))));
}
/**
* 不分词查询
*
* @param index
* @param field
* @param keyword
* @return
* @throws Exception
*/
public HitsMetadata<T> queryByTerm(int page, int pageSize, String field, String keyword, String orderField, boolean isDesc) throws Exception {
return queryList(page, pageSize, Query.of(q -> q.term(w -> w.field(field).value(keyword))),
SortOptions.of(s -> s.field(f -> f.field(orderField).order(isDesc ? SortOrder.Desc : SortOrder.Asc))));
}
/**
* 索引信息查询
*
* @throws IOException
*/
public HitsMetadata<T> queryList(int page, int pageSize, Query query, SortOptions... sortOptions) throws IOException {
SearchResponse<T> search = elasticsearchClient.search(
s -> s.index(index)
.query(query)
.sort(Arrays.asList(sortOptions))
.from((page - 1) * pageSize).size(pageSize)
, obj);
return search.hits();
}
/**
* 删除索引
*
* @throws IOException
*/
public boolean del(String id) throws IOException {
DeleteResponse delete = elasticsearchClient.delete(
d -> d.index(index)
.id(id));
Result result = delete.result();
return "deleted".equals(result.jsonValue()) | "not_found".equals(result.jsonValue());
}
/**
* 批量
*
* @throws IOException
*/
public Map<String, String> batchDel(Set<String> ids) throws Exception {
BulkRequest.Builder br = new BulkRequest.Builder();
for (String id : ids) {
br.operations(op -> op.delete(d -> d.index(index).id(id)));
}
return requestBulk(br);
}
/**
* 批量
*
* @throws IOException
*/
public Map<String, String> batchAdd(List<T> list) throws Exception {
BulkRequest.Builder br = new BulkRequest.Builder();
for (T t : list) {
String idValue = getIdValue(t);
br.operations(op -> op
.index(idx -> idx
.index(index)
.id(idValue)
.document(t)
)
);
}
return requestBulk(br);
}
/**
* 处理批量请求
*
* @param br
* @return
* @throws IOException
*/
private Map<String, String> requestBulk(BulkRequest.Builder br) throws IOException {
//刷新可以立刻搜索到,消耗性能
//br.refresh(Refresh.True);
BulkResponse result = elasticsearchClient.bulk(br.build());
System.out.println(result);
Map<String, String> returnResult = new HashMap<>();
if (result.errors()) {
returnResult = result.items().stream()
.filter(e -> e.error() != null)
.collect(Collectors.toMap(BulkResponseItem::id, b -> b.error().reason()));
}
return returnResult;
}
}
测试使用代码
测试bean
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EsIndex(index = "poster")
public class PosterBean {
@Id
@EsField(isId = true)
public Long id;
@EsField
public Integer categoryId;
@EsField
public String keyword;
public Integer imageCount;
}
测试代码
@Service
@Lazy
public class Test {
/**
*测试查询
*/
public void test() throws Exception {
EsClient<PosterBean> client = new EsClient<>(PosterBean.class);
//写入
PosterBean bean = PosterBean.builder().posterId(1L).categoryI
d(1).keyword("测试").build();
client.push(bean);
//查询单个
PosterBean bean1 = client.query("121");
System.out.println(bean1);
//删除
boolean del = client.del("122");
System.out.println(del);
//批量删除
Set<String> ids = Stream.of("322", "3221", "32221").collect(Collectors.toSet());
Map<String, String> batch = client.batchDel(ids);
System.out.println(batch);
//查询
SortOptions sortOptions = SortOptions.of(s -> s
.field(f -> f
.field("posterid")
.order(SortOrder.Desc)
));
String json = "{\n" +
" \"term\": {\n" +
" \"keyword\": {\n" +
" \"value\": \"年会\"\n" +
" }\n" +
" }\n" +
" }";
HitsMetadata<PosterBean> metadata = client.queryByQueryJson(1, 5, json, sortOptions);
metadata.hits().stream().map(Hit::source).forEach(System.out::println);
//完整json查询
String allJson = "{\n" +
" \"query\": {\n" +
" \"term\": {\n" +
" \"keyword\": {\n" +
" \"value\": \"春节\"\n" +
" }\n" +
" }\n" +
" },\n" +
" \"sort\": [\n" +
" {\n" +
" \"posterid\": {\n" +
" \"order\": \"desc\"\n" +
" }\n" +
" }\n" +
" ], \n" +
" \"from\": 0,\n" +
" \"size\": 20\n" +
"}";
HitsMetadata<PosterBean> metadata1 = client.queryByJson(allJson);
}
}
希望能够帮到大家,有问题可以评论私信