elasticsearch-RestClient索引库以及基本文档操作
ES 官方提供了各种不同语言的客户端,用来操作 ES。这些客户端的本质就是组装 DSL 语句,通过 http 请求发送给 ES。官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html
其中的Java Rest Client又包括两种:
- Java Low Level Rest Client
- Java High Level Rest Client
我们使用Java HighLevel Rest Client 客户端 API
SQL文件
这次学习有对应的数据库数据,我们从mysql获取数据,在elasticsearch中创建索引,sql文件已经准备好,请点击下载:tb_hotel.sql,原始项目,请点击下载:hotel-demo.zip
初始化RestClient
在 elasticsearch 提供的 API 中,elasticsearch 一切交互都封装在一个名为 RestHighLevelClient 的类中,必须先完成这个对象的初始化,建立与 elasticsearch 的连接。
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
SpringBoot 默认的 ES 版本是 7.6.2,我们需要覆盖默认的ES版本
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
我们创建一个测试类 HotelIndexTest,然后将初始化的代码编写在 @BeforeEach
方法,关闭连接写在@AfterEach
方法中。
public class HotelIndexTest {
private RestHighLevelClient client;
/**
* 初始化客户端
*/
@BeforeEach
void setup(){
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.113.130:9200")
));
}
/**
* 关闭客户端
* @throws IOException
*/
@AfterEach
void close() throws IOException {
client.close();
}
}
索引库操作
创建索引库
/**
* 创建索引库
* @throws IOException
*/
@Test
void createHotelIndex() throws IOException {
// 1.创建Request对象
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2.准备请求的参数:DSL语句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3.发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
public class HotelConstants {
public static final String MAPPING_TEMPLATE = "{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"address\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"price\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"score\":{\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"brand\":{\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"city\":{\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"starName\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"business\":{\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"location\":{\n" +
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"pic\":{\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"all\":{\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
}
删除索引库
@Test
void deleteHotelIndex() throws IOException {
DeleteIndexRequest hotel = new DeleteIndexRequest("hotel");
restHighLevelClient.indices().delete(hotel,RequestOptions.DEFAULT);
}
判断索引库是否存在
@Test
void existHotelIndex() throws IOException {
GetIndexRequest hotel = new GetIndexRequest("hotel");
boolean exists = restHighLevelClient.indices().exists(hotel, RequestOptions.DEFAULT);
System.out.println(exists);
}
文档操作
我们将从数据库中查出数据,写入到elasticsearch中。
索引库实体类
@Data
@TableName("tb_hotel")
public class Hotel {
@TableId(type = IdType.INPUT)
private Long id;
private String name;
private String address;
private Integer price;
private Integer score;
private String brand;
private String city;
private String starName;
private String business;
private String longitude;
private String latitude;
private String pic;
}
与我们的索引库结构存在差异:
- longitude和latitude需要合并为location
因此,我们需要定义一个新的类型,与索引库结构吻合:
@Data
@NoArgsConstructor
public class HotelDoc {
private Long id;
private String name;
private String address;
private Integer price;
private Integer score;
private String brand;
private String city;
private String starName;
private String business;
private String location;
private String pic;
public HotelDoc(Hotel hotel) {
this.id = hotel.getId();
this.name = hotel.getName();
this.address = hotel.getAddress();
this.price = hotel.getPrice();
this.score = hotel.getScore();
this.brand = hotel.getBrand();
this.city = hotel.getCity();
this.starName = hotel.getStarName();
this.business = hotel.getBusiness();
this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
this.pic = hotel.getPic();
}
}
新增文档
@SpringBootTest
public class HotelDocTest {
private RestHighLevelClient client;
@Autowired
private HotelService hotelService;
/**
* 初始化客户端
*/
@BeforeEach
void setup() {
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.113.130:9200")
));
}
/**
* 新增文档
* @throws IOException
*/
@Test
void testAddDoc() throws IOException {
//通过id获取数据
Hotel hotel = hotelService.getById("38609");
HotelDoc hotelDoc = new HotelDoc(hotel);
// 创建Request对象
IndexRequest hotelRequest = new IndexRequest("hotel").id(hotelDoc.getId().toString());
// 准备Json文档
hotelRequest.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
// 发送请求
client.index(hotelRequest,RequestOptions.DEFAULT);
}
/**
* 关闭客户端
*
* @throws IOException
*/
@AfterEach
void close() throws IOException {
client.close();
}
}
查询文档
@Test
void testGetDocumentById() throws IOException {
// 1.准备Request
GetRequest hotel = new GetRequest("hotel", "38609");
// 2.发送请求,得到响应
GetResponse hotelResponse = client.get(hotel, RequestOptions.DEFAULT);
// 3.解析响应结果
String hotelDocSourceAsString = hotelResponse.getSourceAsString();
// 4.json转实体类
HotelDoc hotelDoc = JSON.parseObject(hotelDocSourceAsString, HotelDoc.class);
System.out.println(hotelDoc);
}
删除文档
@Test
void testDeleteDocumentById() throws IOException {
DeleteRequest hotel = new DeleteRequest("hotel", "38609");
client.delete(hotel,RequestOptions.DEFAULT);
}
修改文档
前面我们说过,修改文档有两种方式:
- 全量修改:直接覆盖原来的文档
- 增量修改:修改文档中的部分字段
在 RestClient 的 API 中,全量修改与新增的 API 完全一致,判断依据是 ID
- 如果新增时,ID已经存在,则修改
- 如果新增时,ID不存在,则新增
所以全量修改写法与新增文档一样,下面我们主要是介绍增量修改。
@Test
void testUpdateDocument() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("hotel", "38609");
// 2.准备请求参数
request.doc(
"price", "952",
"starName", "四钻"
);
// 3.发送请求
client.update(request, RequestOptions.DEFAULT);
}
批量导入文档
@Test
void testBulk() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
List<Hotel> hotelList = hotelService.list();
hotelList.forEach(item -> {
HotelDoc hotelDoc = new HotelDoc(item);
bulkRequest.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc), XContentType.JSON));
});
client.bulk(bulkRequest, RequestOptions.DEFAULT);
}
elasticsearch-RestClient索引库以及基本文档操作
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/1008