文章目录
环境:
jdk1.8
springboot: 2.7.0
一、依赖配置
1、引入es依赖
<!-- spring data es -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/jakarta.json/jakarta.json-api -->
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<version>2.0.1</version>
</dependency>
2、配置文件application.yaml
spring:
elasticsearch:
uris: http://1.13.152.218:9200
username:
password:
connection-timeout: 10s
jackson:
date-format: "yyyy-MM-dd HH:mm:ss"
二、使用Repository对es增删改查
1、定义实体类 Book
package com.zhuang.es.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName="books")
public class Book {
@Id
private Long id;
@Field(type = FieldType.Text)
private String name;
@Field(type = FieldType.Text)
private String summary;
@Field(type = FieldType.Double)
private Double price;
@Field(type = FieldType.Text)
private String parent;
private List<Long> list;
private Map<Long, String> map;
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
private Date create;
}
2、注解:
@Document
作用:标识要持久化到Elasticsearch的域对象, 如定义索引名
@Document(indexName="books")
@Id
作用:定义标识符 -> 文档id
@Id private Long id;
@Field
作用:对持久化到Elasticsearch域的属性设置, 比如设置对应es中字段的属性类型
type属性类型:
1、如果没有定义属性的type或者type = FieldType.Auto ,会动态映射 type,会在第一次插入数据时动态设置属性类型。如
private String name;
或 如@Field(type = FieldType.Auto) private String name;
2、如果显示定义了type的类型,那么在项目启动的时候,就会在es中创建定义的类型
如@Field(type = FieldType.Text) private String name;
那么name
属性在es中的属性类型为text
format日期格式:
1.使用自带的日期格式:format
如@Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second) private Date create
DateFormat是枚举类型;
2.自定义时间类型:pattern
设置format = DateFormat.custom或 format = DateFormat.none,
如:@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss") private Date create;
3、创建接口 BookRepository
继承 ElasticsearchRepository<T, ID>, T为映射的实体类, ID为标记的id类型
package com.zhuang.es.service;
import com.zhuang.es.entity.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface BookRepository extends ElasticsearchRepository<Book, Long> {
}
4、创建 BookController
注入
BookRepository
bean,调用封装好的增删改查接口
package com.zhuang.es.controller;
import com.zhuang.es.entity.Book;
import com.zhuang.es.service.BookRepository;
import com.zhuang.es.vo.BookVo;
import com.zhuang.es.vo.ResponseVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
/**
* @program: mybatis-plus
* @description:
* @author: mrzhuang
* @create: 2022-12-23 21:14
**/
@RestController
@RequestMapping("/book")
public class BookController {
@Resource
BookRepository bookRepository;
/**
* 查询全部
*
* @return /
*/
@GetMapping("/findAll")
public ResponseVo<Iterable<Book>> findAll() {
Iterable<Book> books = bookRepository.findAll();
return new ResponseVo<>(books);
}
/**
* 向es中增加book
*
* @param book /
* @return /
*/
@PostMapping("/add")
public ResponseVo<Book> addBook(@RequestBody Book book) {
Book save = bookRepository.save(book);
return new ResponseVo<>(save);
}
/**
* 根据id查询
*
* @param id /
* @return /
*/
@GetMapping("/findById")
public ResponseVo<Optional<Book>> findById(@RequestParam("id") Long id) {
Optional<Book> bookOptional = bookRepository.findById(id);
return new ResponseVo<>(bookOptional);
}
/**
* 通过传入实体删除
*
* @param book /
* @return /
*/
@PostMapping("/delete")
public ResponseVo<Boolean> delete(@RequestBody Book book) {
bookRepository.delete(book);
return new ResponseVo<>(true);
}
/**
* 通过id删除
*
* @param id /
* @return /
*/
@GetMapping("/deleteById")
public ResponseVo<Boolean> delete(@RequestParam("id") Long id) {
bookRepository.deleteById(id);
return new ResponseVo<>(true);
}
/**
* 更新某个属性值(如:name)
* @param bookVo /
*/
@PostMapping("/update")
public ResponseVo<Book> update(@RequestBody BookVo bookVo) {
//获取需要更新的文档id
Long id = bookVo.getId();
Optional<Book> option = bookRepository.findById(id);
if (option.isPresent()) {
Book book = option.get();
if (StringUtils.isNotEmpty(bookVo.getName())) {
book.setName(bookVo.getName());
}
Book save = bookRepository.save(book);
return new ResponseVo<>(book);
}
return new ResponseVo<>(CodeEnum.FAILUIRE.code, "更新失败!");
}
/**
* 统计数量
*
* @return /
*/
@GetMapping("/count")
public ResponseVo<Long> count() {
long count = bookRepository.count();
return new ResponseVo<>(count);
}
/**
* 查看id是否存在
* @param id /
* @return /
*/
@GetMapping("/existsById")
public ResponseVo<Boolean> update(@RequestParam("id") Long id) {
boolean exists = bookRepository.existsById(id);
return new ResponseVo<>(exists);
}
/**
* 根据name和price查询
* @param name /
* @param price /
* @return /
*/
@GetMapping("/findByNameAndPrice")
public ResponseVo<List<Book>> findByNameAndPrice(@RequestParam("name") String name, @RequestParam("price") Double price) {
List<Book> books = bookRepository.findByNameAndPrice(name, price);
return new ResponseVo<>(books);
}
/**
* 根据summary和parent查询
* @param summary /
* @param parent /
* @return /
*/
@GetMapping("/findBySummaryAndParent")
public ResponseVo<List<Book>> findBySummaryAndParent(@RequestParam("summary") String summary, @RequestParam("parent") String parent) {
List<Book> books = bookRepository.findBySummaryAndParent(summary, parent);
return new ResponseVo<>(books);
}
}
5、Es创建查询机制
通常,Elasticsearch 的查询创建机制按照查询方法中的描述工作。
以下是 Elasticsearch 查询方法转换成的简短示例:
增加方法: List<Book> findByNameAndPrice(String name, Double price);
上面的方法名会被翻译成下面的 Elasticsearch json 查询:
{
"query": {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "price" ] } }
]
}
}
}
package com.zhuang.es.service;
import com.zhuang.es.entity.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface BookRepository extends ElasticsearchRepository<Book, Long> {
List<Book> findByNameAndPrice(String name, Double price);
}
controller层中调用
@PostMapping("/findByNameAndPrice")
public ResponseVo<List<Book>> findByNameAndPrice(@RequestParam("name") String name, @RequestParam("price") Double price){
List<Book> books = bookRepository.findByNameAndPrice(name, price);
return new ResponseVo<>(books);
}
6、查询创建机制关键词
And
关键词 | 样本 |
---|---|
And | findByNameAndPrice |
Es 查询字符串:
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "price" ] } }
]
}
}}
Or
关键词 | 样本 |
---|---|
Or | findByNameOrPrice |
Es 查询字符串:
{ "query" : {
"bool" : {
"should" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "price" ] } }
]
}
}}
Is
关键词 | 样本 |
---|---|
Is | findByName |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } }
]
}
}}
Not
关键词 | 样本 |
---|---|
Not | findByNameNot |
Es 查询字符串:
{ "query" : {
"bool" : {
"must_not" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } }
]
}
}}
Between
关键词 | 样本 |
---|---|
Between | findByPriceBetween |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } }
]
}
}}
LessThan
关键词 | 样本 |
---|---|
LessThan | findByPriceLessThan |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } }
]
}
}}
LessThanEqual
关键词 | 样本 |
---|---|
LessThanEqual | findByPriceLessThanEqual |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } }
]
}
}}
GreaterThan
关键词 | 样本 |
---|---|
GreaterThan | findByPriceGreaterThan |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } }
]
}
}}
GreaterThanEqual
关键词 | 样本 |
---|---|
GreaterThanEqual | findByPriceGreaterThan |
Es查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } }
]
}
}}
Before
关键词 | 样本 |
---|---|
Before | findByPriceBefore |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } }
]
}
}}
After
关键词 | 样本 |
---|---|
After | findByPriceAfter |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } }
]
}
}}
Like
关键词 | 样本 |
---|---|
Like | findByNameLike |
Es查询字符串
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true }
]
}
}}
StartingWith
关键词 | 样本 |
---|---|
StartingWith | findByNameStartingWith |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true }
]
}
}}
EndingWith
关键词 | 样本 |
---|---|
EndingWith | findByNameEndingWith |
Es查询字符串
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true }
]
}
}}
Contanins/Containing
关键词 | 样本 |
---|---|
Contains/Containing | findByNameContaining |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true }
]
}
}}
In(当注释为 FieldType.Keyword 时)
关键词 | 样本 |
---|---|
In(当注释为 FieldType.Keyword 时) | findByNameIn(Collectionnames) |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"bool" : {"must" : [
{"terms" : {"name" : ["?","?"]}}
]
}
}
]
}
}}
In
关键词 | 样本 |
---|---|
In | findByNameIn(Collectionnames) |
Es 查询字符串:
{ "query": {"bool": {"must": [{"query_string":{"query": "\"?\" \"?\"", "fields": ["name"]}}]}}}
Notln(当注释为 FieldType.Keyword 时)
关键词 | 样本 |
---|---|
NotIn(当注释为 FieldType.Keyword 时) | indByNameNotIn(Collectionnames) |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{"bool" : {"must_not" : [
{"terms" : {"name" : ["?","?"]}}
]
}
}
]
}
}}
Notln
关键词 | 样本 |
---|---|
NotIn | findByNameNotIn(Collectionnames) |
Es 查询字符串:
{"query": {"bool": {"must": [{"query_string": {"query": "NOT(\"?\" \"?\")", "fields": ["name"]}}]}}}
关键词 | 样本
--- | ----
True|findByAvailableTrue
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "true", "fields" : [ "available" ] } }
]
}
}}
False
关键词 | 样本 |
---|---|
False | findByAvailableFalse |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "false", "fields" : [ "available" ] } }
]
}
}}
OrderBy
关键词 | 样本 |
---|---|
OrderBy | findByAvailableTrueOrderByNameDesc |
Es 查询字符串:
{ "query" : {
"bool" : {
"must" : [
{ "query_string" : { "query" : "true", "fields" : [ "available" ] } }
]
}
}, "sort":[{"name":{"order":"desc"}}]
}
Exists
关键词 | 样本 |
---|---|
Exists | findByNameExists |
Es 查询字符串:
{"query":{"bool":{"must":[{"exists":{"field":"name"}}]}}}
IsNull
关键词 | 样本 |
---|---|
IsNull | findByNameIsNull |
Es 查询字符串:
{"query":{"bool":{"must_not":[{"exists":{"field":"name"}}]}}}
IsNotNull
关键词 | 样本 |
---|---|
IsNotNull | findByNameIsNotNull |
Es 查询字符串:
{"query":{"bool":{"must":[{"exists":{"field":"name"}}]}}}
IsEmpty
关键词 | 样本 |
---|---|
IsEmpty | findByNameIsEmpty |
Es 查询字符串:
{"query":{"bool":{"must":[{"bool":{"must":[{"exists":{"field":"name"}}],"must_not":[{"wildcard":{"name":{"wildcard":"*"}}}]}}]}}}
IsNotEmpty
关键词 | 样本 |
---|---|
IsNotEmpty | findByNameIsNotEmpty |
Es 查询字符串:
{"query":{"bool":{"must":[{"wildcard":{"name":{"wildcard":"*"}}}]}}}
7、高级查询
注入 ElasticsearchOperations
bean
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchAllQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
import co.elastic.clients.json.JsonData;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhuang.es.EsApplication;
import com.zhuang.es.entity.Book;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import javax.annotation.Resource;
/**
* @program: mybatis-plus
* @description:
* @author: mrzhuang
* @create: 2022-12-22 21:43
**/
@Slf4j
@SpringBootTest(classes = EsApplication.class)
public class EsTest {
@Resource
ElasticsearchOperations operations;
@Test
public void testSearch() {
//term查询
TermQuery termQuery = new TermQuery.Builder().field("price").value("10.2").build();
Query tQuery = new Query.Builder().term(termQuery).build();
//等同于lambda表达式
Query price2 = new Query.Builder().term(t -> t.field("price").value("10.2")).build();
BoolQuery boolQuery = new BoolQuery.Builder()
//filter
.filter(q -> q.range(r -> r.field("price").gte(JsonData.of(11.0)).lt(JsonData.of(16.0))))
//matchAll
.must(q -> q.matchAll(new MatchAllQuery.Builder().build())).build();
NativeQuery nativeQuery = new NativeQueryBuilder().withQuery(q -> q.bool(boolQuery))
//查询结果按照price从小到大排序
.withSort(Sort.by(Sort.Direction.ASC, "price"))
//第0页开始
.withPageable(PageRequest.of(0, 5))
.build();
SearchHits<Book> search = operations.search(nativeQuery, Book.class);
search.stream().forEach(System.out::println);
}
}
二、Es客户端elasticsearchClient
1、创建客户端配置类 ElasticSearchConfig
package com.zhuang.es.config;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.Node;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import javax.annotation.Resource;
@Configuration
@Slf4j
public class ElasticSearchConfig extends ElasticsearchConfigurationSupport {
@Resource
private ElasticsearchProperties elasticSearchProperty;
@Bean
public RestClientBuilder restClientBuilder() {
return RestClient.builder(elasticSearchProperty.getUris().stream().map(this::getElasticSearchHttpHosts).toArray(HttpHost[]::new)).
setRequestConfigCallback(requestConfigBuilder -> {
//设置连接超时时间
requestConfigBuilder.setConnectTimeout(elasticSearchProperty.getConnectionTimeout().toMillisPart());
requestConfigBuilder.setSocketTimeout(elasticSearchProperty.getSocketTimeout().toMillisPart());
return requestConfigBuilder;
}).setFailureListener(new RestClient.FailureListener() {
//某节点失败,这里可以做一些告警
@Override
public void onFailure(Node node) {
log.error("[ ElasticSearchClient ] >> node :{}, host:{}, fail ", node.getName(), node.getHost());
}
}).setHttpClientConfigCallback(httpClientBuilder -> {
// 设置[X-Elastic-Product] header
httpClientBuilder.disableAuthCaching().addInterceptorLast((HttpResponseInterceptor)(response, context) -> response.addHeader("X-Elastic-Product", "Elasticsearch"));
//设置账密
return getHttpAsyncClientBuilder(httpClientBuilder);
});
}
/**
* 配置es client
*/
@Bean(value = "elasticsearchClient")
public ElasticsearchClient elasticsearchClient(@Qualifier("restClientBuilder") RestClientBuilder restClientBuilder) {
RestClient restClient = restClientBuilder.setDefaultHeaders(new Header[]{new BasicHeader("Content-Type", "application/json")}).build();
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
return new ElasticsearchClient(transport);
}
@Bean(value = "elasticsearchTemplate")
public ElasticsearchTemplate elasticsearchTemplate(ElasticsearchClient elasticsearchClient, ElasticsearchConverter elasticsearchConverter) {
return new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
}
private HttpHost getElasticSearchHttpHosts(String host) {
host = host.replaceAll("http://", "").replaceAll("https://", "");
return new HttpHost(host.split(":")[0], Integer.parseInt(host.split(":")[1]), "http");
}
private HttpAsyncClientBuilder getHttpAsyncClientBuilder(HttpAsyncClientBuilder httpClientBuilder) {
if (StringUtils.isEmpty(elasticSearchProperty.getUsername()) || StringUtils.isEmpty(elasticSearchProperty.getPassword())) {
return httpClientBuilder;
}
//设置账号密码
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(elasticSearchProperty.getUsername(), elasticSearchProperty.getPassword()));
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
return httpClientBuilder;
}
}
2、增删改查、批量操作
注入ElasticsearchClient
bean
@Resource(name = "elasticsearchClient")
ElasticsearchClient client;
package com.zhuang;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
import co.elastic.clients.elasticsearch.core.bulk.UpdateOperation;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import com.zhuang.es.EsApplication;
import com.zhuang.es.entity.Book;
import com.zhuang.es.service.BookRepository;
import com.zhuang.es.vo.BookVo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
/**
* @program: kafka
* @description:
* @author: mrzhuang
* @create: 2022-12-25 13:04
**/
@Slf4j
@SpringBootTest(classes = EsApplication.class)
public class EsClientTest {
@Resource
BookRepository repository;
@Resource(name = "elasticsearchClient")
ElasticsearchClient client;
/**
* 创建索引
* @throws IOException
*/
@Test
void testCreateIndex() throws IOException {
//client.indices().create(c->c.index("book"));
CreateIndexRequest createIndexRequest= new CreateIndexRequest.Builder().index("book").build();
CreateIndexResponse indexResponse = client.indices().create(createIndexRequest);
log.info("[{}]索引创建[{}]!", indexResponse.index(), indexResponse.shardsAcknowledged());
}
/**
* 增加数据
* @throws IOException
*/
@Test
void testInsertData() throws IOException {
Optional<Book> book = repository.findById(1l);
IndexRequest<Book> indexRequest = new IndexRequest.Builder<Book>().index("book").id("1").document(book.isPresent() ? book.get() : Book.builder().name("小刘").id(2l).build()).build();
//IndexRequest source = indexRequest.index("book").id("1").source(book.isPresent() ? book.get() : Book.builder().name("小刘"));
IndexResponse index = client.index(indexRequest);
log.info("向索引[{}]中增加id:[{}]文档:[{}]", index.index(), index.id(), index.result());
}
/**
* 删除数据
* @throws IOException /
*/
@Test
void testDeleteData() throws IOException {
//1.根据id删除
DeleteRequest deleteRequest = new DeleteRequest.Builder().index("book").id("gAcXSIUB94FMQr43ryS6").build();
DeleteResponse deleteResponse = client.delete(deleteRequest);
log.info("根据id删除:{}", deleteResponse.result().jsonValue());
//2.根据查询条件删除
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest.Builder().index(List.of("book")).query(q -> q.term(t -> t.field("name").value("xiaoxiao"))).build();
DeleteByQueryResponse deleteByQueryResponse = client.deleteByQuery(deleteByQueryRequest);
log.info("根据查询条件删除:{}个", deleteByQueryResponse.total());
}
/**
* 更新数据
*
* @throws IOException
*/
@Test
void testUpdateDate() throws IOException {
//方法1:创建实体类BookVo对应的实体类的属性和名称与Book相同
//会将Book中对应的属性值替换为需要修改的bookVo中的属性值,然后更新es相对应的属性值
BookVo bookVo = BookVo.builder().parent("妈").build();
UpdateRequest<Book, BookVo> update1 = new UpdateRequest.Builder<Book, BookVo>().index("book").id("1").doc(bookVo).build();
//方法2:创建Map
Map<String, String > map = new HashMap<>();
map.put("parent","爸妈");
UpdateRequest<Book, Map<String, String >> update2 = new UpdateRequest.Builder<Book, Map<String, String >>().index("book").id("1").doc(map).build();
UpdateResponse<Book> update = client.update(update1, Book.class);
log.info("update:{}", update.result());
}
/**
* 查询数据
* @throws IOException
*/
@Test
void testSearch() throws IOException {
TermQuery termQuery = new TermQuery.Builder().field("id").value("11").build();
Query query = new Query.Builder().term(termQuery).build();
BoolQuery boolQuery = new BoolQuery.Builder().must(query).build();
Query build = new Query.Builder().bool(boolQuery).build();
SearchRequest searchRequest = new SearchRequest.Builder().query(build).index(Arrays.asList(new String[]{"book"})).build();
SearchResponse<Book> response = client.search(searchRequest, Book.class);
log.info("查询数据:{}", response.hits().hits().size());
}
/**
* 批量增加
* @throws IOException
*/
@Test
void testBulkInsert() throws IOException {
//批量新增数据
//第一个数据
IndexOperation<Book> indexOperation1 = new IndexOperation.Builder<Book>().id("2").document(Book.builder().id(2l).name("小庄呀").build()).build();
BulkOperation operation1 = new BulkOperation.Builder().index(indexOperation1).build();
//第二个数据
IndexOperation<Book> indexOperation2 = new IndexOperation.Builder<Book>().id("3").document(Book.builder().id(3l).name("小庄呀").build()).build();
BulkOperation operation2 = new BulkOperation.Builder().index(indexOperation1).build();
List<BulkOperation> operations = new ArrayList<>();
operations.add(operation1);
operations.add(operation2);
BulkRequest bulkRequest = new BulkRequest.Builder().index("book").operations(operations).build();
BulkResponse bulkResponse = client.bulk(bulkRequest);
log.info("批量删除:{}, size:{}", !bulkResponse.errors(), bulkResponse.items().size());
}
/**
* 批量更新
* @throws IOException
*/
@Test
void testBulkUpdate() throws IOException {
//批量新增数据
//第一个数据
UpdateOperation<Book, BookVo> updateOperation1 = new UpdateOperation.Builder<Book, BookVo>().id("2").action(b -> b.doc(BookVo.builder().name("xiaoxiao").build())).build();
BulkOperation operation1 = new BulkOperation.Builder().update(updateOperation1).build();
//第一个数据
UpdateOperation<Book, BookVo> updateOperation2 = new UpdateOperation.Builder<Book, BookVo>().id("3").action(b -> b.doc(BookVo.builder().name("xiao").build())).build();
BulkOperation operation2= new BulkOperation.Builder().update(updateOperation2).build();
List<BulkOperation> operations = new ArrayList<>();
operations.add(operation1);
operations.add(operation2);
BulkRequest bulkRequest = new BulkRequest.Builder().index("book").operations(operations).build();
BulkResponse bulkResponse = client.bulk(bulkRequest);
log.info("批量更新:{}, size:{}", !bulkResponse.errors(), bulkResponse.items().size());
}
}