Elasticsearch High Level REST Client

Compatibilityhtml

The Java High Level REST Client requires Java 1.8 and depends on the Elasticsearch core project. The client version is the same as the Elasticsearch version that the client was developed for. It accepts the same request arguments as the TransportClient and returns the same response objects. See the Migration Guide if you need to migrate an application from TransportClient to the new REST client.java

 

The High Level Client is guaranteed to be able to communicate with any Elasticsearch node running on the same major version and greater or equal minor version. It doesn’t need to be in the same minor version as the Elasticsearch nodes it communicates with, as it is forward compatible meaning that it supports communicating with later versions of Elasticsearch than the one it was developed for.node

 

The 6.0 client is able to communicate with any 6.x Elasticsearch node, while the 6.1 client is for sure able to communicate with 6.1, 6.2 and any later 6.x version, but there may be incompatibility issues when communicating with a previous Elasticsearch node version, for instance between 6.1 and 6.0, in case the 6.1 client supports new request body fields for some APIs that are not known by the 6.0 node(s).mysql

 

It is recommended to upgrade the High Level Client when upgrading the Elasticsearch cluster to a new major version, as REST API breaking changes may cause unexpected results depending on the node that is hit by the request, and newly added APIs will only be supported by the newer version of the client. The client should always be updated last, once all of the nodes in the cluster have been upgraded to the new major version.git

Test Casegithub

ES:5.2.2web

POMspring

<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.4</version>
</dependency>

<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.2.4</version>
</dependency>

<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.2.4</version>
</dependency>

Initialization
sql

RestHighLevelClient instance needs a REST low-level client builder to be built as follows:apache

RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 9201, "http")));

The high-level client will internally create the low-level client used to perform requests based on the provided builder. That low-level client maintains a pool of connections and starts some threads so you should close the high-level client when you are well and truly done with it and it will in turn close the internal low-level client to free those resources. This can be done through the close:

client.close();

In the rest of this documentation about the Java High Level Client, the RestHighLevelClient instance will be referenced as client.

Supported APIs

The Java High Level REST Client supports the following APIs:

package com.ftofs.esclient;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.ftofs.esclient.common.ESAnnotation.IndexAnnotation;
import com.ftofs.esclient.common.JsonHelper;
import com.ftofs.esclient.vo.CommentResultVo;
import com.ftofs.esclient.vo.ImResultVo;
import com.ftofs.esclient.vo.PostResultVo;
import com.ftofs.esclient.vo.SearchCommentResultVo;
import com.ftofs.esclient.vo.SearchImResultVo;
import com.ftofs.esclient.vo.SearchPostResultVo;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.HttpAsyncResponseConsumerFactory;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Component
public class  ESRestService {
    private RestHighLevelClient client = null;
    private RestClient lowClient = null;
    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${esHost}")
    private String esHost;

    @Value("${esPort}")
    private int esPort;

    @Value("${esScheme}")
    private String esScheme;

    @Value("${esIndexImMessage}")
    private String esIndexImMessage;

    @Value("${esTypeImMessage}")
    private String esTypeImMessage;

    @Value("${esIndexWantPost}")
    private String esIndexWantPost;

    @Value("${esTypeWantPost}")
    private String esTypeWantPost;

    @Value("${esIndexWantComment}")
    private String esIndexWantComment;

    @Value("${esTypeWantComment}")
    private String esTypeWantComment;

    public void imReindexRange(List<ImResultVo> imResultVoList) {
        bulkInsert(esIndexImMessage, esTypeImMessage, imResultVoList);
    }

    public void postReindexRange(List<PostResultVo> postResultVoList) {
        bulkInsert(esIndexWantPost, esTypeWantPost, postResultVoList);
    }

    public void commentReindexRange(List<CommentResultVo> commentResultVoList) {
        bulkInsert(esIndexWantComment, esTypeWantComment, commentResultVoList);
    }

    public SearchCommentResultVo wantCommentSearch(HashMap<String, Object> queryMap) {
        StringBuilder entity = new StringBuilder();
        entity.append("{");
        entity.append(getWantCommentQueryPage(queryMap));
        entity.append("\"query\" : {\"bool\" : { \"must\" : [");
        entity.append(getWantCommentQuerySearch(queryMap));
        entity.append(getWantCommentQueryRange(queryMap));
        entity.append("]");
        entity.append(getWantCommentQueryFilter(queryMap));
        entity.append("}}");
        entity.append(getWantCommentQueryString(queryMap));
        entity.append(getWantCommentQuerySort(queryMap));
        entity.append(getWantCommentQueryAggs());
        entity.append("}");

        logger.info(entity.toString());

        HttpEntity httpEntity = new StringEntity(entity.toString(), "utf-8");
        HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory =
                new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024);

        SearchCommentResultVo searchCommentResultVo = new SearchCommentResultVo();

        try {
            Response response = lowClient.performRequest(
                    "GET", "/" + esIndexWantComment + "/_search", new HashMap<>(), httpEntity, consumerFactory);

            String responseBody = EntityUtils.toString(response.getEntity());
            JsonNode jsonNode = JsonHelper.toJsonNode(responseBody);
            logger.info(responseBody);
            searchCommentResultVo.setTotal(jsonNode.get("hits").get("total").asInt());
            searchCommentResultVo.setResultList(getSearchCommentResultVoList(jsonNode.get("hits").get("hits")));
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }

        return searchCommentResultVo;
    }

    public SearchPostResultVo wantPostSearch(HashMap<String, Object> queryMap) {
        StringBuilder entity = new StringBuilder();
        entity.append("{");
        entity.append(getWantPostQueryPage(queryMap));
        entity.append("\"query\" : {\"bool\" : { \"must\" : [");
        entity.append(getWantPostQuerySearch(queryMap));
        entity.append(getWantPostQueryFilterPhrase(queryMap));
        entity.append(getWantPostQueryRange(queryMap));
        entity.append("]");
        entity.append(getWantPostQueryFilter(queryMap));
        entity.append("}}");
        entity.append(getWantPostQueryString(queryMap));
        entity.append(getWantPostQuerySort(queryMap));
        entity.append(getWantPostQueryAggs());
        entity.append(getWantPostQuerySource(queryMap));
        entity.append("}");

        logger.info(entity.toString());

        HttpEntity httpEntity = new StringEntity(entity.toString(), "utf-8");
        HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory =
                new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024);

        SearchPostResultVo searchPostResultVo = new SearchPostResultVo();

        try {
            Response response = lowClient.performRequest(
                    "GET", "/" + esIndexWantPost + "/_search", new HashMap<>(), httpEntity, consumerFactory);

            String responseBody = EntityUtils.toString(response.getEntity());
            JsonNode jsonNode = JsonHelper.toJsonNode(responseBody);
            logger.info(responseBody);
            searchPostResultVo.setTotal(jsonNode.get("hits").get("total").asInt());
            searchPostResultVo.setResultList(getSearchPostResultVoList(jsonNode.get("hits").get("hits")));
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }

        return searchPostResultVo;
    }

    public SearchImResultVo imMessageSearch(HashMap<String, Object> queryMap) {
        //es <5.4.0 不支持高級查詢語法
//        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.query(QueryBuilders.termQuery("targetType", "users"));
//        sourceBuilder.query(QueryBuilders.termQuery("messageType", "txt"));
//        sourceBuilder.from(0);
//        sourceBuilder.size(5);
//        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//
//        QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("targetType", "users")
//                .fuzziness(Fuzziness.AUTO)
//                .prefixLength(3)
//                .maxExpansions(10);
//
//        sourceBuilder.query(matchQueryBuilder);
//
//        SimpleQueryStringBuilder simpleQueryStringBuilder = new SimpleQueryStringBuilder("users").field("targetType");
//        sourceBuilder.query(simpleQueryStringBuilder);
//
//        QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder("users").field("targetType");
//        sourceBuilder.query(queryStringQueryBuilder);
//
//        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
//        sourceBuilder.query(queryBuilder);
//
//        SearchRequest searchRequest = new SearchRequest(esIndexImMessage);
//        searchRequest.types(esTypeImMessage);
//        searchRequest.source(sourceBuilder);
//
//        try {
//
//            SearchResponse searchResponse = client.search(searchRequest);
//            SearchHits hits = searchResponse.getHits();
//
//            long totalHits = hits.getTotalHits();
//            float maxScore = hits.getMaxScore();
//
//            SearchHit[] searchHits = hits.getHits();
//            for (SearchHit hit : searchHits) {
//                String index = hit.getIndex();
//                String type = hit.getType();
//                String id = hit.getId();
//                float score = hit.getScore();
//
//                //取_source字段值
//                String sourceAsString = hit.getSourceAsString(); //取成json串
//                Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 取成map對象
//                logger.info("totalHits:" + totalHits + " maxScore:" + maxScore + " index:" + index + "  type:" + type + "  id:" + id + " score:" + score);
//                logger.info(sourceAsString);
//            }
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        StringBuilder entity = new StringBuilder();
        entity.append("{");
        entity.append(getImMessageQueryPage(queryMap));
        entity.append("\"query\" : {\"bool\" : { \"must\" : [");
        entity.append(getImMessageQuerySearch(queryMap));
        entity.append(getImMessageQueryRange(queryMap));
        entity.append("]");
        entity.append(getImMessageQueryFilter(queryMap));
        entity.append("}}");
        entity.append(getImMessageQueryString(queryMap));
        entity.append(getImMessageQuerySort(queryMap));
        entity.append(getImMessageQueryAggs());
        entity.append("}");

        logger.info(entity.toString());

        //queryMap = Collections.singletonMap("pretty", "true");

        HttpEntity httpEntity = new StringEntity(entity.toString(), "utf-8");
        HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory =
                new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024);

        SearchImResultVo searchImResultVo = new SearchImResultVo();

        try {
            Response response = lowClient.performRequest(
                    "GET", "/" + esIndexImMessage + "/_search", new HashMap<>(), httpEntity, consumerFactory);

            String responseBody = EntityUtils.toString(response.getEntity());
            JsonNode jsonNode = JsonHelper.toJsonNode(responseBody);
            logger.info(responseBody);
            searchImResultVo.setTotal(jsonNode.get("hits").get("total").asInt());
            searchImResultVo.setResultList(getSearchImResultVoList(jsonNode.get("hits").get("hits")));
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }

        return searchImResultVo;
    }

    private List<ImResultVo> getSearchImResultVoList(JsonNode hitsNode) {
        List<ImResultVo> searchImResultVoList = new ArrayList<>();
        if (hitsNode.isArray()) {
            for (JsonNode hit : hitsNode) {
                searchImResultVoList.add(JsonHelper.toGenericObject(hit.get("_source").toString(), new TypeReference<ImResultVo>() {
                }));
            }
        }
        return searchImResultVoList;
    }

    private List<PostResultVo> getSearchPostResultVoList(JsonNode hitsNode) {
        List<PostResultVo> searchPostResultList = new ArrayList<>();
        if (hitsNode.isArray()) {
            for (JsonNode hit : hitsNode) {
                searchPostResultList.add(JsonHelper.toGenericObject(hit.get("_source").toString(), new TypeReference<PostResultVo>() {
                }));
            }
        }
        return searchPostResultList;
    }

    private List<CommentResultVo> getSearchCommentResultVoList(JsonNode hitsNode) {
        List<CommentResultVo> searchCommentResultList = new ArrayList<>();
        if (hitsNode.isArray()) {
            for (JsonNode hit : hitsNode) {
                searchCommentResultList.add(JsonHelper.toGenericObject(hit.get("_source").toString(), new TypeReference<CommentResultVo>() {
                }));
            }
        }
        return searchCommentResultList;
    }


//    public void update(String index, String type, String id, HashMap<String, Object> jsonMap) {
//        UpdateRequest updateRequest = new UpdateRequest(index, type, id).doc(jsonMap);
//        ActionListener<UpdateResponse> listener = new ActionListener<UpdateResponse>() {
//            @Override
//            public void onResponse(UpdateResponse updateResponse) {
//                //若是執行成功,則調用onResponse方法;
//                logger.info(String.format("index %s", updateResponse.getGetResult()));
//            }
//
//            @Override
//            public void onFailure(Exception e) {
//                //若是失敗,則調用onFailure方法。
//                logger.error(e.getMessage());
//            }
//        };
//
//        client.updateAsync(updateRequest, listener);
//    }

    public <T> boolean bulkInsert(String index, String type, List<T> list) {
        boolean bulkInsertResult = false;

        BulkRequest request = new BulkRequest();
        request.timeout(TimeValue.timeValueMinutes(2));
        request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
        request.waitForActiveShards(2);

        for (T t : list) {
            String indexField = t.getClass().getAnnotation(IndexAnnotation.class).field();
            try {
                request.add(new IndexRequest(index, type, t.getClass().getDeclaredField(indexField).get(t).toString()).source(JsonHelper.toJson(t), XContentType.JSON));
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        try {
            BulkResponse bulkResponse = client.bulk(request);
            if (!bulkResponse.hasFailures()) {
                bulkInsertResult = true;
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }

        return bulkInsertResult;
    }

    public <T> void insertOrUpdate(String index, String type, T t) {
        try {
            String indexField = t.getClass().getAnnotation(IndexAnnotation.class).field();
            IndexRequest indexRequest = new IndexRequest(index, type, t.getClass().getDeclaredField(indexField).get(t).toString());
            indexRequest.source(JsonHelper.toJson(t), XContentType.JSON);
            ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
                @Override
                public void onResponse(IndexResponse indexResponse) {
                    //若是執行成功,則調用onResponse方法;
                    logger.info(String.format("%s %s %s", indexResponse.getIndex(), indexResponse.getId(), indexResponse.getResult()));
                }

                @Override
                public void onFailure(Exception e) {
                    //若是失敗,則調用onFailure方法。
                    logger.error(e.getMessage());
                }
            };

            client.indexAsync(indexRequest, listener);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public void createImMessageIndex() {
        //先刪除再創建
        deleteIndex(esIndexImMessage);
        createIndex(esIndexImMessage, esTypeImMessage, createImMessageMapping());
    }

    public void createWantPostIndex() {
        //先刪除再創建
        deleteIndex(esIndexWantPost);
        createIndex(esIndexWantPost, esTypeWantPost, createWantPostMapping());
    }

    public void createWantCommentIndex() {
        //先刪除再創建
        deleteIndex(esIndexWantComment);
        createIndex(esIndexWantComment, esTypeWantComment, createWantCommentMapping());
    }

    public boolean deleteImMessageDocument(String id) {
        return deleteDocument(esIndexImMessage, esTypeImMessage, id);
    }

    public boolean deleteWantPostDocument(String id) {
        return deleteDocument(esIndexWantPost, esTypeWantPost, id);
    }


    public boolean deleteWantCommentDocument(String id) {
        return deleteDocument(esIndexWantComment, esTypeWantComment, id);
    }

    protected String createWantCommentMapping() {
        String json = "";
        try {
            XContentBuilder mapping = XContentFactory.jsonBuilder()
                    .startObject()
                    .startObject(esTypeWantComment)
                    .startObject("properties") //設置之定義字段

                    .startObject("commentId")//字段id
                    .field("type", "long")//設置數據類型
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentType")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentChannel")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("content")
                    .field("type", "text")
                    .field("index", "analyzed")
                    .endObject()

                    .startObject("deep")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("relateStoreId")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("relateCommonId")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("relatePostId")
                    .field("type", "long")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("replyCommentId")
                    .field("type", "long")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("createBy")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("createTime")
                    .field("type", "date")
                    .field("index", "not_analyzed")
                    .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
                    .endObject()

                    .startObject("commentState")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentLike")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentUnlike")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentFavor")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentReply")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("commentShare")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("images")
                    .field("type", "nested")
                    .endObject()

                    .endObject()
                    .endObject()
                    .endObject();

            json = mapping.string();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return json;
    }

    protected String createWantPostMapping() {
        String json = "";
        try {
            XContentBuilder mapping = XContentFactory.jsonBuilder()
                    .startObject()
                    .startObject(esTypeWantPost)
                    .startObject("properties") //設置之定義字段

                    .startObject("postId")//字段id
                    .field("type", "long")//設置數據類型
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("title")
                    .field("type", "text")
                    .field("index", "analyzed")
                    .endObject()

                    .startObject("content")
                    .field("type", "text")
                    .field("index", "analyzed")
                    .endObject()

                    .startObject("postCategory")
                    .field("type", "keyword")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("coverImage")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postType")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postTag")
                    .field("type", "text")
                    .field("index", "analyzed")
                    .endObject()

                    .startObject("keyword")
                    .field("type", "text")
                    .field("index", "analyzed")
                    .endObject()

                    .startObject("createTime")
                    .field("type", "date")
                    .field("index", "not_analyzed")
                    .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
                    .endObject()

                    .startObject("createBy")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("isPublish")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("isDelete")
                    .field("type", "byte")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("expiresDate")
                    .field("type", "date")
                    .field("index", "not_analyzed")
                    .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
                    .endObject()

                    .startObject("budgetPrice")
                    .field("type", "scaled_float")
                    .field("scaling_factor", "10")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postView")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postLike")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postUnlike")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postFavor")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postReply")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("postShare")
                    .field("type", "integer")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("approveReason")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("comments")
                    .field("type", "nested")
                    .endObject()

                    .startObject("images")
                    .field("type", "nested")
                    .endObject()

                    .endObject()
                    .endObject()
                    .endObject();

            json = mapping.string();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return json;
    }

    protected String createImMessageMapping() {
        String json = "";
        try {
            XContentBuilder mapping = XContentFactory.jsonBuilder()
                    .startObject()
                    .startObject(esTypeImMessage)
                    .startObject("properties") //設置之定義字段

                    .startObject("id")//字段id
                    .field("type", "long")//設置數據類型
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("sendFrom")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("target")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("targetType")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("groupName")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("messageContent")
                    .field("type", "text")
                    .field("index", "analyzed")
                    .endObject()

                    .startObject("messageType")
                    .field("type", "text")
                    .field("index", "not_analyzed")
                    .endObject()

                    .startObject("sendTime")
                    .field("type", "date")
                    .field("index", "not_analyzed")
                    .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")
                    .endObject()

                    .endObject()
                    .endObject()
                    .endObject();

            json = mapping.string();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return json;
    }

    protected void createIndex(String index, String type, String source) {
        CreateIndexRequest request = new CreateIndexRequest(index);//建立索引
        //建立的每一個索引均可以有與之關聯的特定設置。
        request.settings(Settings.builder()
                .put("index.number_of_shards", 5)
                .put("index.number_of_replicas", 1)
        );
        //建立索引時建立文檔類型映射
        request.mapping(type,//類型定義
                source,//類型映射,須要的是一個JSON字符串
                XContentType.JSON);

        //可選參數
        request.timeout(TimeValue.timeValueMinutes(2));//超時,等待全部節點被確認(使用TimeValue方式)

        request.masterNodeTimeout(TimeValue.timeValueMinutes(1));//鏈接master節點的超時時間(使用TimeValue方式)

        request.waitForActiveShards(2);//在建立索引API返回響應以前等待的活動分片副本的數量,以int形式表示。

        ActionListener<CreateIndexResponse> listener = new ActionListener<CreateIndexResponse>() {
            @Override
            public void onResponse(CreateIndexResponse createIndexResponse) {
                //若是執行成功,則調用onResponse方法;
                logger.info(String.format("create %s mapping %s", createIndexResponse.index(), createIndexResponse.isAcknowledged()));
            }

            @Override
            public void onFailure(Exception e) {
                //若是失敗,則調用onFailure方法。
                logger.error(e.getMessage());
            }
        };
        client.indices().createAsync(request, listener);//要執行的CreateIndexRequest和執行完成時要使用的ActionListener
    }

    protected boolean deleteIndex(String index) {
        boolean acknowledged = false;
        DeleteIndexRequest request = new DeleteIndexRequest(index);//指定要刪除的索引名稱
        //可選參數:
        request.timeout(TimeValue.timeValueMinutes(2)); //設置超時,等待全部節點確認索引刪除(使用TimeValue形式)

        request.masterNodeTimeout(TimeValue.timeValueMinutes(1));////鏈接master節點的超時時間(使用TimeValue方式)

        //設置IndicesOptions控制如何解決不可用的索引以及如何擴展通配符表達式
        request.indicesOptions(IndicesOptions.lenientExpandOpen());

        try {
            //同步執行
            DeleteIndexResponse deleteIndexResponse = client.indices().delete(request);
            //返回的DeleteIndexResponse容許檢索有關執行的操做的信息,以下所示:
            acknowledged = deleteIndexResponse.isAcknowledged();//是否全部節點都已確認請求
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.NOT_FOUND) {
                //若是沒有找到要刪除的索引,要執行某些操做
            }
        } catch (IOException e) {

        }

        return acknowledged;
    }

    protected boolean deleteDocument(String index, String type, String id) {
        boolean deleted = false;
        DeleteRequest deleteRequest = new DeleteRequest(index, type, id);
        //可選參數:
        deleteRequest.timeout(TimeValue.timeValueMinutes(2));
        deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);

        try {
            //同步執行
            DeleteResponse deleteResponse = client.delete(deleteRequest);
            if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {

            } else if (deleteResponse.getResult() == DocWriteResponse.Result.DELETED) {
                deleted = true;
            }
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.CONFLICT) {

            }
        } catch (IOException e) {

        }

        return deleted;
    }

    private String getImMessageQueryPage(HashMap<String, Object> params) {
        int page = 0;
        int size = 0;

        if(params.containsKey("page")) {
            String paramPage = params.get("page").toString();
            if (!Strings.isEmpty(paramPage)) {
                page = Integer.valueOf(paramPage);
            }
        }

        if(params.containsKey("size")) {
            String paramSize = params.get("size").toString();
            if (!Strings.isEmpty(paramSize)) {
                size = Integer.valueOf(paramSize);
            }
        }

        if (page <= 0) {
            page = 1;
        }
        if (size <= 0) {
            size = 10;
        }

        int from = (page - 1) * size;
        return "\"from\":" + from + ",\"size\":" + size + ",";
    }

    private String getImMessageQuerySearch(HashMap<String, Object> params) {
        if (params.containsKey("messageContent")) {
            return "{\"match\": {\"messageContent\": \"" + params.get("messageContent") + "\"}}";
        }
        return "{\"match_all\":{}}";
    }

    private String getImMessageQueryRange(HashMap<String, Object> params) {
        String rangeString = "";
        if (params.containsKey("sendTimeFrom")) {
            rangeString += ",{\"range\": {\"sendTime\": {\"gte\": \"" + params.get("sendTimeFrom") + "\"}}}";
        }

        if (params.containsKey("sendTimeTo")) {
            rangeString += ",{\"range\": {\"sendTime\": {\"lte\": \"" + params.get("sendTimeTo") + "\"}}}";
        }

        if (params.containsKey("idFrom")) {
            rangeString += ",{\"range\": {\"id\": {\"gte\":" + params.get("idFrom") + "}}}";
        }

        if (params.containsKey("idTo")) {
            rangeString += ",{\"range\": {\"id\": {\"lte\":" + params.get("idTo") + "}}}";
        }

        return rangeString;
    }

    private String getImMessageQueryFilter(HashMap<String, Object> params) {
        String filterString = "";

        if (params.containsKey("id")) {
            filterString += ",{\"term\": { \"id\":" + params.get("id") + "}}";
        }

        if (params.containsKey("sendFrom")) {
            filterString += ",{\"term\": { \"sendFrom\":\"" + params.get("sendFrom") + "\"}}";
        }

        if (params.containsKey("groupName")) {
            filterString += ",{\"term\": { \"groupName\":\"" + params.get("groupName") + "\"}}";
        }

        if (params.containsKey("messageType")) {
            filterString += ",{\"term\": { \"messageType\":\"" + params.get("messageType") + "\"}}";
        }

        if (params.containsKey("target")) {
            filterString += ",{\"term\": { \"target\":\"" + params.get("target") + "\"}}";
        }

        if (params.containsKey("targetType")) {
            filterString += ",{\"term\": { \"targetType\":\"" + params.get("targetType") + "\"}}";
        }

        if (!filterString.equals("")) {
            filterString = ",\"filter\": [" + filterString.substring(1, filterString.length()) + "]";
        }

        return filterString;
    }

    private String getImMessageQuerySort(HashMap<String, Object> params) {
        if (params.containsKey("sort")) {
            return ",\"sort\": [{\"" + params.get("sort")
                    + "\":{\"order\": \"" + params.get("order")
                    + "\"}}, {\"id\": {\"order\": \"desc\"}}]";
        }
        return "";
    }

    private String getImMessageQueryAggs() {
        return ",\"aggs\": { }";
    }

    private String getImMessageQueryString(HashMap<String, Object> params) {
        if (params.containsKey("query")) {
            return ",\"query\": {\"query_string\": { \"query\":\"" + params.get("query") + "\"}}";
        }

        return "";
    }

    private String getWantPostQueryPage(HashMap<String, Object> params) {
        int page = 0;
        int size = 0;

        if(params.containsKey("page")) {
            String paramPage = params.get("page").toString();
            if (!Strings.isEmpty(paramPage)) {
                page = Integer.valueOf(paramPage);
            }
        }

        if(params.containsKey("size")) {
            String paramSize = params.get("size").toString();
            if (!Strings.isEmpty(paramSize)) {
                size = Integer.valueOf(paramSize);
            }
        }

        if (page <= 0) {
            page = 1;
        }
        if (size <= 0) {
            size = 10;
        }

        int from = (page - 1) * size;
        return "\"from\":" + from + ",\"size\":" + size + ",";
    }

    private String getWantPostQuerySearch(HashMap<String, Object> params) {
        if (params.containsKey("content")) {
            return "{\"match\": {\"content\": \"" + params.get("content") + "\"}}";
        }

        if (params.containsKey("title")) {
            return "{\"match\": {\"title\": \"" + params.get("title") + "\"}}";
        }

        return "{\"match_all\":{}}";
    }

    private String getWantPostQueryRange(HashMap<String, Object> params) {
        String rangeString = "";
        if (params.containsKey("createTimeFrom")) {
            rangeString += ",{\"range\": {\"createTime\": {\"gte\": \"" + params.get("createTimeFrom") + "\"}}}";
        }

        if (params.containsKey("createTimeTo")) {
            rangeString += ",{\"range\": {\"createTime\": {\"lte\": \"" + params.get("createTimeTo") + "\"}}}";
        }

        if (params.containsKey("expiresDateFrom")) {
            rangeString += ",{\"range\": {\"expiresDate\": {\"gte\": \"" + params.get("expiresDateFrom") + "\"}}}";
        }

        if (params.containsKey("expiresDateTo")) {
            rangeString += ",{\"range\": {\"expiresDate\": {\"lte\": \"" + params.get("expiresDateTo") + "\"}}}";
        }

        if (params.containsKey("budgetPriceFrom")) {
            rangeString += ",{\"range\": {\"budgetPrice\": {\"lte\": " + params.get("budgetPriceFrom") + "}}}";
        }

        if (params.containsKey("budgetPriceTo")) {
            rangeString += ",{\"range\": {\"budgetPrice\": {\"lte\": " + params.get("budgetPriceTo") + "}}}";
        }

        if (params.containsKey("postIdFrom")) {
            rangeString += ",{\"range\": {\"postId\": {\"gte\":" + params.get("postIdFrom") + "}}}";
        }

        if (params.containsKey("postIdTo")) {
            rangeString += ",{\"range\": {\"postId\": {\"lte\":" + params.get("postIdTo") + "}}}";
        }

        return rangeString;
    }

    private String getWantPostQueryFilterPhrase(HashMap<String, Object> params){
        String phraseString = "";
        if (params.containsKey("postTag")) {
            phraseString += ",{\"match_phrase\": { \"postTag\":\"" + params.get("postTag") + "\"}}";
        }

        if (params.containsKey("keyword")) {
            phraseString += ",{\"match_phrase\": { \"keyword\":\"" + params.get("keyword") + "\"}}";
        }

        return phraseString;
    }

    private String getWantPostQueryFilter(HashMap<String, Object> params) {
        String filterString = "";

        if (params.containsKey("postId")) {
            filterString += ",{\"term\": { \"postId\":" + params.get("postId") + "}}";
        }

        if (params.containsKey("postCategory")) {
            filterString += ",{\"term\": { \"postCategory\":\"" + params.get("postCategory") + "\"}}";
        }

        if (params.containsKey("postType")) {
            filterString += ",{\"term\": { \"postType\":\"" + params.get("postType") + "\"}}";
        }

        if (params.containsKey("createBy")) {
            filterString += ",{\"term\": { \"createBy\":\"" + params.get("createBy") + "\"}}";
        }

        if (params.containsKey("isPublish")) {
            filterString += ",{\"term\": { \"isPublish\":\"" + params.get("isPublish") + "\"}}";
        }

        if (params.containsKey("isDelete")) {
            filterString += ",{\"term\": { \"isDelete\":\"" + params.get("isDelete") + "\"}}";
        }

        if (!filterString.equals("")) {
            filterString = ",\"filter\": [" + filterString.substring(1, filterString.length()) + "]";
        }

        return filterString;
    }

    private String getWantPostQuerySort(HashMap<String, Object> params) {
        if (params.containsKey("sort")) {
            return ",\"sort\": [{\"" + params.get("sort")
                    + "\":{\"order\": \"" + params.get("order")
                    + "\"}}, {\"postId\": {\"order\": \"desc\"}}]";
        }
        return "";
    }

    private String getWantPostQueryAggs() {
        return ",\"aggs\": { }";
    }

    private String getWantPostQueryString(HashMap<String, Object> params) {
        if (params.containsKey("query")) {
            return ",\"query\": {\"query_string\": { \"query\":\"" + params.get("query") + "\"}}";
        }

        return "";
    }

    private String getWantPostQuerySource(HashMap<String, Object> params) {
        if (params.containsKey("source")) {
            return ",\"_source\": " + JsonHelper.toJson(params.get("source"));
        }
        return ",\"_source\": []";
    }


    private String getWantCommentQueryPage(HashMap<String, Object> params) {
        int page = 0;
        int size = 0;

        if(params.containsKey("page")) {
            String paramPage = params.get("page").toString();
            if (!Strings.isEmpty(paramPage)) {
                page = Integer.valueOf(paramPage);
            }
        }

        if(params.containsKey("size")) {
            String paramSize = params.get("size").toString();
            if (!Strings.isEmpty(paramSize)) {
                size = Integer.valueOf(paramSize);
            }
        }

        if (page <= 0) {
            page = 1;
        }
        if (size <= 0) {
            size = 10;
        }

        int from = (page - 1) * size;
        return "\"from\":" + from + ",\"size\":" + size + ",";
    }

    private String getWantCommentQuerySearch(HashMap<String, Object> params) {
        if (params.containsKey("content")) {
            return "{\"match\": {\"content\": \"" + params.get("content") + "\"}}";
        }
        return "{\"match_all\":{}}";
    }

    private String getWantCommentQueryRange(HashMap<String, Object> params) {
        String rangeString = "";
        if (params.containsKey("createTimeFrom")) {
            rangeString += ",{\"range\": {\"createTime\": {\"gte\": \"" + params.get("createTimeFrom") + "\"}}}";
        }

        if (params.containsKey("createTimeTo")) {
            rangeString += ",{\"range\": {\"createTime\": {\"lte\": \"" + params.get("createTimeTo") + "\"}}}";
        }

        if (params.containsKey("commentIdFrom")) {
            rangeString += ",{\"range\": {\"commentId\": {\"gte\":" + params.get("commentIdFrom") + "}}}";
        }

        if (params.containsKey("commentIdTo")) {
            rangeString += ",{\"range\": {\"commentId\": {\"lte\":" + params.get("commentIdTo") + "}}}";
        }

        return rangeString;
    }

    private String getWantCommentQueryFilter(HashMap<String, Object> params) {
        String filterString = "";

        if (params.containsKey("commentId")) {
            filterString += ",{\"term\": { \"commentId\":" + params.get("commentId") + "}}";
        }

        if (params.containsKey("commentType")) {
            filterString += ",{\"term\": { \"commentType\":" + params.get("commentType") + "}}";
        }

        if (params.containsKey("commentChannel")) {
            filterString += ",{\"term\": { \"commentChannel\":" + params.get("commentChannel") + "}}";
        }

        if (params.containsKey("deep")) {
            filterString += ",{\"term\": { \"deep\":" + params.get("deep") + "}}";
        }

        if (params.containsKey("relateStoreId")) {
            filterString += ",{\"term\": { \"relateStoreId\":" + params.get("relateStoreId") + "}}";
        }

        if (params.containsKey("relateCommonId")) {
            filterString += ",{\"term\": { \"relateCommonId\":" + params.get("relateCommonId") + "}}";
        }

        if (params.containsKey("relatePostId")) {
            filterString += ",{\"term\": { \"relatePostId\":" + params.get("relatePostId") + "}}";
        }

        if (params.containsKey("replyCommentId")) {
            filterString += ",{\"term\": { \"replyCommentId\":" + params.get("replyCommentId") + "}}";
        }

        if (params.containsKey("commentState")) {
            filterString += ",{\"term\": { \"commentState\":" + params.get("commentState") + "}}";
        }

        if (params.containsKey("createBy")) {
            filterString += ",{\"term\": { \"createBy\":\"" + params.get("createBy") + "\"}}";
        }

        if (!filterString.equals("")) {
            filterString = ",\"filter\": [" + filterString.substring(1, filterString.length()) + "]";
        }

        return filterString;
    }

    private String getWantCommentQuerySort(HashMap<String, Object> params) {
        if (params.containsKey("sort")) {
            return ",\"sort\": [{\"" + params.get("sort")
                    + "\":{\"order\": \"" + params.get("order")
                    + "\"}}, {\"commentId\": {\"order\": \"desc\"}}]";
        }
        return "";
    }

    private String getWantCommentQueryAggs() {
        return ",\"aggs\": { }";
    }

    private String getWantCommentQueryString(HashMap<String, Object> params) {
        if (params.containsKey("query")) {
            return ",\"query\": {\"query_string\": { \"query\":\"" + params.get("query") + "\"}}";
        }

        return "";
    }

    @PostConstruct
    protected void init() {
        client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(esHost, esPort, esScheme)));

        lowClient = RestClient.builder(
                new HttpHost(esHost, esPort, esScheme)).build();
    }

    @PreDestroy
    protected void destroy() {
        if (client != null) {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (lowClient != null) {
            try {
                lowClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
ESRestService
package com.ftofs.esclient.service;

import com.ftofs.esclient.dao.ImMessageLogRepository;
import com.ftofs.esclient.dao.WantCommentImageRepository;
import com.ftofs.esclient.dao.WantCommentRepository;
import com.ftofs.esclient.dao.WantPostImageRepository;
import com.ftofs.esclient.dao.WantPostRepository;
import com.ftofs.esclient.domain.ImMessageLog;
import com.ftofs.esclient.domain.WantComment;
import com.ftofs.esclient.domain.WantPost;
import com.ftofs.esclient.vo.CommentImageResultVo;
import com.ftofs.esclient.vo.CommentResultVo;
import com.ftofs.esclient.vo.ImResultVo;
import com.ftofs.esclient.vo.PostImageResultVo;
import com.ftofs.esclient.vo.PostResultVo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

@Component
public class ReindexService {
    @Autowired
    private WantPostRepository wantPostRepository;
    @Autowired
    private WantCommentRepository wantCommentRepository;
    @Autowired
    private WantPostImageRepository wantPostImageRepository;
    @Autowired
    private WantCommentImageRepository wantCommentImageRepository;
    @Autowired
    private ImMessageLogRepository imMessageLogRepository;

    private <T> String emptyToNull(T value) {
        if (value == null) {
            return null;
        } else {
            return String.valueOf(value);
        }
    }

    /**
     * 重置全部IM消息記錄
     * @return
     */
    public List<ImResultVo> getImMessageResultVoList() {
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<ImResultVo> imResultVoList = new ArrayList<>();
        List<ImMessageLog> imMessageLogList = imMessageLogRepository.findAll();
        imMessageLogList.forEach(x -> {
            ImResultVo imResultVo = new ImResultVo();
            imResultVo.setGroupName(x.getGroupName());
            imResultVo.setId(String.valueOf(x.getId()));
            imResultVo.setMessageContent(x.getMessageContent());
            imResultVo.setMessageType(x.getMessageType());
            imResultVo.setSendFrom(x.getSendFrom());
            imResultVo.setSendTime(sdf.format(x.getSendTime()));
            imResultVo.setTarget(x.getTarget());
            imResultVo.setTargetType(x.getTargetType());

            imResultVoList.add(imResultVo);
        });

        return imResultVoList;
    }
    /**
     * 重置全部評論記錄
     * @return
     */
    public List<CommentResultVo> getCommentResultVoList() {
        SimpleDateFormat sdf =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<CommentResultVo> commentResultVoList = new ArrayList<>();
        List<WantComment> wantCommentList = wantCommentRepository.findAll();
        wantCommentList.forEach(x -> {
            CommentResultVo commentResultVo = new CommentResultVo();
            commentResultVo.setReplyCommentId(emptyToNull(x.getReplyCommentId()));
            commentResultVo.setRelateStoreId(emptyToNull(x.getRelateStoreId()));
            commentResultVo.setRelatePostId(emptyToNull(x.getRelateStoreId()));
            commentResultVo.setRelateCommonId(emptyToNull(x.getRelateCommonId()));
            commentResultVo.setDeep(emptyToNull(x.getDeep()));
            commentResultVo.setCommentUnlike(emptyToNull(x.getCommentUnlike()));
            commentResultVo.setCommentType(emptyToNull(x.getCommentType()));
            commentResultVo.setCommentState(emptyToNull(x.getCommentState()));
            commentResultVo.setCommentShare(emptyToNull(x.getCommentShare()));
            commentResultVo.setCommentReply(emptyToNull(x.getCommentReply()));
            commentResultVo.setCommentLike(emptyToNull(x.getCommentLike()));
            commentResultVo.setCommentId(emptyToNull(x.getCommentId()));
            commentResultVo.setCommentFavor(emptyToNull(x.getCommentFavor()));
            commentResultVo.setCommentChannel(emptyToNull(x.getCommentChannel()));
            commentResultVo.setCreateTime(sdf.format(x.getCreateTime()));
            commentResultVo.setCreateBy(x.getCreateBy());
            commentResultVo.setContent(x.getContent());

            List<CommentImageResultVo> commentImages = new ArrayList<>();
            List<String> imageUrlList = wantCommentImageRepository.findWantCommentImagesByCommentId(x.getCommentId());
            imageUrlList.forEach(url -> {
                CommentImageResultVo commentImageResultVo = new CommentImageResultVo();
                commentImageResultVo.setImageUrl(url);
                commentImages.add(commentImageResultVo);
            });
            commentResultVo.setImages(commentImages);

            commentResultVoList.add(commentResultVo);
        });

        return commentResultVoList;
    }

    /**
     * 重置全部貼文記錄
     * @return
     */
    public List<PostResultVo> getPostResultVoList() {
        SimpleDateFormat sdfDateTime =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfDate =  new SimpleDateFormat("yyyy-MM-dd");
        List<PostResultVo> postResultVoList = new ArrayList<>();
        List<WantPost> wantPostList = wantPostRepository.findAll();
        wantPostList.forEach(x -> {
            PostResultVo postResultVo = new PostResultVo();
            postResultVo.setBudgetPrice(emptyToNull(x.getBudgetPrice()));
            postResultVo.setContent(x.getContent());
            postResultVo.setCreateBy(x.getCreateBy());
            postResultVo.setCreateTime(sdfDateTime.format(x.getCreateTime()));
            postResultVo.setExpiresDate(sdfDate.format(x.getExpiresDate()));
            postResultVo.setIsDelete(emptyToNull(x.getIsDelete()));
            postResultVo.setIsPublish(emptyToNull(x.getIsPublish()));
            postResultVo.setKeyword(x.getKeyword());
            postResultVo.setPostCategory(x.getPostCategory());
            postResultVo.setPostId(emptyToNull(x.getPostId()));
            postResultVo.setPostTag(x.getPostTag());
            postResultVo.setPostType(emptyToNull(x.getPostType()));
            postResultVo.setPostFavor(emptyToNull(x.getPostFavor()));
            postResultVo.setPostLike(emptyToNull(x.getPostLike()));
            postResultVo.setPostUnlike(emptyToNull(x.getPostUnlike()));
            postResultVo.setPostShare(emptyToNull(x.getPostShare()));
            postResultVo.setPostReply(emptyToNull(x.getPostReply()));
            postResultVo.setPostView(emptyToNull(x.getPostView()));
            postResultVo.setTitle(x.getTitle());
            postResultVo.setCoverImage(x.getCoverImage());
            postResultVo.setApproveReason(x.getApproveReason());

            List<CommentResultVo> comments = new ArrayList<>();
            List<WantComment> wantCommentList = wantCommentRepository.findWantCommentsByPostId(x.getPostId());
            wantCommentList.forEach(y -> {
                CommentResultVo commentResultVo = new CommentResultVo();
                commentResultVo.setContent(y.getContent());
                commentResultVo.setCreateBy(y.getCreateBy());
                commentResultVo.setCreateTime(sdfDateTime.format(y.getCreateTime()));
                commentResultVo.setCommentChannel(emptyToNull(y.getCommentChannel()));
                commentResultVo.setCommentFavor(emptyToNull(y.getCommentFavor()));
                commentResultVo.setCommentId(emptyToNull(y.getCommentId()));
                commentResultVo.setCommentLike(emptyToNull(y.getCommentLike()));
                commentResultVo.setCommentReply(emptyToNull(y.getCommentReply()));
                commentResultVo.setCommentShare(emptyToNull(y.getCommentShare()));
                commentResultVo.setCommentState(emptyToNull(y.getCommentState()));
                commentResultVo.setCommentType(emptyToNull(y.getCommentType()));
                commentResultVo.setCommentUnlike(emptyToNull(y.getCommentUnlike()));
                commentResultVo.setDeep(emptyToNull(y.getDeep()));
                commentResultVo.setRelateCommonId(emptyToNull(y.getRelateCommonId()));
                commentResultVo.setRelatePostId(emptyToNull(y.getRelatePostId()));
                commentResultVo.setRelateStoreId(emptyToNull(y.getRelateStoreId()));
                commentResultVo.setReplyCommentId(emptyToNull(y.getReplyCommentId()));
                List<CommentImageResultVo> commentImages = new ArrayList<>();
                List<String> imageUrlList = wantCommentImageRepository.findWantCommentImagesByCommentId(y.getCommentId());
                imageUrlList.forEach(url -> {
                    CommentImageResultVo commentImageResultVo = new CommentImageResultVo();
                    commentImageResultVo.setImageUrl(url);
                    commentImages.add(commentImageResultVo);
                });
                commentResultVo.setImages(commentImages);
                comments.add(commentResultVo);
            });
            postResultVo.setComments(comments);

            List<PostImageResultVo> postImages = new ArrayList<>();
            List<String> imageUrlList = wantPostImageRepository.findWantPostImagesByPostId(x.getPostId());
            imageUrlList.forEach(url -> {
                PostImageResultVo postImageResultVo = new PostImageResultVo();
                postImageResultVo.setImageUrl(url);
                postImages.add(postImageResultVo);
            });
            postResultVo.setImages(postImages);

            postResultVoList.add(postResultVo);
        });

        return postResultVoList;
    }
}
ReindexService
package com.ftofs.esclient.common;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class ESAnnotation {
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface IndexAnnotation {
        String field();
    }
}
ESAnnotation
package com.ftofs.esclient.common;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

/**
 * JSON幫助類
 */
public class JsonHelper {
    private static final Logger log = LoggerFactory.getLogger(JsonHelper.class);

    final static ObjectMapper objectMapper;

    static {
        objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
    }

    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     * JSON串轉換爲Java泛型對象
     * @param <T>
     * @param jsonString JSON字符串
     * @param tr         TypeReference,例如: new TypeReference< List<FamousUser> >(){}
     * @return List對象列表
     */
    public static <T> T toGenericObject(String jsonString, TypeReference<T> tr) {

        if (jsonString == null || "".equals(jsonString)) {
            return null;
        } else {
            try {
                return (T) objectMapper.readValue(jsonString, tr);
            } catch (Exception e) {
                log.warn(jsonString);
                log.warn("json error:" + e.getMessage());
            }
        }
        return null;
    }

    /**
     * Json字符串轉Java對象
     * @param jsonString
     * @param c
     * @return
     */
    public static Object toObject(String jsonString, Class<?> c) {

        if (jsonString == null || "".equals(jsonString)) {
            return "";
        } else {
            try {
                return objectMapper.readValue(jsonString, c);
            } catch (Exception e) {
                log.warn("json error:" + e.getMessage());
            }
        }
        return null;
    }

    /**
     * Java對象轉Json字符串
     * @param object Java對象,能夠是對象,數組,List,Map等
     * @return json 字符串
     */
    public static String toJson(Object object) {
        String jsonString = "";
        try {
            jsonString = objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            log.warn("json error:" + e.getMessage());
        }
        return jsonString;
    }

    /**
     * Json字符串轉JsonNode
     * @param jsonString
     * @return
     */
    public static JsonNode toJsonNode(String jsonString) {
        try {
            return objectMapper.readTree(jsonString);
        } catch (IOException e) {
            e.printStackTrace();
            log.warn("json error:" + e.getMessage());
        }
        return null;
    }

}
JsonHelper
package com.ftofs.esclient.controller;

import com.ftofs.esclient.ESRestService;
import com.ftofs.esclient.service.ReindexService;
import com.ftofs.esclient.vo.CommentResultVo;
import com.ftofs.esclient.vo.ImResultVo;
import com.ftofs.esclient.vo.PostResultVo;
import com.ftofs.esclient.vo.SearchCommentResultVo;
import com.ftofs.esclient.vo.SearchImResultVo;
import com.ftofs.esclient.vo.SearchPostResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("")
@Api(tags="ESRestController")
public class ESRestController {
    @Autowired
    private ESRestService restService;

    @Autowired
    private ReindexService reindexService;

    @Value("${esIndexImMessage}")
    private String esIndexImMessage;

    @Value("${esTypeImMessage}")
    private String esTypeImMessage;

    @Value("${esIndexWantPost}")
    private String esIndexWantPost;

    @Value("${esTypeWantPost}")
    private String esTypeWantPost;

    @Value("${esIndexWantComment}")
    private String esIndexWantComment;

    @Value("${esTypeWantComment}")
    private String esTypeWantComment;

    @PostMapping("/im/init")
    @ApiOperation(value = "IM消息索引初始化")
    public void imMessageInit() {
        restService.createImMessageIndex();
    }

    @PostMapping("/im/delete/{id}")
    @ApiOperation(value = "刪除IM消息")
    public void deleteImMessageDocument(@PathVariable String id) {
        restService.deleteImMessageDocument(id);
    }

    @PostMapping("/post/init")
    @ApiOperation(value = "貼文索引初始化")
    public void wantPostInit() {
        restService.createWantPostIndex();
    }

    @PostMapping("/post/delete/{id}")
    @ApiOperation(value = "刪除貼文")
    public void deleteWantPostDocument(@PathVariable String id) {
        restService.deleteWantPostDocument(id);
    }

    @PostMapping("/comment/init")
    @ApiOperation(value = "評論索引初始化")
    public void wantCommentInit() {
        restService.createWantCommentIndex();
    }

    @PostMapping("/comment/delete/{id}")
    @ApiOperation(value = "刪除評論")
    public void deleteWantCommentDocument(@PathVariable String id) {
        restService.deleteWantCommentDocument(id);
    }

    @PostMapping("/im/reindexRange")
    @ApiOperation(value = "批量添加IM消息記錄")
    public void imReindexRange(@RequestBody List<ImResultVo> imResultVoList) {
        restService.imReindexRange(imResultVoList);
    }

    @PostMapping("/post/reindexRange")
    @ApiOperation(value = "批量添加貼文")
    public void postReindexRange(@RequestBody List<PostResultVo> postResultVoList) {
        restService.postReindexRange(postResultVoList);
    }

    @PostMapping("/comment/reindexRange")
    @ApiOperation(value = "批量添加評論")
    public void commentReindexRange(@RequestBody List<CommentResultVo> commentResultVoList) {
        restService.commentReindexRange(commentResultVoList);
    }

    @PostMapping("/im/insertOrUpdate")
    @ApiOperation(value = "添加IM消息")
    public void imMessageInsertOrUpdate(@RequestBody ImResultVo imResultVo) {
        restService.insertOrUpdate(esIndexImMessage, esTypeImMessage, imResultVo);
    }

    @PostMapping("/post/insertOrUpdate")
    @ApiOperation(value = "添加貼文")
    public void wantPostInsertOrUpdate(@RequestBody PostResultVo postResultVo) {
        restService.insertOrUpdate(esIndexWantPost, esTypeWantPost, postResultVo);
    }

    @PostMapping("/comment/insertOrUpdate")
    @ApiOperation(value = "添加評論")
    public void wantCommentInsertOrUpdate(@RequestBody CommentResultVo commentResultVo) {
        restService.insertOrUpdate(esIndexWantComment, esTypeWantComment, commentResultVo);
    }

    @GetMapping("/im/search")
    @ApiOperation(value = "IM消息搜索")
    public SearchImResultVo imMessageSearch(@RequestBody HashMap<String, Object> queryMap) {
        return restService.imMessageSearch(queryMap);
    }

    @GetMapping("/post/search")
    @ApiOperation(value = "貼文搜索")
    public SearchPostResultVo wantPostSearch(@RequestBody HashMap<String, Object> queryMap) {
        return restService.wantPostSearch(queryMap);
    }

    @GetMapping("/comment/search")
    @ApiOperation(value = "評論搜索")
    public SearchCommentResultVo wantCommentSearch(@RequestBody HashMap<String, Object> queryMap) {
        return restService.wantCommentSearch(queryMap);
    }

    @PostMapping("/im/reindexAll")
    @ApiOperation(value = "重置全部IM消息記錄")
    public void imReindexAll() {
        restService.imReindexRange(reindexService.getImMessageResultVoList());
    }

    @PostMapping("/post/reindexAll")
    @ApiOperation(value = "重置全部貼文記錄")
    public void postReindexAll() {
        restService.postReindexRange(reindexService.getPostResultVoList());
    }

    @PostMapping("/comment/reindexAll")
    @ApiOperation(value = "重置全部評論記錄")
    public void commentReindexAll() {
        restService.commentReindexRange(reindexService.getCommentResultVoList());
    }
}
ESRestController
package com.ftofs.esclient;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2
@Configuration
public class Swagger2 {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.ftofs.esclient.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Elasticsearch Rest High/Low Level Client 接口文檔說明")
                .contact(new Contact("Nick.Chung", "http://cnblogs.com/ncore", "46638441@qq.com"))
                .description("簡單優雅的Restful風格")
                .termsOfServiceUrl("https://github.com/mbhybird")
                .version("1.0")
                .build();
    }
}
Swagger2
package com.ftofs.esclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ESClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ESClientApplication.class, args);
    }


}
ESClientApplication
server.port=9500
esHost = 127.0.0.1
#dev:192.168.5.30
#train:192.168.5.32
esPort = 9200
esScheme = http
esIndexImMessage = index_im_msg
esIndexWantPost = index_want_post
esIndexWantComment = index_want_comment
esTypeImMessage = im_msg
esTypeWantPost = want_post
esTypeWantComment = want_comment

spring.datasource.url = jdbc:mysql://192.168.5.30:3306/twdb?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456

spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect

#logging.level.root=WARN
##logging.level.org.springframework.web=INFO
##logging.file=/log/es.log
##logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n
##logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n
application.properties
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ftofs</groupId>
    <artifactId>esclient</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>esclient</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.2.4</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>shade</goal></goals>
                        <configuration>
                            <relocations>
                                <relocation>
                                    <pattern>org.apache.http</pattern>
                                    <shadedPattern>hidden.org.apache.http</shadedPattern>
                                </relocation>
                                <relocation>
                                    <pattern>org.apache.logging</pattern>
                                    <shadedPattern>hidden.org.apache.logging</shadedPattern>
                                </relocation>
                                <relocation>
                                    <pattern>org.apache.commons.codec</pattern>
                                    <shadedPattern>hidden.org.apache.commons.codec</shadedPattern>
                                </relocation>
                                <relocation>
                                    <pattern>org.apache.commons.logging</pattern>
                                    <shadedPattern>hidden.org.apache.commons.logging</shadedPattern>
                                </relocation>
                            </relocations>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
pom.xml
相關文章
相關標籤/搜索