因为业务需求,需要引入es,我们用的是 https://gitee.com/zxporz/ESClientRHL 这个框架,但是到后面发现部分需求无法满足,比如嵌套文档的处理等,于是在这个框架的基础上,做了一些调整,主要就是重写了index的创建
1.创建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);