java连接ElasticSearch 8.2.3、新建索引、删除索引、填充数据

版本:ElasticSearch 8.2.3

        文末有实测例子,本文为同步ES库与数据库中数据,有相同需求的朋友可以直接拿走

建立连接

private ElasticsearchClient elasticsearchClient;

    @Override
    public void initialize() {
        log.info("initElasticSearchClient ...");
        RestClient restClient = RestClient.builder(
                new HttpHost(GenomeApp.Config.ELASTIC_SEARCH_HOST, GenomeApp.Config.ELASTIC_SEARCH_PORT)).build();
        ElasticsearchTransport transport = new RestClientTransport(
                restClient, new JacksonJsonpMapper());
        elasticsearchClient = new ElasticsearchClient(transport);
        log.info("initElasticSearchClient successfully");
    }

精确查询

    public  SearchResponse search(String index, String field, String searchText, Class targetClass) {
        SearchResponse response = null;
        try {
            // 查询name=AAV的对象 参考链接:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/searching.html
            response = elasticsearchClient.search(s -> s
                            .index(index)
                            .query(q -> q.match(t -> t.field(field).query(searchText))),
                    targetClass);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

模糊匹配

    /**
     * 根据条件模糊匹配并返回记录信息
     * @param index 领域资源名
     * @param conditionMap 筛选条件
     * @param targetClass 返回的对象类
     * @param
     * @return 符合筛选条件的记录
     */
    public  SearchResult searchResourceByCondition(String index, HashMap conditionMap, Class targetClass){
        SearchResult result = new SearchResult();
        SearchResponse response = null;
        long totalSize = 0;
        List objectList = new ArrayList<>();

        // 是否模糊匹配,默认模糊查询
        boolean isWildcardQuery = true;
        if (conditionMap.containsKey("queryMode")) {
            isWildcardQuery = conditionMap.get("queryMode").equals("wild");
            conditionMap.remove("queryMode");
        }
        // 查询大小,默认为10000
        int size = 10000;
        if (conditionMap.containsKey("size")) {
            size = Integer.parseInt(conditionMap.get("size"));
            conditionMap.remove("size");
        }
        // 查询开始索引,默认为0
        int from = 0;
        if (conditionMap.containsKey("from")) {
            from = Integer.parseInt(conditionMap.get("from"));
            if (from >= 10000) {
                result.setCode(-1);
                result.setMessage("不支持查询10000以上的数据,请选择搜索条件,缩小查询范围!");
                return result;
            }
            conditionMap.remove("from");
        }
        // 排序
        List sortList = new ArrayList<>();
        if(conditionMap.containsKey("sort")){
            // 多个字段用","连接
            String sortItems = conditionMap.get("sort");
            String[] fieldItems = sortItems.split(",");
            for(String fieldItem : fieldItems) {
                // 字段和排序方式用"-"连接
                sortList.add(fieldItem);
            }
            conditionMap.remove("sort");
        } else {
            // 没有条件,默认按第一个字段升序排列
            for(String field:conditionMap.keySet()){
                sortList.add(field+"-asc");
                break;
            }
        }

        BoolQuery.Builder builder = new BoolQuery.Builder();
        for(String field:conditionMap.keySet()){
            String value = conditionMap.get(field);
            if(value.contains(",")){
                // 多选
                String[] values = value.split(",");
                List multiQueryList = new ArrayList<>();
                for(String val: values) {
                    if(isWildcardQuery) {
                        // 模糊匹配
                        multiQueryList.add(WildcardQuery.of(m -> m
                                .field(field)
                                .value("*"+val+"*")
                        )._toQuery());
                    } else {
                        // 精准匹配
                        multiQueryList.add(MatchQuery.of(m -> m
                                .field(field)
                                .query(val)
                        )._toQuery());
                    }
                }
                // 相同字段多选用or连接
                BoolQuery orQuery = BoolQuery.of(o -> o.should(multiQueryList));
                // 不同字段多选用must连接
                builder.must(m->m.bool(orQuery));
            } else{
                // 单选
                if(isWildcardQuery) {
                    // 模糊匹配
                    builder.must(WildcardQuery.of(m -> m
                            .field(field)
                            .value("*"+value+"*")
                    )._toQuery());
                } else {
                    // 精准匹配
                    builder.must(MatchQuery.of(m -> m
                            .field(field)
                            .query(value)
                    )._toQuery());
                }
            }
        }
        BoolQuery queryES = builder.build();

        // 拼装排序条件
        List sortOptions = new ArrayList<>();

        for(String fieldItem: sortList) {
            String[] items = fieldItem.split("-");
            SortOrder sortOrder = "asc".equals(items[1]) ? SortOrder.Asc : SortOrder.Desc;
            SortOptions sortOption = SortOptions.of(s -> s.field(f -> f.field(items[0]).order(sortOrder)));
            sortOptions.add(sortOption);
        }


        try {
            totalSize = elasticsearchClient.count(s -> s
                    .index(index).query(q->q.bool(queryES))).count();

            int finalSize = size;
            int finalFrom = from;
            response = elasticsearchClient.search(s -> s
                            .index(index)
                            .query(q->q.bool(queryES))
                            .from(finalFrom)
                            .size(finalSize)
                            .sort(sortOptions)
                           ,
                    targetClass
            );

            List> hits = response.hits().hits();
            for (Hit hit : hits) {
                T object = hit.source();
                objectList.add(object);
            }
            result.setCode(200);
            result.setTotalSize(totalSize);
            result.setResultList(objectList);
        }
        catch (Exception e) {
            result.setCode(-1);
            result.setMessage("查询失败,错误原因为:" + e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

创建索引

/**
     * 创建索引:若索引存在,先删除再创建
     */
    public void createIndex(String indexName, Map mappings) {
        try {
            //创建索引时创建文档类型映射

            //创建索引
            CreateIndexRequest createIndexRequest = CreateIndexRequest.of(e ->
                    e.index(indexName)
                            .mappings(m -> m.properties(mappings))
            );
            //先判断索引是否存在,存在则删除后再创建
            BooleanResponse existRes = elasticsearchClient.indices().exists(ExistsRequest.of(e -> e.index(indexName)));
            if (existRes.value()) {
                deleteIndex(indexName);
            }
            CreateIndexResponse createIndexResponse = elasticsearchClient.indices().create(createIndexRequest);
            if (createIndexResponse.acknowledged()) {
                log.info(String.format("Index [%s] created", indexName));
            }
        }
        catch (Exception e) {
            log.info(String.format("Index [%s] creation fail", indexName) + e);
        }
    }

删除索引


    /**
     * 删除索引
     *
     * @param indexName
     * @return 成功 or 失败
     * @throws IOException
     */
    public boolean deleteIndex(String indexName) throws IOException {
        DeleteIndexRequest  deleteIndexRequest = DeleteIndexRequest.of(e -> e.index(indexName));
        DeleteIndexResponse deleteRes          = elasticsearchClient.indices().delete(deleteIndexRequest);
        if (deleteRes.acknowledged()) {
            log.info("索引:" + indexName + ",删除成功!");
        }
        return deleteRes.acknowledged();
    }

批量填充数据

        本文使用反射获取第一个值来获得ID,各位要根据自己的id属性在对象中的位置来获取


    /**
     * 批量新建es数据
     * @param list 数据对象
     * @param name 索引名
     * @param  数据对象类型
     */
    public  void createESData(List list, String name){
        initialize();
        List bulkOperations = new ArrayList<>();
        try {
            for (T object : list){
                //通过反射获取Id属性
                Field[] field = object.getClass().getDeclaredFields();
                //设置对象的访问权限,保证对private的属性的访问
                field[0].setAccessible(true);
                String virusId = (String) field[0].get(object);
                bulkOperations.add(new BulkOperation.Builder().create(d-> d.document(object).id(virusId).index(name)).build());
            }// 使用bulk方法执行批量操作并获得响应
            BulkResponse response = elasticsearchClient.bulk(e->e.index(name).operations(bulkOperations));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

更新ES中信息(删除索引-新建索引-填充数据)

        直接传入对象的类和数据列表就可以,直接使用反射获取属性信息,防止手写mapping时出现问题

    /**
     * 更新es中信息
     * @param clazz 类
     * @param list 数据列表
     * @param  数据类型
     */
    public static  void updateEs(ElasticSearchService elasticSearchService, Class clazz, List list, String indexName){
        Map mappings = new HashMap<>();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //设置对象的访问权限,保证对private的属性的访问
            field.setAccessible(true);
            mappings.put(field.getName(), Property.of(p -> p.keyword(KeywordProperty.of(key -> key.nullValue(field.getName())))));
        }
        elasticSearchService.createIndex(indexName, mappings);
        elasticSearchService.createESData(list, indexName);
    }

你可能感兴趣的:(笔记,elasticsearch,java,搜索引擎)