欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
- 本文是《java与es8实战》系列的第六篇,经过前面的实战,咱们初步掌握了一些Java对ES的基本操作,通过发送请求对象(例如CreateIndexResponse)到ES服务端,达到操作ES的目的,但是细心的您可能发现了:请求对象可能很复杂,例如多层对象嵌套,那么用代码来创建这些请求对象也必然不会容易
- 今天的文章,咱们先来体验用代码创建请求对象的不便之处,再尝试ES官方给我们提供的解决之道:用JSON创建请求对象
- 接下来,咱们从一个假设的任务开始
任务安排
- 现在咱们要创建一个索引,此索引记录的是商品信息
- 有一个副本(属于setting部分)
- 共三个分片(属于setting部分)
- 共三个字段:商品名称name(keyword),商品描述description(text),价格price(integer)(属于mapping部分)
- name字段值长为256,超出此长度的字段将不会被索引,但是会存储
- 接下来,咱们在kibana上用JSON创建索引,再写代码创建相同索引,然后对比两种方式的复杂程度
kibana上创建索引
- 如果在kibana上用json来创建,请求内容如下,索引名是product001
PUT product001
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": {
"type": "keyword",
"ignore_above": 256
},
"description": {
"type": "text"
},
"price": {
"type": "integer"
}
}
}
}
- 效果如下,符合预期
- 通过eshead观察,也是符合预期
- 可见基于JSON的操作简单明了,接下来看看创建相通索引的代码是什么样子
基于代码创建
- 关于如何连接ES的代码并非本篇重点,而且前面的文章已有详细说明,就不多赘述了
- 首先创建一个API,可以接受外部传来的Setting和Mapping设定,然后用这些设定来创建索引
@Autowired
private ElasticsearchClient elasticsearchClient;
@Override
public void create(String name,
Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn,
Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn) throws IOException {
elasticsearchClient
.indices()
.create(c -> c
.index(name)
.settings(settingFn)
.mappings(mappingFn)
);
}
- 然后就是如何准备Setting和Mapping参数,再调用create方法完成创建,为了让代码顺利执行,我将调用create方法的代码写在单元测试类中,这样后面只需要执行单元测试即可调用create方法
@SpringBootTest
class EsServiceImplTest {
@Autowired
EsService esService;
@Test
void create() throws Exception {
// 索引名
String indexName = "product002";
// 构建setting时,builder用到的lambda
Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn = sBuilder -> sBuilder
.index(iBuilder -> iBuilder
// 三个分片
.numberOfShards("3")
// 一个副本
.numberOfReplicas("1")
);
// 新的索引有三个字段,每个字段都有自己的property,这里依次创建
Property keywordProperty = Property.of(pBuilder -> pBuilder.keyword(kBuilder -> kBuilder.ignoreAbove(256)));
Property textProperty = Property.of(pBuilder -> pBuilder.text(tBuilder -> tBuilder));
Property integerProperty = Property.of(pBuilder -> pBuilder.integer(iBuilder -> iBuilder));
// // 构建mapping时,builder用到的lambda
Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn = mBuilder -> mBuilder
.properties("name", keywordProperty)
.properties("description", textProperty)
.properties("price", integerProperty);
// 创建索引,并且指定了setting和mapping
esService.create(indexName, settingFn, mappingFn);
}
}
- 由于Java API Client中所有对象都统一使用builder pattern的方式创建,这导致代码量略多,例如setting部分,除了setting自身要用Lambda表达式,设置分片和副本的代码也要用Lambda的形式传入,这种嵌套效果在编码中看起来还是有点绕的,阅读起来可能会有点不适应
- 执行单元测试,如下图,未发生异常
- 用kibana查看新建的索引
- 最后,将product001和product002的mapping放在一起对比,可见一模一样
- 再用eshead对比分片和副本的效果,也是一模一样
小结和感慨
- 至此,可以得出结论:
- Java