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);

 

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