elasticsearch-java 7.17.16 范型引入通用无侵入工具类

本文介绍如何在使用Java和Elasticsearch7.17.16时自定义工具类,包括安装步骤、依赖管理、索引操作和查询API的实现,以及遇到常见错误的解决方案。
摘要由CSDN通过智能技术生成

最近在学习elasticsearch,因为当前使用的jdk是1.8的,所以安装了elasticsearch 7.17.16版本,安装方法网上教程很多,这里就不介绍了。找了好久的java工具类,没有找到合适的,所以打算自己写一个,参考官方文档,上代码

文档icon-default.png?t=N7T8https://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);
    }
}

希望能够帮到大家,有问题可以评论私信

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值