Java創建ES嵌套文檔及查詢

因爲業務需求,需要引入es,我們用的是 https://gitee.com/zxporz/ESClientRHL 這個框架,但是到後面發現部分需求無法滿足,比如嵌套文檔的處理等,於是在這個框架的基礎上,做了一些調整,主要就是重寫了index的創建

1.創建mapping

   mapping詳解

package com.xxx.entity.es;

import org.elasticsearch.common.xcontent.XContentBuilder;

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

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

public class ESMapping {

    public static XContentBuilder corpMapping(){
        XContentBuilder mapping = null ;
        try {
            mapping = jsonBuilder()
                    .startObject()
                        .startObject("properties")
                            .startObject("id").field("type","keyword").endObject()
                            .startObject("name")
                                .field("search_analyzer","ik_smart")
                                .field("analyzer","ik_max_word")
                                .field("type","text")
                                    .startObject("fields")
                                        .startObject("keyword").field("type","keyword").endObject()
                                    .endObject()
                                .endObject()
                            .startObject("qualityNum").field("type","integer").endObject()
                            //如果是嵌套文檔,一定要在此處聲明是nested
                            .startObject("labels").field("type","nested")
                                .startObject("properties")
                                    .startObject("color").field("type","keyword").endObject()
                                    .startObject("name").field("type","keyword").endObject()
                                    .startObject("type").field("type","keyword").endObject()
                                .endObject()
                            .endObject()
                            //可以一直嵌套下去,此處根據業務邏輯設置了兩層嵌套
                            .startObject("personQualities").field("type","nested")
                                .startObject("properties")
                                    .startObject("personId").field("type","keyword").endObject()
                                    .startObject("qualities").field("type","nested")
                                        .startObject("properties")
                                            .startObject("qualityType").field("type","keyword").endObject()
                                            .startObject("qualityMajor").field("type","keyword").endObject()
                                        .endObject()
                                    .endObject()
                                .endObject()
                            .endObject()
                        .endObject()
                    .endObject();
        }catch (Exception e){
            e.printStackTrace();
        }
        return mapping ;
    }
    
    public static Map<String,Integer> getSettings(){
        Map<String, Integer> settings = new HashMap<>();
        settings.put("shards", 3);//分片數量
        settings.put("replicas", 1);//複製數量
//        settings.put("nestedLimit", 100000);//嵌套文檔限制大小(默認10000)
        return settings ;
    }
}

創建index

package com.xxx.service.es.impl;

import com.alibaba.fastjson.JSON;
import com.xxx.service.es.EsService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
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.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.ReindexRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import static com.xxx.entity.es.ESMapping.getSettings;
import static org.zxp.esclientrhl.util.Tools.getESId;
import static utils.Utils.getRoutingId;

@Service
@Log4j2
public class EsServiceImpl<T> implements EsService<T> {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    //判斷index是否存在
    private boolean isNotExists(String index, String type) throws Exception {
        GetIndexRequest request = new GetIndexRequest();
        request.indices(index);
        request.types(type);
        return !this.restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
    }

    //不單獨創建,而是在插入文檔時創建,先調用isNotExists判斷index是否存在,不存在則創建
    private void createIndex(XContentBuilder mapping, String index, String type) {
        CreateIndexRequest request = new CreateIndexRequest(index);
        request.settings(Settings.builder()
                //這裏可以自定義設置,包括各種分詞器等
                .put("index.number_of_shards", getSettings().get("shards"))
                .put("index.number_of_replicas", getSettings().get("replicas"))
                .put("analysis.filter.autocomplete_filter.type", "edge_ngram")
                .put("analysis.filter.autocomplete_filter.min_gram", 1)
                .put("analysis.filter.autocomplete_filter.max_gram", 20)
                .put("analysis.analyzer.autocomplete.type", "custom")
                .put("analysis.analyzer.autocomplete.tokenizer", "standard")
                .putList("analysis.analyzer.autocomplete.filter",
                        "lowercase", "autocomplete_filter")
        );

        request.mapping(type, mapping);

        try {
            CreateIndexResponse createIndexResponse = this.restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            boolean acknowledged = createIndexResponse.isAcknowledged();
            System.out.println(acknowledged);
        } catch (IOException var9) {
            var9.printStackTrace();
        }

    }
}

//插入文檔

package com.xxx.service.es.impl;

import com.alibaba.fastjson.JSON;
import com.xxx.service.es.EsService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
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.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.ReindexRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import static com.xxx.entity.es.ESMapping.getSettings;
import static org.zxp.esclientrhl.util.Tools.getESId;
import static utils.Utils.getRoutingId;

@Service
@Log4j2
public class EsServiceImpl<T> implements EsService<T> {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    //此處是批量存儲
    @Override
    public BulkResponse save(List<T> list,XContentBuilder mapping,String index,String type) {
        BulkResponse bulkResponse = null ;
        if (list != null && list.size() != 0) {
            try {
                EsServiceImpl.log.info("......start to save......");
                //這裏就是用的判斷index是否存在的方法
                if(isNotExists(index,type)){
                    createIndex(mapping,index,type);
                }

                BulkRequest bulkRequest = new BulkRequest();

                for (T tt : list) {
                    bulkRequest.add((new IndexRequest(index, type, getESId(tt))).source(JSON.toJSONString(tt), XContentType.JSON));
                }
                bulkResponse = this.restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
                BulkItemResponse[] responses = bulkResponse.getItems();
                log.info("... insert success {} ",responses.length);
                Arrays.stream(responses).forEach(response->{
                    if(StringUtils.isEmpty(response.getId())){
                        log.info("... response id is empty ...");
                    }
                    if(response.getFailure()!=null){
                        log.info("... response failure ...");
                    }
                });
                if(bulkResponse.hasFailures()){
                    log.info("... save failure {} ..." , bulkResponse.buildFailureMessage());
                }
            }catch (Exception e){
                log.error("... save failure ..." , e);
            }
        }
        return bulkResponse;
    }

}

查詢

//使用nested查詢
NestedQueryBuilder nq = nestedQuery("labels",matchQuery("labels.name",label),ScoreMode.Total);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章