基于elasticsearch-java封装crud

  • template
package com.yitsd.template;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.mapping.*;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.search.Highlight;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.indices.get_mapping.IndexMappingRecord;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.yitsd.annotations.ElasticSearchField;
import com.yitsd.annotations.ElasticSearchIndex;
import com.yitsd.constant.Constants;
import com.yitsd.entity.dto.QueryDto;
import com.yitsd.exception.ElasticSearchException;
import com.yitsd.exception.FieldException;
import com.yitsd.util.StringUtils;
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.Configuration;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.*;
import java.util.stream.Collectors;


@Configuration
public class ElasticSearchTemplate {

    private ElasticsearchClient client;

    @Value("${elastic-search.host}")
    private String host;

    @Value("${elastic-search.port}")
    private String port;

    @Value("${certs.url}")
    private String cert;

    @PostConstruct
    public void init() throws Exception {
        RestClient restClient;
        if (host.equals("82.157.165.116")) {
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials("elastic", "password"));
            Path caCertificatePath = Paths.get(cert);
            CertificateFactory factory =
                    CertificateFactory.getInstance("X.509");
            Certificate trustedCa;
            try (InputStream is = Files.newInputStream(caCertificatePath)) {
                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 sslContext = sslContextBuilder.build();
            RestClientBuilder builder = RestClient.builder(
                            new HttpHost(host, Integer.parseInt(port), "http"))
                    .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setSSLContext(sslContext)
                            .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                            .setDefaultCredentialsProvider(credentialsProvider));
            restClient = builder.build();
            ElasticsearchTransport transport = new RestClientTransport(
                    restClient, new JacksonJsonpMapper());
            client = new ElasticsearchClient(transport);
        } else {
            restClient = RestClient.builder(new HttpHost(Constants.LOCAL_HOST, 9200))
                    .build();
        }
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        this.client = new ElasticsearchClient(transport);
    }


    public List<String> getAllIndex() throws IOException {
        Map<String, IndexMappingRecord> result = this.client.indices().getMapping().result();
        return new ArrayList<>(result.keySet());
    }


    public Boolean indexExists(String index) throws IOException {
        return this.client.indices().exists(req -> req.index(index)).value();
    }

    public Boolean deleteIndex(String index) throws IOException {
        return this.client.indices().delete(req -> req.index(index)).acknowledged();
    }

    public <T> Boolean createIndex(Class<T> clazz) throws IOException {
        ElasticSearchIndex elasticSearchIndex = clazz.getAnnotation(ElasticSearchIndex.class);
        String indexName = elasticSearchIndex.name();
        if (indexExists(indexName)) {
            String msg = "index:" + indexName + " " + "already exists";
            throw new RuntimeException(msg);
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        Map<String, Property> fieldMap = new LinkedHashMap<>();
        for (Field field : declaredFields) {
            ElasticSearchField annotation = field.getAnnotation(ElasticSearchField.class);
            if (annotation == null) {
                continue;
            }
            switch (annotation.type()) {
                case text:
                    doHandleText(fieldMap, field);
                    break;
                case keyword:
                    doHandleKeyword(fieldMap, field);
                    break;
                case long_:
                    doHandleLong_(fieldMap, field);
                    break;
                case integer:
                    doHandleInteger(fieldMap, field);
                    break;
                default:
                    throw new RuntimeException("类型匹配失败");
            }

        }
        Boolean acknowledged = client.indices()
                .create(req -> req.index(indexName)
                        .mappings(mapping -> mapping.properties(fieldMap)))
                .acknowledged();
        return acknowledged;
    }

    public void addDoc(Object obj) throws Exception {
        String indexName = getIndexName(obj);
        Long id = getId(obj);
        client.create(
                createReq -> createReq.index(indexName).id(String.valueOf(id)).document(obj)
        );
    }

    public <R> void batchAddDoc(List<R> list) throws Exception {
        List<BulkOperation> opts = new ArrayList<>();
        for (R obj : list) {
            Long id = getId(obj);
            String indexName = getIndexName(obj);
            BulkOperation opt = new BulkOperation.Builder()
                    .create(
                            createReq -> createReq.index(indexName).id(String.valueOf(id)).document(obj)
                    )
                    .build();
            opts.add(opt);
        }
        client.bulk(bulk -> bulk.operations(opts));
    }

    public void deleteDoc(Object obj) throws IOException {
        Long id = getId(obj);
        String indexName = getIndexName(obj);
        client.delete(
                del -> del.index(indexName).id(String.valueOf(id))
        );
    }


    public QueryDto page(String field, String value, int pageNum, int pageSize, String indexName) throws IOException {
        if (StringUtils.isNull(value)) {
            value = "";
        }
        int from = ((pageNum - 1) * pageSize);
        String finalValue = value;
        MatchQuery matchQuery = new MatchQuery.Builder()
                .field(field)
                .query(r -> r.stringValue(finalValue))
                .build();

        Query query = new Query.Builder()
                .match(matchQuery)
                .build();


        SearchRequest searchRequest = new SearchRequest.Builder()
                .index(indexName)
                .query(query)
                .from(from)
                .size(pageSize)
                .build();


        SearchResponse<Object> search = client.search(searchRequest, Object.class);
        List<Object> hits = search.hits()
                .hits()
                .stream()
                .map(Hit::source).
                collect(Collectors.toList());


        Long total = search.hits().total().value();

        return QueryDto.builder()
                .total(total)
                .list(hits)
                .build();
    }

    public QueryDto queryDoc(String field, String value, String highLightKey) throws IOException {


        MatchQuery matchQuery = new MatchQuery.Builder()
                .field(field)
                .query(FieldValue.of(value))
                .build();

        Query query = new Query.Builder()
                .match(matchQuery)
                .build();


        Highlight highlight = new Highlight.Builder()
                .fields(highLightKey, fields -> fields.preTags("<em>").postTags("</em>"))
                .build();

        SearchRequest searchRequest = new SearchRequest.Builder()
                .query(query)
                .highlight(highlight)
                .build();
        SearchResponse<Object> search = client.search(searchRequest, Object.class);

        List<Hit<Object>> hits = search.hits().hits();

        List<Object> list = hits.stream().map(Hit::source).collect(Collectors.toList());
        List<Map<String, List<String>>> highLight = hits.stream().map(Hit::highlight).collect(Collectors.toList());


        return QueryDto.builder()
                .list(list)
                .highLight(highLight)
                .build();
    }


    public List<Object> queryDoc(String field, String value) throws IOException {

        MatchQuery matchQuery = new MatchQuery.Builder()
                .field(field)
                .query(FieldValue.of(value))
                .build();

        Query query = new Query.Builder()
                .match(matchQuery)
                .build();


        SearchRequest searchRequest = new SearchRequest.Builder()
                .query(query)
                .build();


        SearchResponse<Object> search = client.search(searchRequest, Object.class);
        List<Object> hits = search.hits().hits()
                .stream().map(Hit::source).collect(Collectors.toList());

        return hits;
    }


    private Long getId(Object obj) {
        long id = 0;
        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            Optional<Field> any = Arrays.stream(fields).filter(e -> e.getName().equals("id")).findAny();
            Field idField = null;
            if (any.isPresent()) {
                idField = any.get();
            }
            assert idField != null;
            idField.setAccessible(true);
            id = (Long) idField.get(obj);
        } catch (IllegalAccessException e) {
            throw new FieldException("该类没有id属性");
        }
        return id;
    }

    private String getIndexName(Object obj) {
        String indexName = null;
        try {
            Class<?> clazz = obj.getClass();
            indexName = clazz.getAnnotation(ElasticSearchIndex.class).name();
        } catch (Exception e) {
            throw new ElasticSearchException("检查Class是否标有<ElasticSearchIndex>注解");
        }
        return indexName;
    }

    private void doHandleText(Map<String, Property> fieldMap, Field field) {
        ElasticSearchField annotation = field.getAnnotation(ElasticSearchField.class);
        List<String> list = Arrays.asList(annotation.copyTo());
        if (list.size() > 0 && StringUtils.isNotEmpty(list.get(0))) {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.text(TextProperty.of(textProperty -> textProperty
                                            .index(annotation.index())
                                            .analyzer(annotation.analyzer().toString())
                                            .copyTo(list)
                                    )
                            )
                    )
            );
        } else {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.text(TextProperty.of(textProperty -> textProperty
                                            .index(annotation.index())
                                            .analyzer(annotation.analyzer().toString())
                                    )
                            )
                    )
            );
        }
    }

    private void doHandleKeyword(Map<String, Property> fieldMap, Field field) {
        ElasticSearchField annotation = field.getAnnotation(ElasticSearchField.class);
        List<String> list = Arrays.asList(annotation.copyTo());
        if (list.size() > 0 && StringUtils.isNotEmpty(list.get(0))) {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.keyword(KeywordProperty.of(keywordProp -> keywordProp
                                            .index(annotation.index())
                                            .copyTo(list)
                                    )
                            )
                    )
            );
        } else {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.keyword(KeywordProperty.of(keywordProp -> keywordProp
                                            .index(annotation.index())
                                    )
                            )
                    )
            );
        }
    }

    private void doHandleLong_(Map<String, Property> fieldMap, Field field) {
        ElasticSearchField annotation = field.getAnnotation(ElasticSearchField.class);
        List<String> list = Arrays.asList(annotation.copyTo());
        if (list.size() > 0 && StringUtils.isNotEmpty(list.get(0))) {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.long_(LongNumberProperty.of(longProp -> longProp
                                    .index(annotation.index())
                                    .copyTo(list))
                            )
                    )
            );
        } else {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.long_(LongNumberProperty.of(longProp -> longProp
                                            .index(annotation.index())
                                    )
                            )
                    )
            );
        }
    }

    private void doHandleInteger(Map<String, Property> fieldMap, Field field) {
        ElasticSearchField annotation = field.getAnnotation(ElasticSearchField.class);
        List<String> list = Arrays.asList(annotation.copyTo());
        if (list.size() > 0 && StringUtils.isNotEmpty(list.get(0))) {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.integer(IntegerNumberProperty.of(integerProp -> integerProp
                                    .index(annotation.index())
                                    .copyTo(list))
                            )
                    )
            );
        } else {
            fieldMap.put(field.getName(), Property.of(property ->
                            property.integer(IntegerNumberProperty.of(integerProp -> integerProp
                                            .index(annotation.index())
                                    )
                            )
                    )
            );
        }
    }
}


  • annotatioins
package com.yitsd.annotations;

import java.lang.annotation.*;

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AggField {
    String name() default "";
}

package com.yitsd.annotations;

import com.yitsd.enums.Type;
import com.yitsd.enums.Analyzer;

import java.lang.annotation.*;

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ElasticSearchField {
    Type type();

    Analyzer analyzer() default Analyzer.standard;

    boolean index() default true;

    String[] copyTo() default "";

}

package com.yitsd.annotations;

import java.lang.annotation.*;

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ElasticSearchIndex {
    String name();
}
  • enums
package com.yitsd.enums;

public enum Analyzer {

    standard("standard"),
    
    ik_smart("ik_smart"),
    
    ik_max_word("ik_max_word")
    ;

    Analyzer(String str) {

    }
}


package com.yitsd.enums;

public enum Type {

    text("text"),
    
    keyword("keyword"),

    long_("long"),

    integer("integer");

    Type(String str) {

    }
}
  • exception
package com.yitsd.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public class ElasticSearchException extends RuntimeException{

    public ElasticSearchException() {

    }

    public ElasticSearchException(String msg) {
        super(msg);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kouxh@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值