Java API操作ES-通用api抽取

本文介绍了使用Elasticsearch的SearchDataService接口实现,包括创建、更新索引,处理字段映射,设置IndexSettings,以及对文档的增删改操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SearchDataService

import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch.indices.Alias;
import co.elastic.clients.elasticsearch.indices.IndexSettings;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

public interface SearchDataService {

    /**
     * 索引名称
     *
     * @return
     */
    String getIndex();

    /**
     * 创建索引
     */
    void createIndex();

    /**
     * 创建索引 - 读文件
     */
    void createIndexByReader(Reader reader) throws IOException;

    /**
     * 创建索引 - 字符串
     */
    void createIndexByString(String jsonContent) throws IOException;

    /**
     * 更新索引
     */
    void updateIndex();


    /**
     * 字段mapping
     *
     * @return
     */
    EsProperties mapping();

    HashMap<String, Property> specialMapping();

    /**
     * 更新字段mapping
     *
     */
    public HashMap<String, Property> updateMapping();

    /**
     * 索引的settings
     */
    IndexSettings settings();

    /**
     * 索引的别名
     */
    Map<String, Alias> indexAlias();

    /**
     * 新增文档
     */
    <TDocument> void saveData(TDocument data, String id);

    /**
     * 删除数据
     *
     * @param id
     */
    void deleteData(String id);

    /**
     * 更新文档
     */
    <TDocument> void updateData(TDocument data, String id, Class<TDocument> clazz);
}
AbstractSearchDataService

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.core.CreateResponse;
import co.elastic.clients.elasticsearch.core.UpdateResponse;
import co.elastic.clients.elasticsearch.indices.*;
import jakarta.json.Json;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.HashMap;

public abstract class AbstractSearchDataService implements SearchDataService {

    @Resource
    protected ElasticsearchClient syncElasticsearchClient;

    /**
     * 创建索引
     */
    @Override
    public void createIndex() {
        String index = getIndex();

        if (!existIndex(index)) {
            IndexSettings settings = settings();

            String mappings = this.mapping().build();
            System.out.println("mappings are: " + mappings);

            try {
                CreateIndexRequest build = new CreateIndexRequest.Builder()
                        .index(getIndex())
                        .settings(settings)
                        .mappings(TypeMapping._DESERIALIZER.deserialize(Json.createParser(new StringReader(mappings))
                                , syncElasticsearchClient._transport().jsonpMapper()))
                        .aliases(indexAlias())
                        .build();

                CreateIndexResponse createIndexResponse = syncElasticsearchClient.indices()
                        .create(build);

                System.out.println(createIndexResponse);

                //添加 复杂mapping
                if (specialMapping() != null) {
                    // 构建mapping时,builder用到的lambda
                    PutMappingResponse putMappingResponse = syncElasticsearchClient.indices()
                            .putMapping(typeMappingBuilder ->
                                    typeMappingBuilder
                                            .index(index)
                                            .properties(specialMapping())
                            );
                    System.out.println(putMappingResponse);
                }
            } catch (Exception e) {

            }
        }
    }


    @Override
    public void createIndexByReader(Reader reader) throws IOException {
        String index = getIndex();

        if (!existIndex(index)) {
            // 根据Reader创建请求对象
            CreateIndexRequest request = CreateIndexRequest.of(builder -> builder
                    .index(index)
                    .withJson(reader));

            syncElasticsearchClient.indices().create(request);
        }
    }

    @Override
    public void createIndexByString(String jsonContent) throws IOException {
        String index = getIndex();

        if (!existIndex(index)) {
            // 根据Reader创建请求对象
            CreateIndexRequest request = CreateIndexRequest.of(builder -> builder
                    .index(index)
                    .withJson(new StringReader(jsonContent)));

            syncElasticsearchClient.indices().create(request);
        }
    }


    /**
     * 更新索引方式 - 也是支持 withJson 的
     */
    @Override
    public void updateIndex() {
        try {
            String index = getIndex();
            if (!existIndex(index)) {
                System.out.println("索引不存在");
                return;
            }

            HashMap<String, Property> updateMapping = this.updateMapping();
            if (updateMapping != null && updateMapping.size() > 0) {
                PutMappingResponse putMappingResponse = syncElasticsearchClient.indices()
                        .putMapping(typeMappingBuilder ->
                                typeMappingBuilder
                                        .index(getIndex())
                                        .properties(this.updateMapping())
                        );
                System.out.println(putMappingResponse);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 添加记录.
     */
    @Override
    public <TDocument> void saveData(TDocument data, String id) {
        try {
            CreateResponse response = syncElasticsearchClient.create(c -> c.index(getIndex()).id(id).document(data));
            System.out.println(response);
        } catch (IOException e) {
        }
    }

    /**
     * 更新 doc
     * ***********
     * 如果要更新某个字段为 null
     * 在实体对应的属性上加 @JsonInclude(JsonInclude.Include.ALWAYS)
     * 原因 new ObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
     */
    @Override
    public <TDocument> void updateData(TDocument data, String id, Class<TDocument> clazz) {
        try {
            UpdateResponse<TDocument> updateResponse = syncElasticsearchClient.update(u -> u
                    .index(getIndex()).id(id).doc(data).docAsUpsert(true), clazz);
            System.out.println(updateResponse);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除数据
     *
     * @param id
     */
    @Override
    public void deleteData(String id) {
        try {
            syncElasticsearchClient.delete(c -> c.index(getIndex())
                    .id(id));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 索引是否存在
     *
     * @param index
     * @return
     */
    public boolean existIndex(String index) {
        ElasticsearchIndicesClient indices = syncElasticsearchClient.indices();
        try {
            if (!indices.exists(u -> u.index(index)).value()) {
                return false;
            }
        } catch (Exception ignored) {

        }
        return true;
    }
}

项目启动时候管理index


import com.dd.mall.demo.es.search.es.SearchDataService;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;

@Component
public class SearchDataRunner {

    @Resource
    private ApplicationContext applicationContext;

    @PostConstruct
    public void executeIndex() {
        Map<String, SearchDataService> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
                applicationContext, SearchDataService.class, true, false);
        for (SearchDataService bean : beans.values()) {
            bean.createIndex();
        }

        for (SearchDataService bean : beans.values()) {
            bean.updateIndex();
        }
    }
}



用到的工具类

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;

public class JsonMapper {
    private static final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
    private final ObjectMapper mapper;

    public JsonMapper() {
        this((JsonInclude.Include) null);
    }

    public JsonMapper(JsonInclude.Include include) {
        this.mapper = new ObjectMapper();
        if (include != null) {
            this.mapper.setSerializationInclusion(include);
        }

        this.mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    public static JsonMapper nonEmptyMapper() {
        return new JsonMapper(Include.NON_EMPTY);
    }

    public static JsonMapper nonNullMapper() {
        return new JsonMapper(Include.NON_NULL);
    }

    public static JsonMapper alwaysMapper() {
        return new JsonMapper(Include.ALWAYS);
    }

    public String toJson(Object object) {
        try {
            return this.mapper.writeValueAsString(object);
        } catch (JsonProcessingException var3) {
            logger.warn("JSON序列化出错", var3);
            return null;
        }
    }

    public <T> T fromJson(String json, Class<T> clazz) {
        if (StringUtils.isBlank(json)) {
            return null;
        } else {
            try {
                return this.mapper.readValue(json, clazz);
            } catch (IOException var4) {
                logger.warn("JSON反序列化出错: " + json, var4);
                return null;
            }
        }
    }

    public <T> T fromJson(String json, TypeReference<T> valueTypeRef) {
        if (StringUtils.isBlank(json)) {
            return null;
        } else {
            try {
                return this.mapper.readValue(json, valueTypeRef);
            } catch (IOException var4) {
                logger.warn("JSON反序列化出错: " + json, var4);
                return null;
            }
        }
    }

    public <T> T fromJson(InputStream inputStream, Class<T> clazz) {
        try {
            return this.mapper.readValue(inputStream, clazz);
        } catch (IOException var4) {
            logger.warn("JSON反序列化出错");
            return null;
        }
    }
}
用到的工具类

import java.util.HashMap;
import java.util.Map;

public class EsProperties {


    private Map<String, Fields> fieldMap;

    private EsProperties() {
        this.fieldMap = new HashMap<>();
    }

    public static EsProperties builder() {
        return new EsProperties();
    }

    public Fields field(String field) {
        if (!this.fieldMap.containsKey(field)) {
            this.fieldMap.put(field, new Fields(this));
        }
        return fieldMap.get(field);
    }

    public String build() {
        Map<String, Object> properties = new HashMap<>();
        properties.put("properties", fieldMap);
        return JsonMapper.alwaysMapper().toJson(properties);
    }

    public String buildSettings() {
        Map<String, Object> properties = new HashMap<>();
        properties.put("index", fieldMap);
        return JsonMapper.alwaysMapper().toJson(properties);
    }


    public Map<String, Fields> props() {
        return fieldMap;
    }

    public static class Fields extends HashMap<String, Object> {
        private final EsProperties esProperties;

        public Fields(EsProperties esProperties) {
            this.esProperties = esProperties;
        }

        public Fields property(String key, Object value) {
            this.put(key, value);
            return this;
        }

        public static Fields newFiled() {
            return new Fields(null);
        }

        public EsProperties then() {
            return esProperties;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值