目录
1、SpringBoot集成ElasticSearch
在创建项目时,选择elasticsearch选项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
注意:版本兼容的问题,不同版本的SpringBoot有对应的ElasticSearch版本
如SpringBoot2.5版本对应ES-7.11.X
2、ElasticSearch之文档的基本操作(增删改查)
ES提供了基于HTTP协议的RESTful API用于操作文档,使用Kibana中的开发工具,可以方便的执行以下操作(不仅限下述方法):
方法 | 功能 |
PUT | 创建索引数据 |
GET | 查询文档 |
POST | 修改文档 |
DELETE | 删除文档 |
HEAD | 检查某文档是否存在 |
ES是面向文档的,文档是es
中可搜索的最小单位,ES
的文档由一个或多个字段组成,类似于关系型数据库中的一行记录,但ES
的文档是以JSON
进行序列化并保存的,每个JSON
对象由一个或多个字段组成,字段类型可以是布尔,数值,字符串、二进制、日期等数据类型。
3、通过RestHighClient操作ES索引
(1)配置RestHighClient对象
/**
* Spring的两步骤:
* 1、找对象
* 2、放入Spring容器中待用
*
*/
@Configuration
public class ElasticSearchClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1",9200,"http")
));
return client;
}
}
(2)通过注解的方式获取对象
@Autowired
@Qualifier("restHighLevelClient")//通过指定的方法,获取对象
private RestHighLevelClient client;
(3)操作文档的API
对于文档的CRUD操作存在同步和异步两种操作,当执行同步操作时,客户端需要等待xxxResponse('xxx'表示文档的一种操作方法)返回后才能继续执行其他操作,而执行异步操作(xxxAsync)则不需要等待客户端的响应。
1)创建索引
PUT /<target>/_doc/<_id>
IndexRequest中提供了以下重载的方法,根据指定的数据源创建索引
根据源码中的提示可知,推荐使用上述两种方式指定索引的数据源
/**
* Sets the document source to index.
*
* Note, its preferable to either set it using {@link #source(org.elasticsearch.common.xcontent.XContentBuilder)}
* or using the {@link #source(byte[], XContentType)}.
*/
public IndexRequest source(String source, XContentType xContentType) {
return source(new BytesArray(source), xContentType);
}
@Test
void indexDocumentTest() throws IOException {
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("user", "kimchy");
builder.timeField("postDate", new Date());
builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("posts")
.id("3").source(builder);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse);
}
2)查询文档
GET /index/_doc/id
/**
* 获取文档信息
* @throws IOException
*/
@Test
void getDocTest() throws IOException {
GetRequest getRequest = new GetRequest("posts", "1");
GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
Map<String, Object> source = response.getSourceAsMap();
for (Map.Entry<String, Object> entry : source.entrySet()) {
System.out.println(entry.getKey() + " , " + entry.getValue());
}
}
/**
* GetSourceRequest 专门用于获取文档的_source资源
*
* @throws IOException
*/
@Test
void getSourceTest() throws IOException {
//专用于获取某一个文档的_source资源信息
GetSourceRequest getSourceRequest = new GetSourceRequest("posts", "1");
GetSourceResponse sourceResponse = client.getSource(getSourceRequest, RequestOptions.DEFAULT);
sourceResponse.getSource().forEach((key, value) -> System.out.println(key + " , " + value));
}
3)删除文档
DELETE /<index>/_doc/<_id>
@Test
void deleteDocTest() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("posts", "2");
deleteRequest.timeout("1s");
deleteRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
System.out.println(deleteResponse.toString());
}
4) 更新文档
POST /<index>/_update/<_id>
UPDATE API操作可以通过使用一个脚本或者传入部分文档信息,从而更新文档内容;
文档是不可变的,其不能被修改,只能被替换。
/**
* 更新文档信息
* @throws IOException
*/
@Test
void updateDocTest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("posts", "2");
updateRequest.timeout(TimeValue.timeValueMillis(10000));
//使用脚本来更新文档信息(有错误,待解决)
// Caused by: ElasticsearchException[Elasticsearch exception [type=null_pointer_exception, reason=null]]
//报错原因是参数异常,在当前索引下/posts/_doc/2 对应的_source中没有field字段,所以脚本执行报错
Map<String, Object> parameters = Collections.singletonMap("count", 4);
//该脚本可以作为内联脚本提供,或者存储脚本ScriptType.STORED
Script inline = new Script(ScriptType.INLINE, "painless",
"ctx._source.field += params.count", parameters);
updateRequest.script(inline);
// updateRequest.upsert() 更新的文档可能不存在,则将更新内容新建为一个文档索引
UpdateResponse response = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(response.toString());
//根据数据的映射,更新对应的值
/* HashMap<String, Object> update = new HashMap<>();
update.put("name","Lilard2");
update.put("birth","1996-11-03");
updateRequest.doc(update);*/
}
通过kibana的开发工具,演示更新文档的操作效果:
创建一个新的文档:
PUT /test/_doc/1?pretty
{
"counter" : 1,
"tags" : ["red"]
}
通过脚本传递参数,将counter值执行加5的操作:
POST /test/_update/1?pretty
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 8
}
}
}
查询更新后的文档内容,_source中counter对应的结果为9:
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_version" : 3,
"_seq_no" : 9,
"_primary_term" : 6,
"found" : true,
"_source" : {
"counter" : 9,
"tags" : [
"red"
]
}
}
同样的,可以使用更新操作,为标签列表添加或者删除一个标签:
POST /test/_update/1?pretty
{
"script": {
"source": "ctx._source.tags.add(params.tag)",
"lang": "painless",
"params": {
"tag": "blue"
}
}
}
结果为:
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_version" : 4,
"_seq_no" : 10,
"_primary_term" : 6,
"found" : true,
"_source" : {
"counter" : 9,
"tags" : [
"red",
"blue"
]
}
}
参考链接:
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html