采用Java的方式创建ElasticSearch的index、settings、mapping
settings可采用XContentType.JSON也可以采用settingsJson的方式
mapping可以采用数据库Model的方式根据自定义规则映射成ES的数据类型
package com.demo.plugin;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;
@SuppressWarnings("all")
public class IniIndex {
private RestHighLevelClient restHighLevelClient = ElasticSearchPlugin.getHighLevelClient();
private RequestOptions options = RequestOptions.DEFAULT;
private static final Map<String, String> MAPPINGS = new HashMap<>();
/**
* settings处理
* @throws IOException
* indexName 类名_版本号 test_v1.0
* 别名统一 类名_alias
*/
public void settings(String indexName) throws IOException {
CreateIndexRequest params = new CreateIndexRequest(indexName);
params.alias(new Alias(indexName+"_alias"));
/*params.settings(" {\n" +
" \"number_of_shards\" : 1,\n" +
" \"number_of_replicas\" : 0,\n" +
" \"analysis\": {\n" +
" \"analyzer\": {\n" +
" \"rebuilt_thai\": {\n" +
" \"tokenizer\": \"thai\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}", XContentType.JSON);*/
params.settings(" {\n" +
" \"number_of_shards\" : 1,\n" +
" \"number_of_replicas\" : 0,\n" +
" \"analysis\": {\n" +
" \"analyzer\": {\n" +
" \"icu_analyzer\": {\n" +
" \"tokenizer\": \"icu_tokenizer\",\n" +
" \"filter\": [\n" +
" \"lowercase\",\n" +
" \"decimal_digit\"\n" +
" ]\n" +
" }\n" +
" }\n" +
" }\n" +
"}", XContentType.JSON);
/*params.settings(
" {\n" +
" \"number_of_shards\" : 1,\n" +
" \"number_of_replicas\" : 0,\n" +
" \"analysis\": {\n" +
" \"analyzer\": {\n" +
" \"ik_analyzer\": {\n" +
" \"tokenizer\": \"ik_max_word\",\n" +
" \"filter\": [\n" +
" \"lowercase\",\n" +
" \"decimal_digit\"\n" +
" ]\n" +
" }\n" +
" }\n" +
" }\n" +
"}", XContentType.JSON);*/
/*params.settings("{\n" +
" \"number_of_shards\" : 1,\n" +
" \"number_of_replicas\" : 0,\n" +
" \"analysis\": {\n" +
" \"tokenizer\": {\n" +
" \"ik_max_word\": {\n" +
" \"type\": \"pattern\",\n" +
" \"pattern\": \"[ .,*,~,|,!,?,\\/,。,,,-,+,=,,]\"\n" +
" }\n" +
" },\n" +
" \"analyzer\": {\n" +
" \"ik_analyzer\": {\n" +
" \"tokenizer\": \"ik_max_word\",\n" +
" \"filter\": [\n" +
" \"lowercase\",\n" +
" \"decimal_digit\"\n" +
" ]\n" +
" }\n" +
" }\n" +
" }\n" +
" }", XContentType.JSON);*/
restHighLevelClient.indices().create(params, options);
}
/**
* 初始化索引
*
* @param indexName 索引名称
* @param indexNameAlia 索引别名
* @param settingsJson settings数据
* @param mappingJson mapping数据
* @return
*/
public static boolean iniIndex(String indexName,String indexNameAlia,String settingsJson,String mappingJson){
// 判断索引是否存在
boolean result = isIndexExists(indexName);
if(result){
log.error("索引已存在: "+indexName);
return false;
}
try {
CreateIndexRequest params = new CreateIndexRequest(indexName);
params.alias(new Alias(indexNameAlia));
params.settings(settingsJson, XContentType.JSON);
params.mapping(mappingJson, XContentType.JSON);
restHighLevelClient.indices().create(params, options);
} catch (IOException e) {
//e.printStackTrace();
log.error("索引: "+indexName+",初始化异常:"+ e);
return false;
}
return true;
}
/**
* Mapping处理
*
* @param obj model类
* @param indexName 索引名
* @param analyzerList 需要分词的字段
* @param objType 对象类型
* @throws IOException
*/
public void mapping(Object obj,String indexName,List<String> analyzerList,int objType) throws IOException {
String type = obj.getClass().getSimpleName().toLowerCase();
GetMappingsRequest request = new GetMappingsRequest();
if (!MAPPINGS.containsKey(type)) {
synchronized (ElasticSearchPlugin.class) {
createIndex(indexName);
//获取所有的Mapping
//ImmutableOpenMap<String, MappingMetaData> mappings = client.admin().cluster().prepareState().execute()
// .actionGet().getState().getMetaData().getIndices().get(clusterName).getMappings();
//MappingMetaData mmd = mappings.get(type);
Map<String, MappingMetaData> mappings = restHighLevelClient.indices().getMapping(request, options).mappings();
MappingMetaData mmd = mappings.get("type");
if (null == mmd) {
createMapping(obj,indexName,analyzerList,objType);
} else {
CompressedXContent xContent = mappings.get(type).source();
if (xContent == null) {
createMapping(obj,indexName,analyzerList,objType);
} else {
String mapping = xContent.toString();
MAPPINGS.put(type, mapping);
}
}
}
}
}
/**
* 创建Mapping
*
*/
public void createMapping(Object obj,String indexName,List<String> analyzerList,int objType) {
String type = obj.getClass().getSimpleName().toLowerCase();
PutMappingRequest mapping = null;
if(objType == 1){
mapping = Requests.putMappingRequest(indexName).type(type).source(saveMapping(obj,analyzerList));
}else{
mapping = Requests.putMappingRequest(indexName).type(type).source(setMapping(obj,analyzerList));
}
//AcknowledgedResponse actionGet = client.admin().indices().putMapping(mapping).actionGet();
//AcknowledgedResponse putMapping = restHighLevelClient.indices().putMapping(mapping, options);
try {
restHighLevelClient.indices().putMapping(mapping, options);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 设置对象的ElasticSearch的Mapping
*
* jfinal
* @param obj
* @return
*/
public XContentBuilder setMapping(Object obj,List<String> analyzerList) {
List<Map.Entry<String,Object>> fieldList = getFieldList(obj);
XContentBuilder mapping = null;
try {
mapping = jsonBuilder().startObject().startObject("properties");
for (Map.Entry<String,Object> atrrValue : fieldList) {
String key = (String) atrrValue.getKey();
String value = atrrValue.getValue().toString();
String name = value.substring(value.lastIndexOf(".")+1);
String type = getElasticSearchMappingType(name.toLowerCase());
if (analyzerList.contains(key)) {
mapping.startObject(key)
.field("type", type)
//使用icu_analyzer分词器
.field("analyzer", "icu_analyzer")
.field("search_analyzer", "icu_analyzer")
.endObject();
} else {
mapping.startObject(key)
.field("type", type)
.endObject();
}
}
mapping.endObject().endObject();
} catch (IOException e) {
e.printStackTrace();
}
return mapping;
}
/**
* 设置对象的ElasticSearch的Mapping
*
* 普通对象
* @param obj
* @return
*/
public XContentBuilder saveMapping(Object obj,List<String> analyzerList) {
List<Field> fieldList = getFields(obj);
XContentBuilder mapping = null;
try {
mapping = jsonBuilder().startObject().startObject("properties");
for (Field field : fieldList) {
//修饰符是static的字段不处理
if (Modifier.isStatic(field.getModifiers())){
continue;
}
if (field.getType().isInterface()){
//处理list
List<Field> listFields = getListFields(obj,field.getName());
mapping.startObject(field.getName())
.field("type", "nested")
.startObject("properties");
for (Field f : listFields) {
String name = f.getName();
String type = getElasticSearchMappingType(f.getType().getSimpleName().toLowerCase());
mapping.startObject(name)
.field("type", type)
.endObject();
}
mapping.endObject().endObject();
}else{
String name = field.getName();
String type = getElasticSearchMappingType(field.getType().getSimpleName().toLowerCase());
if (analyzerList.contains(name)) {
mapping.startObject(name)
.field("type", type)
//使用icu_analyzer分词器
.field("analyzer", "icu_analyzer")
.field("search_analyzer", "icu_analyzer")
.endObject();
} else {
mapping.startObject(name)
.field("type", type)
.endObject();
}
}
}
mapping.endObject().endObject();
} catch (IOException e) {
e.printStackTrace();
}
return mapping;
}
/**
* 获取对象所有自定义的属性
*
* jfinal反射
* @param obj
* @return
*/
public List<Map.Entry<String,Object>> getFieldList(Object obj) {
List<Map.Entry<String,Object>> fieldList = new ArrayList<>();
Class objClass = obj.getClass();
Table table = TableMapping.me().getTable(objClass);
Map<String, Class<?>> columnTypeMap = table.getColumnTypeMap();
Iterator it = columnTypeMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String,Object> atrrValue = (Map.Entry<String,Object>)it.next();
fieldList.add(atrrValue);
}
return fieldList;
}
/**
* 获取对象所有自定义的属性
*
* 普通对象映射
* @param obj
* @return
*/
public List<Field> getFields(Object obj) {
Field[] fields = obj.getClass().getDeclaredFields();
List<Field> fieldList = new ArrayList<>();
fieldList.addAll(Arrays.asList(fields));
return fieldList;
}
/**
* 获取对象所有自定义的属性
* 普通对象List映射
* @param obj
* @param listName
* @return
*/
private List<Field> getListFields(Object obj,String listName) {
Field listField;
List<Field> fieldList = new ArrayList<>();
try {
listField = obj.getClass().getDeclaredField(listName);
//获取 list 字段的泛型参数
ParameterizedType listGenericType = (ParameterizedType) listField.getGenericType();
Type[] listActualTypeArguments = listGenericType.getActualTypeArguments();
Class objClass =(Class)listActualTypeArguments[0];
Field[] fields = objClass.getDeclaredFields();
fieldList.addAll(Arrays.asList(fields));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return fieldList;
}
/**
* java类型与ElasticSearch类型映射
*
* @param varType
* @return
*/
public String getElasticSearchMappingType(String varType) {
String es;
switch (varType) {
case "date":
//默认格式2020-06-06 || 1420070400001
es = "date";
break;
case "double":
es = "double";
break;
case "bigdecimal":
//scaled_float 会缩放存储
es = "double";
break;
case "long":
es = "long";
break;
case "int":
es = "long";
break;
case "integer":
es = "long";
break;
case "list":
es = "nested";
break;
default:
es = "text";
break;
}
return es;
}
/**
* 创建索引
* @throws IOException
*/
public void createIndex(String indexName) {
/*if (!indexExists()) {
CreateIndexRequest request = new CreateIndexRequest("ice");
client.admin().indices().create(request);
}*/
try {
if (!indexExists(indexName)) {
CreateIndexRequest request = new CreateIndexRequest(indexName);
IndicesClient indices = restHighLevelClient.indices();
indices.create(request, options);
}
}catch (IOException e) {
e.printStackTrace();
}
}
/**
* 判断ElasticSearch中的索引是否存在
* @throws IOException
*/
public boolean indexExists(String indexName){
/*IndicesExistsRequest request = new IndicesExistsRequest(clusterName);
IndicesAdminClient adminClient = client.admin().indices();
IndicesExistsResponse response = adminClient.exists(request).actionGet();
if (response.isExists()) {
return true;
}
return false;*/
GetIndexRequest request = new GetIndexRequest(indexName);
IndicesClient indices = restHighLevelClient.indices();
boolean exists = false;
try {
exists = indices.exists(request, options);
} catch (IOException e) {
e.printStackTrace();
}
return exists;
}
}
高版本ES的mapping一旦设定不可修改 参考官方文档
采用Java的方式创建ES的 index、settings、mapping属于硬编码的形式,我是是可以选择更简便的方式 Kibana 去创建