因爲業務需求,需要引入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);