错误说明:此错误是发生在使用java RestHighLevelClient操作向ES中单挑/多条插入数据时报的错,关键报错信息
org.elasticsearch.action.ActionRequestValidationException: Validation Failed:
1: type is missing;2: type is missing;
错误原因:安装的es和分词器版本太低,例如lz使用的是6.6.2版本的es,使用RestHighLevelClient插入时一直报错,换成7.3.2版本后一次性插入成功。
在一个索引中,你可以定义一个或多个类型,一个类型是你的索引的一个逻辑上的分类,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型,比如说,我们订单数据索引中我们把订单信息作为一个类型,订单相关的物流信息做为一个类型。但在6.0开始建议index只包含一个type,在7.0之后开始去除。
根据提示也可以知道大概是类型的错误,就是创建索引的类型字段问题,另外还需注意es与ik的版本统一问题,安装的es客户端与java api的版本统一问题,lz的代码如下
public void createIndex() {
CreateIndexRequest request = new CreateIndexRequest(indexName);//创建索引
// request.settings(Settings.builder()
// //分片参数
// .put("index.number_of_shards", 5)
// .put("index.number_of_replicas", 2)
// );
request.mapping("{\"properties\":{\"newsId\":{\"type\":\"text\",\"index\":false},\"newsTitle\":{\"type\":\"text\",\"index\":true,\"analyzer\":\"ik_smart\"},\"newsContont\":{\"type\":\"text\",\"index\":true,\"analyzer\":\"ik_smart\"},\"readCount\":{\"type\":\"integer\",\"index\":true}}}",//类型映射,需要的是一个JSON字符串
XContentType.JSON);
//为索引设置一个别名
request.alias(
new Alias("news_alias")
);
//可选参数
//超时,等待所有节点被确认(使用TimeValue方式)
request.setTimeout(TimeValue.timeValueSeconds(1000));
//连接master节点的超时时间(使用TimeValue方式)
request.setMasterTimeout(TimeValue.timeValueSeconds(1000));
//在创建索引API返回响应之前等待的活动分片副本的数量,以int形式表示。
// request.waitForActiveShards(ActiveShardCount.from(2));
try {
CreateIndexResponse createIndexResponse = client.indices().create(request, DEFAULT);
if (createIndexResponse.isAcknowledged()) {
System.out.println("所有节点都已确认请求" + createIndexResponse.index());
}
} catch (IOException e) {
e.printStackTrace();
}
}
所以解决问题的方式有两种:
1、将上述代码中request.mapping("{\"properties\":{\"newsId\":{\"type\":\"text\",\"index\":false},\"newsTitle\":{\"type\":\"text\",\"index\":true,\"analyzer\":\"ik_smart\"},\"newsContont\":{\"type\":\"text\",\"index\":true,\"analyzer\":\"ik_smart\"},\"readCount\":{\"type\":\"integer\",\"index\":true}}}",//类型映射,需要的是一个JSON字符串 XContentType.JSON);
中的json格式类型修改,修改成适合es6规范的数据,lz试了很多次都没有成功
2、重装es,将es修改为7.0以上的版本重新运行代码即可
注释说明:lz使用transportCient(此对象已过时,官方说将在7中声明过时,8中完全废除)创建和插入对象都是正常的在此贴一下代码:
package com.icoding.springbootesjdelasticsearch.core;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.net.InetAddress;
/**
* 用于获取es的客户端链接对象
*
* @description:
* @author: Czw
* @create: 2020-06-26 15:28
**/
public class TransportClientUtil {
public static final String HOST = "127.0.0.1";
//es通讯端口
public static final int PORT = 9300;
//es索引库名称(库名称)
public static final String INDEX_NAME = "jdgoodsdb";
//es类型表名称(表名)
public static final String TABLE_NAME = "content";
//获取es链接客户端
public static TransportClient getTransportClientUtil() {
try {
//设置集群信息
Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
//创建transportClient对象
TransportClient transportClient = new PreBuiltTransportClient(settings);
//开始连接服务
transportClient.addTransportAddress(new TransportAddress(InetAddress.getByName(HOST), PORT));
return transportClient;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//创建索引库
public static void createIndexDB() {
//获取es客户端,链接对象
TransportClient transportClientUtil = getTransportClientUtil();
//创建索引
CreateIndexResponse createIndexResponse = transportClientUtil.admin().indices().prepareCreate(INDEX_NAME).get();
System.out.println(createIndexResponse.isAcknowledged());
//关闭连接
transportClientUtil.close();
}
//创建索引规则
public static void createIndexData() {
TransportClient transportClient = null;
try {
transportClient = getTransportClientUtil();
CreateIndexResponse createIndexResponse = transportClient.admin().indices().prepareCreate(INDEX_NAME).get();
if (createIndexResponse.isAcknowledged()) {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject()
.startObject(TABLE_NAME)
.startObject("properties")
.startObject("id").field("type", "long").field("store", true).endObject()
.startObject("cid").field("type", "text").field("store", true).endObject()
//使用ik分词器有两种: ik_smart最小切分,ik_ max word最细切分,有个前提:你es服务必须要安装中文分词器
.startObject("title").field("type", "text").field("store", true).field("analyzer", "ik_smart").endObject()
.startObject("price").field("type", "float").field("store", true).endObject()
.startObject("img").field("type", "text").field("store", true).endObject()
.startObject("description").field("type", "text").field("store", true).field("analyzer", "ik_smart").endObject()
.endObject()
.endObject()
.endObject();
//设置规则 前提:库必须存在,才能创建规则,否则报错
AcknowledgedResponse acknowledgedResponse = transportClient.admin().indices()
//设置索引库
.preparePutMapping(INDEX_NAME)
//给那个类型(表)添加规则
.setType(TABLE_NAME)
//关联规则
.setSource(xContentBuilder)
.get();
System.out.println("索引规则创建成功="+acknowledgedResponse.isAcknowledged());
}
} catch (Exception e) {
e.printStackTrace();
}finally {
transportClient.close();
}
}
public static void main(String[] args) {
createIndexData();
}
}