目录
1. es常用方法封装接口:
2. es常用方法封装实现类:
package com.boot.base.config.es.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boot.base.config.es.service.impl.ElasticSearchServiceImpl;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @Description es常用方法封装接口
* @Author admin
* @Date 2021/5/24
*/
public interface ElasticSearchService {
ElasticSearchServiceImpl selectIndex(String index);
boolean createIndex(String index, String type);
boolean existIndex(String index);
boolean deleteIndex(String index);
void createDocument(String id, Map source);
void updateDocument(String id, Map source) throws IOException;
void deleteDocument(String type, String id);
void bulkDocument(String type, Map> sources);
void bulkDeleteDocument(String type, List ids);
Page
package com.boot.base.config.es.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boot.base.common.exception.WorkException;
import com.boot.base.config.es.service.ElasticSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description es常用方法封装实现类
*
* 配置文件结构必须满足如下要求:
* 1.必须指定index,如:blue_whale_news_3
* 2.必须存在的节点mappings
* 3.必须指定type,如:news
* 4.必须存在的节点properties
* 5.建议指定字段名及其类型等,如:
* "content": {
* "type": "text",
* "fields": {
* "keyword": {
* "type": "keyword",
* "ignore_above": 256
* }
* }
* 节点"fields": {...}为非必填!
*
* 示例(可直接拷贝该示例并名命为indices.json,最终的存放路径为:classpath:es.index/indices.json):
* [{
* "blue_whale_news_3": {
* "mappings": {
* "news": {
* "properties": {
* "content": {
* "type": "text",
* "fields": {
* "keyword": {
* "type": "keyword",
* "ignore_above": 256
* }
* }
* },
* "createTime": {
* "type": "date"
* }
* }
* }
* }
* }
* }]
*
*
*
* @Author admin
* @Date 2021/5/24
*/
@Slf4j
@Component
@ConditionalOnResource(resources = "classpath:es.index/indices.json")
public class ElasticSearchServiceImpl implements ElasticSearchService {
@Autowired
private RestHighLevelClient restHighLevelClient;
/** es索引 */
private String index;
/** 指定的es索引的type */
private String type;
/** 所有被加载的索引信息:key: {@link index}, value: {@link type} */
private Map loadedIndices = new HashMap<>();
@Override
public ElasticSearchServiceImpl selectIndex(String index) {
this.index = index;
this.index = loadedIndices.get(index);
return this;
}
@PostConstruct
private void createIndices() {
List indexMappings = parseIndicesConfFile();
doCreateIndices(indexMappings);
}
/**
* 循环创建索引
*
* @param indexMappings
*/
private void doCreateIndices(List indexMappings) {
if (ObjectUtils.isEmpty(indexMappings)) {
return;
}
for (IndexMapping indexMapping : indexMappings) {
if (!this.existIndex(indexMapping.getIndex())) {
this.doCreateIndex(indexMapping.getIndex(), indexMapping.getType(), indexMapping.getXContentBuilder());
}
}
}
/**
* 解析索引配置文件
*
* @return
* @throws FileNotFoundException
*/
private List parseIndicesConfFile() {
File file = null;
try {
file = ResourceUtils.getFile("classpath:es.index/indices.json");
} catch (FileNotFoundException fileNotFoundException) {
log.error("指定的es索引配置文件[classpath:es.index/indices.json]不存在,异常:", file.getAbsolutePath(), fileNotFoundException);
}
String jsonStr;
List indexMappings = null;
try {
jsonStr = IOUtils.toString(file.toURI(), StandardCharsets.UTF_8);
final JSONArray indices = JSON.parseArray(jsonStr);
indexMappings = doParseIndices(indices);
} catch (Exception e) {
log.error("无法创建es索引,解析配置文件[{}]异常:", file.getAbsolutePath(), e);
}
return indexMappings;
}
/**
* 解析JSONArray格式的多个索引
*
* @param indices
*/
private List doParseIndices(JSONArray indices) {
List indexMappings = new ArrayList<>();
if (ObjectUtils.isEmpty(indices)) {
return indexMappings;
}
for (Object index : indices) {
if (index instanceof JSONObject) {
doParseIndex((JSONObject) index, indexMappings);
} else {
log.error("无法解析索引{[]},只能解析json格式的内容!", index);
}
}
return indexMappings;
}
/**
* 解析单个json格式的索引文件
*
* @param idx
* @param indexMappings
*/
private void doParseIndex(JSONObject idx, List indexMappings) {
if (idx.isEmpty()) {
return;
}
final String indexName = idx.keySet().iterator().next();
final Object mappingsObj = ((Map) idx.get(indexName)).get("mappings");
if (mappingsObj == null) {
return;
}
final Map mappings = (Map) mappingsObj;
final String typeName = mappings.keySet().iterator().next();
loadedIndices.put(indexName, typeName);
// 至少有index和type才创建索引
IndexMapping indexMapping = new IndexMapping();
indexMapping.setIndex(indexName).setType(typeName);
indexMappings.add(indexMapping);
final Object propertiesObj = mappings.get(typeName);
final Map properties = (Map) propertiesObj;
if (propertiesObj == null || properties.isEmpty()) {
return;
}
// 构造index的mappings结构
XContentBuilder builder;
try {
builder = XContentFactory.jsonBuilder().map(mappings);
indexMapping.setXContentBuilder(builder);
} catch (IOException e) {
log.error("创建索引失败,构造index的mappings结构异常:", e);
}
}
/**
* es的mappings结构中属性对应的实体类
*
*/
private class IndexMapping {
private String index;
private String type;
private XContentBuilder xContentBuilder;
public String getIndex() {
return index;
}
public IndexMapping setIndex(String index) {
this.index = index;
return this;
}
public String getType() {
return type;
}
public IndexMapping setType(String type) {
this.type = type;
return this;
}
public XContentBuilder getXContentBuilder() {
return xContentBuilder;
}
public IndexMapping setXContentBuilder(XContentBuilder xContentBuilder) {
this.xContentBuilder = xContentBuilder;
return this;
}
}
/**
* 创建指定的索引
*
* @param index
* @param type
* @param xContentBuilder
* @return
*/
public boolean doCreateIndex(String index, String type, XContentBuilder xContentBuilder) {
try {
CreateIndexRequest request = new CreateIndexRequest(index);
// request.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_shards", 5));
request.mapping(type, xContentBuilder);
return this.restHighLevelClient.indices().create(request, RequestOptions.DEFAULT).isAcknowledged();
} catch (IOException e) {
log.error("创建索引[index={},type={}]异常:", index, type, e);
return false;
}
}
@Override
public boolean createIndex(String index, String type) {
try {
CreateIndexRequest request = new CreateIndexRequest(index);
// request.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_shards", 5));
CreateIndexResponse response = this.restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
return response.isAcknowledged();
} catch (IOException e) {
log.error("创建索引[index={},type={}]异常:", index, type, e);
return false;
}
}
@Override
public boolean existIndex(String index) {
GetIndexRequest request = new GetIndexRequest();
request.indices(index).local(false).humanReadable(true);
try {
return restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("查询索引[index={},type={}]是否存在时异常:", index, type, e);
}
return false;
}
@Override
public boolean deleteIndex(String index) {
return false;
}
@Override
public void createDocument(String id, Map source) {
IndexRequest request = new IndexRequest(index, type, id);
request.source(source);
try {
restHighLevelClient.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("创建es的document[index={},type={},id={},source={}]异常:", index, type, id, source, e);
}
}
@Override
public void updateDocument(String id, Map source) {
UpdateRequest request = new UpdateRequest(index, type, id);
request.doc(source);
try {
restHighLevelClient.update(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("更新es的document[index={},type={},id={},source={}]异常:", index, type, id, source, e);
throw new WorkException("更新es的document失败!");
}
}
@Override
public void deleteDocument(String type, String id) {
try {
DeleteRequest request = new DeleteRequest(index, type, id);
restHighLevelClient.delete(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("删除es文档[index={},type={},id={}]异常:", index, type, id, e);
}
}
@Override
public void bulkDocument(String type, Map> sources) {
try {
BulkRequest requests = new BulkRequest();
Iterator it = sources.keySet().iterator();
int count = 0;
while (it.hasNext()) {
count++;
String next = it.next();
IndexRequest request = new IndexRequest(index, type, next);
request.source(sources.get(next));
requests.add(request);
if (count % 1000 == 0) {
restHighLevelClient.bulk(requests, RequestOptions.DEFAULT);
requests.requests().clear();
count = 0;
}
}
if (requests.numberOfActions() > 0) restHighLevelClient.bulk(requests, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("批量创建es文档[index={},type={},sources={}]异常:", index, type, sources, e);
}
}
@Override
public void bulkDeleteDocument(String type, List ids) {
try {
BulkRequest requests = new BulkRequest();
int count = 0;
for (Integer id : ids) {
count++;
DeleteRequest request = new DeleteRequest(index, type, String.valueOf(id));
requests.add(request);
if (count % 1000 == 0) {
restHighLevelClient.bulk(requests, RequestOptions.DEFAULT);
requests.requests().clear();
count = 0;
}
}
if (requests.numberOfActions() > 0) restHighLevelClient.bulk(requests, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("执行类[ElasticSearchServiceImpl]的方法[bulkDeleteDocument(...)]异常:", e);
}
}
@Override
public Page