Используйте SpringBoot Data ElasticSearch для инкапсуляции собственного API

Elasticsearch

предисловие

Солнечным днем ​​менеджер проекта похлопал меня по плечу и сказал: "Сяо Чжоу, есть небольшой запрос, который нуждается в вашей поддержке. Он будет запущен в конце месяца. Сначала вы должны изучить спрос. Когда я уже собирался возвращаться, как обнаружил, что менеджер проекта разговаривает по телефону, и с улыбкой убежал, сказав: «Здравствуйте...»

Скромная разработка наконец-то сформировала спрос — пристыковать ElasticSearch, написать API для бэкенда, но его запустят меньше чем через две недели (продукт дня…). Наконец, я решил использовать SpringBoot Data ElasticSearch и сделать на его основе простую инкапсуляцию, основанную наElasticsearchRestTemplateВнедрите API для предоставления услуг серверной части. Поддерживается CURD.Поскольку запрос должен поддерживать SQL-запрос, дополнительно ссылаются на пакет bboss, чтобы помочь в анализе объекта.

дизайн

Разделен на два модуля: API-Module и Service-Module.

  • API-Module
    • xxxEntity.java: определяет сущность, параметры индекса и параметры знакомства полей документа es.
    • EsQueryAnnotation: аннотация, определяющая данные, используемые для запроса Es.
    • xxxReq.java: сущность запроса Es, указанная выше EsQueryAnnotation предназначена для него.
    • xxxResp.java: объект, который получает данные Es
    • xxxFacade.java: открыт интерфейс Dubbo
  • Service-Module
    • EsQueryParse.java: Анализ EsQueryAnnotation и сборка в общий запрос.
    • xxxService/xxxxServiceImpl.java: Интерфейс службы и реализация

окрестности

  • ElasticSearch : 7.7.1
  • SpringBoot: 2.3.1.RELEASE
  • JDK1.8

Временная диаграмма

Подобно обычному CURD, будь то операция индекса или данных es, ее необходимо выполнять через сущность.

пример кода

pom.xml

    <properties>
        <!--依赖版本-->
        <spring-boot.version>2.3.1.RELEASE</spring-boot.version>
    <dependencies>
		<!-- Spring -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>${spring-boot.version}</version>
            <scope>compile</scope>
        </dependency>
        <!-- Es -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>com.bbossgroups.plugins</groupId>
            <artifactId>bboss-elasticsearch-rest-jdbc</artifactId>
            <version>6.1.8</version>
        </dependency>
    </dependencies>

Api-Module

аннотация запроса

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EsEquals {
    /**
     * filed name
     */
    String name() default "";
}

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EsIn {
    /**
     * filed name
     */
    String name() default "";
}

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EsLike {
    /**
     * filed name
     */
    String name() default "";

    boolean leftLike() default false;

    boolean rightLike() default false;
}

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EsRange {
    /**
     * filed name
     */
    String name() default "";

    /**
     * >
     */
    boolean lt() default false;

    /**
     * <
     */
    boolean gt() default false;

    /**
     * 包含上界
     */
    boolean includeUpper() default false;

    /**
     * 包含下界
     */
    boolean includeLower() default false;

}

Entity

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Document(indexName = "ems", shards = 1, replicas = 1)
public class EsDocBeanEntity extends EsBaseEntity {
    @Id
    private String id;

    @Field(type = FieldType.Keyword)
    private String firstCode;

    @Field(type = FieldType.Keyword)
    private String secordCode;

    @Field(type = FieldType.Text)
    private String content;

    @Field(type = FieldType.Integer)
    private Integer type;
}

EsResult

@Getter
@Setter
public class EsResult<T> extends EsBaseResp {
    private T data;
    private Long pageCount;
    private Long recordCount;

    public void setPageCount(Long recordCount, Long size) {
        this.pageCount = recordCount / size;
    }

    public static <T> EsResult<T> of(T t) {
        return EsResult.of(t, null, null, null);
    }

    public static <T> EsResult<T> of(T t, Long recordCount) {
        return EsResult.of(t, recordCount, null, null);
    }

    public static <T> EsResult<T> of(T t, Long recordCount, Long pageCount) {
        return EsResult.of(t, pageCount, recordCount, null);
    }

    public static <T> EsResult<T> of(T t, Long recordCount, Long pageCount, Long pageSize) {
        EsResult<T> esResult = new EsResult<>();
        esResult.setData(t);
        if (recordCount != null) {
            esResult.setRecordCount(recordCount);
        }
        if (pageCount != null) {
            esResult.setPageCount(pageCount);
        }
        if (pageSize != null) {
            esResult.setPageCount(recordCount, pageSize);
        }
        return esResult;
    }
}

EsPageable

@Getter
@Setter
public class EsPageable {
    private Integer page = 1;
    private Integer size = 15;
    private String orderBy = "";
    private String order = "";

    public enum OrderEnum {
        /**
         * 正序
         */
        ASC("ASC"),
        /**
         * 倒叙
         */
        DESC("DESC");
        /**
         * 值
         */
        private String value;

        OrderEnum(String value) {
            this.value = value;
        }
    }


    public static Sort getQuerySort(EsPageable pageable) {
        Sort sort = null;
        if (StringUtils.isNotBlank(pageable.getOrderBy()) && pageable.getOrder() != null) {
            if (StringUtils.equalsIgnoreCase(pageable.getOrder(), EsBaseReq.OrderEnum.ASC.name())) {
                sort = Sort.by(Sort.Order.asc(pageable.getOrderBy()));
            } else {
                sort = Sort.by(Sort.Order.desc(pageable.getOrderBy()));
            }
        }
        return sort == null ? Sort.unsorted() : sort;
    }

    public static Pageable getQueryPageable(EsPageable pageable) {
        int page = pageable.getPage() - 1;
        Integer size = pageable.getSize();
        return PageRequest.of(page, size);
    }

}

Request

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Document(indexName = "ems")
public class EsDocBeanReq extends EsBaseReq {
    @EsEquals(name = "_id")
    private String id;

    @EsEquals
    private String firstCode;

    @EsEquals
    private String secordCode;

    @EsLike
    private String content;

    @EsIn(name = "type")
    private List<Integer> typeList;

    @EsRange(lt = true, name = "type")
    private Integer typeRange;
}

Respone

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class EsDocBeanResp extends EsBaseResp {
    private String id;

    private String firstCode;

    private String secordCode;

    private String content;

    private Integer type;
}

Service-Module

EsQueryParse

@Slf4j
public class EsQueryParse {
    private EsQueryParse() {
    }

    public static <T> Query convert2Query(T t) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder(t);
        queryBuilder.withQuery(boolQueryBuilder);
        return queryBuilder.build();
    }

    private static <T> BoolQueryBuilder getBoolQueryBuilder(T t) {
        return getBoolQueryBuilder(t, null);
    }

    private static <T> BoolQueryBuilder getBoolQueryBuilder(T t, String nestedPath) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Class<?> clazz = t.getClass();
        Field[] fields = clazz.getDeclaredFields();
        nestedPath = nestedPath == null ? "" : nestedPath;
        try {
            for (Field field : fields) {
                Object value = ClassUtils.getPublicMethod(clazz, "get" + captureName(field.getName())).invoke(t);
                if (value == null) {
                    continue;
                }
                if (field.isAnnotationPresent(EsLike.class)) {
                    WildcardQueryBuilder query = getLikeQuery(field, value, nestedPath);
                    boolQueryBuilder.must(query);
                }
                if (field.isAnnotationPresent(EsEquals.class)) {
                    MatchQueryBuilder query = getEqualsQuery(field, value, nestedPath);
                    boolQueryBuilder.must(query);
                }
                if (field.isAnnotationPresent(EsRange.class)) {
                    RangeQueryBuilder query = getRangeQuery(field, value, nestedPath);
                    boolQueryBuilder.must(query);
                }
                if (field.isAnnotationPresent(EsIn.class)) {
                    TermsQueryBuilder query = getInQuery(field, (List<?>) value, nestedPath);
                    boolQueryBuilder.must(query);
                }
                if (field.isAnnotationPresent(EsNotNull.class)) {
                    ExistsQueryBuilder query = getNotNullQuery(field, nestedPath);
                    boolQueryBuilder.must(query);
                }
                if (field.isAnnotationPresent(EsNotNullFields.class)) {
                    List<ExistsQueryBuilder> query = getNotNullQuery((List<String>) value, nestedPath);
                    Optional.ofNullable(query).orElse(new ArrayList<>())
                            .forEach(boolQueryBuilder::must);
                }
                if (field.isAnnotationPresent(EsNested.class)) {
                    NestedQueryBuilder query = getNestedQuery(field, value);
                    boolQueryBuilder.must(query);
                }
            }
        } catch (Exception e) {
            log.info("ES查询解析异常:{}", e.getMessage());
        }
        return boolQueryBuilder;
    }

    private static TermsQueryBuilder getInQuery(Field field, List<?> value, String nestedPath) {
        EsIn esIn = field.getAnnotation(EsIn.class);
        String filedName = getFiledName(field, esIn.name(), nestedPath);
        return QueryBuilders.termsQuery(filedName, value);
    }

    private static RangeQueryBuilder getRangeQuery(Field field, Object value, String nestedPath) {
        EsRange esRange = field.getAnnotation(EsRange.class);
        String filedName = getFiledName(field, esRange.name(), nestedPath);
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(filedName)
                .includeLower(esRange.includeLower())
                .includeUpper(esRange.includeUpper());
        if (esRange.lt()) {
            rangeQueryBuilder.gt(value);
        }
        if (esRange.gt()) {
            rangeQueryBuilder.gt(value);
        }
        return rangeQueryBuilder;
    }

    private static MatchQueryBuilder getEqualsQuery(Field field, Object value, String nestedPath) {
        EsEquals esEquals = field.getAnnotation(EsEquals.class);
        String filedName = getFiledName(field, esEquals.name(), nestedPath);
        return QueryBuilders.matchQuery(filedName, value);
    }

    private static WildcardQueryBuilder getLikeQuery(Field field, Object value, String nestedPath) {
        String likeValue = (String) value;
        EsLike esLike = field.getAnnotation(EsLike.class);
        String filedName = getFiledName(field, esLike.name(), nestedPath);
        if (esLike.leftLike()) {
            likeValue = "*" + likeValue;
        }
        if (esLike.rightLike()) {
            likeValue = likeValue + "*";
        }
        return QueryBuilders.wildcardQuery(filedName, likeValue);
    }

    private static ExistsQueryBuilder getNotNullQuery(Field field, String nestedPath) {
        EsNotNull esNotNull = field.getAnnotation(EsNotNull.class);
        String filedName = getFiledName(field, esNotNull.name(), nestedPath);
        return QueryBuilders.existsQuery(filedName);
    }

    private static List<ExistsQueryBuilder> getNotNullQuery(List<String> value, String nestedPath) {
        if (CollectionUtils.isEmpty(value)) {
            return new ArrayList<>();
        }
        return value.stream()
                .map(item-> getFiledName(item, nestedPath))
                .map(QueryBuilders::existsQuery)
                .collect(Collectors.toList());
    }

    private static NestedQueryBuilder getNestedQuery(Field field, Object object) {
        EsNested esNested = field.getAnnotation(EsNested.class);
        String nestedPath = getFiledName(field, esNested.name(), "");
        QueryBuilder boolQueryBuilder = getBoolQueryBuilder(object, nestedPath);
        return QueryBuilders.nestedQuery(nestedPath, boolQueryBuilder, ScoreMode.None);
    }

    private static String getFiledName(Field field, String name, String nestedPath) {
        String fileName = name;
        if (field != null) {
            fileName = StringUtils.isBlank(name) ? field.getName() : name;
        }
        if (StringUtils.isBlank(nestedPath)) {
            return fileName;
        }
        return nestedPath + "." + fileName;
    }

    private static String getFiledName(String name, String nestedPath) {
        return getFiledName(null, name, nestedPath);
    }

    public static String captureName(String name) {
        char[] cs = name.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);
    }
}

service

/**
 * 对ElasticSearch 数据操作
 *
 * @author: zhoukun@hztianque.com
 */
@Validated
public interface EsDataService {

    /**
     * 添加一条数据
     *
     * @param t obj
     */
    <T> T save(@NotNull T t);

    /**
     * 批量添加数据
     *
     * @param tList
     */
    <T> boolean batchSave(@NotEmpty List<T> tList);

    /**
     * 单个更新
     *
     * @param t
     * @param <T>
     * @return
     */
    <T> boolean update(@NotNull T t);

    /**
     * 批量更新
     *
     * @param tList
     * @param <T>
     * @return
     */
    <T> boolean batchUpdate(@NotEmpty List<T> tList);

    /**
     * 删除
     *
     * @param clazz
     * @param id
     * @param <T>
     * @return
     */
    <T> boolean delete(@NotNull Class<T> clazz, @NotBlank String id);

    /**
     * 批量删除
     *
     * @param clazz
     * @param idList
     * @param <T>
     * @return
     */
    <T> boolean batchDelete(@NotNull Class<T> clazz, @NotEmpty List<String> idList);

    /**
     * 根据id查询一个对象
     *
     * @param clazz
     * @param id
     * @return
     */
    <T> T findById(@NotNull Class<T> clazz, @NotBlank String id);

    /**
     * 根据查询条件查询对象
     *
     * @param clazz
     * @param query
     * @return
     */
    <T> T findOne(@NotNull Class<T> clazz, @NotNull Query query);

    /**
     * 根据查询条件查询对象
     *
     * @param clazz
     * @param req
     * @return
     */
    <T> T findOne(@NotNull Class<T> clazz, @NotNull EsBaseReq req);

    /**
     * 查询某个对象的所有数据,慎用
     *
     * @param clazz
     * @return
     */
    <T> EsResult<List<T>> findAll(@NotNull Class<T> clazz);

    /**
     * 查询某个对象的所有数据,提供分页排序参数
     *
     * @param clazz
     * @param pageable
     * @return
     */
    <T> EsResult<List<T>> findAll(@NotNull Class<T> clazz, @NotNull EsPageable pageable);

    /**
     * 根据条件查询数据
     *
     * @param t
     * @param query
     * @return
     */
    <T> EsResult<List<T>> search(@NotNull Class<T> t, @NotNull Query query);

    /**
     * 根据es查询条件查询
     *
     * @param t
     * @param request
     * @return
     */
    <T> EsResult<List<T>> search(@NotNull Class<T> t, @NotNull EsBaseReq request);

    /**
     * 手写dsl查询条件查询数据
     *
     * @param t
     * @param dsl
     * @return
     */
    <T> EsResult<List<T>> dslSearch(@NotNull Class<T> t, @NotBlank(message = "dsl语句不能为空") String dsl);

    /**
     * 使用SQL 条件查询数据
     *
     * @param t
     * @param sql
     * @return
     */
    <T> List<T> sqlSearch(@NotNull Class<T> t, @NotBlank(message = "sql语句不能为空") String sql);

    /**
     * 使用SQL查询单个对象
     *
     * @param t
     * @param sql
     * @return
     */
    <T> T sqlFindOne(@NotNull Class<T> t, @NotBlank(message = "sql语句不能为空") String sql);
}

/**
 * 对ElasticSearch 索引操作
 *
 * @date: 2020/8/10 00:00
 */
public interface EsIndexService {

    /**
     * 创建索引
     *
     * @param t
     * @return
     */
    <T> boolean createIndex(Class<T> t);

    /**
     * 删除索引
     *
     * @param t
     * @return
     */
    <T> boolean deleteIndex(Class<T> t);

    /**
     * 重建索引,数据会被删除
     *
     * @param t
     * @return
     */
    <T> boolean reCreate(Class<T> t);

    /**
     * 判断索引是否存在
     *
     * @param t
     * @return
     */
    <T> boolean indexExists(Class<T> t);
}

serviceImpl

/**
 * @date: 2020/8/5 19:22
 */

@Service
public class EsDataServiceImpl implements EsDataService {
    @Resource
    private RestClient restClient;
    @Resource
    private ElasticsearchRestTemplate elasticsearchTemplate;

    private static Gson gson = new Gson();

    @Override
    public <T> T save(T t) {
        return elasticsearchTemplate.save(t);
    }

    @Override
    public <T> boolean batchSave(List<T> tList) {
        elasticsearchTemplate.save(tList);
        return true;
    }

    @Override
    public <T> boolean update(T t) {
        return true;
    }

    @Override
    public <T> boolean batchUpdate(List<T> tList) {
        return true;
    }

    @Override
    public <T> boolean delete(Class<T> clazz, String id) {
        Annotation annotation = AnnotationUtils.getAnnotation(clazz, Document.class);
        Document document = (Document) annotation;
        IndexCoordinates index = IndexCoordinates.of(document.indexName());
        elasticsearchTemplate.delete(id, index);
        return true;
    }

    @Override
    public <T> boolean batchDelete(Class<T> clazz, List<String> idList) {
        Annotation annotation = AnnotationUtils.getAnnotation(clazz, Document.class);
        Document document = (Document) annotation;
        IndexCoordinates index = IndexCoordinates.of(document.indexName());
        idList.forEach(id -> elasticsearchTemplate.delete(id, index));
        return true;
    }

    @Override
    public <T> T findById(Class<T> clazz, String id) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.matchQuery("_id", id));
        SearchHit<T> searchHit = elasticsearchTemplate.searchOne(queryBuilder.build(), clazz);
        return searchHit == null ? null : searchHit.getContent();
    }

    @Override
    public <T> T findOne(Class<T> clazz, Query query) {
        SearchHit<T> searchHit = elasticsearchTemplate.searchOne(query, clazz);
        return searchHit == null ? null : searchHit.getContent();
    }

    @Override
    public <T> T findOne(Class<T> clazz, EsBaseReq esBaseReq) {
        Query query = EsQueryParse.convert2Query(esBaseReq);
        SearchHit<T> searchHit = elasticsearchTemplate.searchOne(query, clazz);
        return searchHit != null ? searchHit.getContent() : null;
    }

    @Override
    public <T> EsResult<List<T>> findAll(Class<T> clazz) {
        SearchHits<T> searchHits = elasticsearchTemplate.search(Query.findAll(), clazz);
        List<T> data = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        return EsResult.of(data, searchHits.getTotalHits());
    }

    @Override
    public <T> EsResult<List<T>> findAll(Class<T> clazz, EsPageable pageable) {
        Query query = new StringQuery(QueryBuilders.boolQuery().toString());
        query.setPageable(EsPageable.getQueryPageable(pageable));
        query.addSort(EsPageable.getQuerySort(pageable));

        SearchHits<T> search = elasticsearchTemplate.search(query, clazz);
        List<T> data = search.get().map(SearchHit::getContent).collect(Collectors.toList());
        long recordCount = search.getTotalHits();
        return EsResult.of(data, recordCount);
    }

    @Override
    public <T> EsResult<List<T>> search(Class<T> clazz, Query query) {
        SearchHits<T> searchHit = elasticsearchTemplate.search(query, clazz);
        List<T> data = searchHit.get().map(SearchHit::getContent).collect(Collectors.toList());
        long recordCount = searchHit.getTotalHits();
        return EsResult.of(data, recordCount);
    }

    @Override
    public <T> EsResult<List<T>> search(Class<T> t, EsBaseReq request) {
        //组装查询
        Query query = EsQueryParse.convert2Query(request);
        //组装分页
        query.setPageable(EsPageable.getQueryPageable(request));
        //组装排序
        query.addSort(EsPageable.getQuerySort(request));

        SearchHits<T> searchHits = elasticsearchTemplate.search(query, t);
        List<T> data = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        long recordCount = searchHits.getTotalHits();
        return EsResult.of(data, recordCount);
    }

    @Override
    public <T> EsResult<List<T>> dslSearch(Class<T> t, String dsl) {
        StringQuery stringQuery = new StringQuery(dsl);

        SearchHits<T> searchHits = elasticsearchTemplate.search(stringQuery, t);
        List<T> data = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        long recordCount = searchHits.getTotalHits();
        return EsResult.of(data, recordCount);
    }

    @Override
    public <T> T sqlFindOne(Class<T> t, String sql) {
        String queryStr = String.format("{\"query\":\"%s\", \"fetch_size\":1}", sql);
        return restClientSearch(t, queryStr).stream().findFirst().orElse(null);
    }

    @Override
    public <T> List<T> sqlSearch(Class<T> t, String sql) {
        String queryStr = String.format("{\"query\":\"%s\"}", sql);
        return restClientSearch(t, queryStr);
    }

    /**
     * 使用restClient 查询数据
     *
     * @param t
     * @param queryStr sql_dsl查询条件
     * @return
     */
    private <T> List<T> restClientSearch(Class<T> t, String queryStr) {
        try {
            Request request = new Request("POST", "/_xpack/sql");
            request.setJsonEntity(queryStr);

            Response response = restClient.performRequest(request);
            String jsonData = EntityUtils.toString(response.getEntity());

            SQLRestResponse sqlRestResponse = gson.fromJson(jsonData, SQLRestResponse.class);
            SQLResult<T> sqlResult = ResultUtil.buildFetchSQLResult(sqlRestResponse, t, (SQLResult<T>) null);

            return sqlResult.getDatas();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return new ArrayList<>();
    }

}

/**
 * 对ElasticSearch 索引的服务类
 *
 * @date: 2020/8/10 00:01
 */
@Service
public class EsIndexServiceImpl implements EsIndexService {
    @Resource
    protected ElasticsearchOperations operations;

    @Override
    public <T> boolean createIndex(Class<T> t) {
        IndexOperations indexOperations = operations.indexOps(t);
        boolean createIndexRes = indexOperations.create();
        if (!createIndexRes) {
            return false;
        }
        Document document = indexOperations.createMapping();
        return indexOperations.putMapping(document);
    }

    @Override
    public <T> boolean deleteIndex(Class<T> t) {
        return operations.indexOps(t).delete();
    }

    @Override
    public <T> boolean reCreate(Class<T> t) {
        IndexOperations indexOperations = operations.indexOps(t);
        return indexOperations.delete() && indexOperations.create();
    }

    @Override
    public <T> boolean indexExists(Class<T> t) {
        return operations.indexOps(t).exists();
    }
}

Junit


    @Test
    public void search2() {
        EsDocBeanEntity one = createOne();
        String id = one.getId();

        EsDocBeanReq request = new EsDocBeanReq();
        request.setId(id);
        request.setPage(1);
        request.setSize(3);

        EsResult<List<EsDocBeanEntity>> search = esDataService.search(EsDocBeanEntity.class, request);

        System.out.println("gson.toJson(search) = " + gson.toJson(search));

        Assert.assertNotNull(search);
        Assert.assertTrue(CollectionUtils.isNotEmpty(search.getData()));

        deleteOne(one);
    }
    
    @Test
    public void sqlSearch() {
        String sql = null;
        sql = "SELECT * FROM ems limit 10";

        List<EsDocBeanEntity> esDocBeanEntityList = esDataService.sqlSearch(EsDocBeanEntity.class, sql);
        System.out.println("gson.toJson(esDocBeanList) = " + gson.toJson(esDocBeanEntityList));
    }

    @Test
    public void bbossQueryTest() {
        //TODO 需要yml中配置bboss相关属性才可使用
        ClientInterface clientUtil = ElasticSearchHelper.getRestClientUtil();
        SQLResult<EsDocBeanEntity> sqlResult = clientUtil.fetchQuery(EsDocBeanEntity.class, "{\"query\": \"SELECT * FROM ems\"}");
        List<EsDocBeanEntity> datas = sqlResult.getDatas();
        System.out.println("gson.toJson(datas) = " + gson.toJson(datas));
    }
    

    private EsDocBeanEntity createOne() {
        EsDocBeanEntity b1 = new EsDocBeanEntity("XX" + RandomUtils.nextInt(1, 10000), "XX" + RandomUtils.nextInt(1, 10000), "xxx" + RandomUtils.nextInt(1, 10000), RandomUtils.nextInt(1, 10000));
        EsDocBeanEntity save = esDataService.save(b1);
        try {
            //延迟一下,等待es执行
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return save;
    }

    private boolean deleteOne(EsDocBeanEntity esDocBeanEntity) {
        return esDataService.delete(EsDocBeanEntity.class, esDocBeanEntity.getId());
    }

Заключительные замечания:

Поскольку это первое издание, код относительно груб. Но цель все равно достигнута, а новые возможности нужно расширять позже. Это новый, так что я надеюсь дать мне легкий спрей...