1. 程式人生 > 其它 >RestClient操作ES文件

RestClient操作ES文件

建立一個測試類,做兩件事情:

  • 初始化RestHighLevelClient

  • 我們的酒店資料在資料庫,需要利用IHotelService去查詢,所以注入這個介面

import cn.pino.hotel.pojo.Hotel;
import cn.pino.hotel.service.IHotelService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.List;

@SpringBootTest
public class HotelDocumentTest {
    @Autowired
    private IHotelService hotelService;

    private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://127.0.0.1:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

  

1.新增文件

我們要將資料庫的酒店資料查詢出來,寫入elasticsearch中。

索引庫實體類

資料庫查詢後的結果是一個Hotel型別的物件。結構如下:

@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

因此,我們需要定義一個新的型別,與索引庫結構吻合:

import lombok.Data;
import lombok.NoArgsConstructor;

@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();
    }
}

  

語法說明

新增文件的DSL語句如下:

POST /{索引庫名}/_doc/1
{
    "name": "Jack",
    "age": 21
}

  對應的java程式碼如圖:

完整程式碼

@Test
void testAddDocument() throws IOException {
    // 1.根據id查詢酒店資料
    Hotel hotel = hotelService.getById(61083L);
    // 2.轉換為文件型別
    HotelDoc hotelDoc = new HotelDoc(hotel);
    // 3.將HotelDoc轉json
    String json = JSON.toJSONString(hotelDoc);

    // 1.準備Request物件
    IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
    // 2.準備Json文件
    request.source(json, XContentType.JSON);
    // 3.傳送請求
    client.index(request, RequestOptions.DEFAULT);
}

  

2.查詢文件

查詢的DSL語句如下:

GET /hotel/_doc/{id}

  

非常簡單,因此程式碼大概分兩步:

  • 準備Request物件

  • 傳送請求

不過查詢的目的是得到結果,解析為HotelDoc,因此難點是結果的解析。完整程式碼如下:

完整程式碼

@Test
void testGetDocumentById() throws IOException {
    // 1.準備Request
    GetRequest request = new GetRequest("hotel", "61082");
    // 2.傳送請求,得到響應
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    // 3.解析響應結果
    String json = response.getSourceAsString();

    HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
    System.out.println(hotelDoc);
}

  

3.刪除文件

刪除的DSL為是這樣的:

DELETE /hotel/_doc/{id}

  

完整程式碼:

@Test
void testDeleteDocument() throws IOException {
    // 1.準備Request
    DeleteRequest request = new DeleteRequest("hotel", "61083");
    // 2.傳送請求
    client.delete(request, RequestOptions.DEFAULT);
}

  

4.修改文件

語法說明

修改我們講過兩種方式:

  • 全量修改:本質是先根據id刪除,再新增

  • 增量修改:修改文件中的指定欄位值

在RestClient的API中,全量修改與新增的API完全一致,判斷依據是ID:

  • 如果新增時,ID已經存在,則修改

  • 如果新增時,ID不存在,則新增

這裡不再贅述,我們主要關注增量修改。

程式碼示例如圖:

完整程式碼

@Test
void testUpdateDocument() throws IOException {
    // 1.準備Request
    UpdateRequest request = new UpdateRequest("hotel", "61083");
    // 2.準備請求引數
    request.doc(
        "price", "952",
        "starName", "四鑽"
    );
    // 3.傳送請求
    client.update(request, RequestOptions.DEFAULT);
}

  

5.批量匯入文件

步驟如下:

  • 利用mybatis-plus查詢酒店資料

  • 將查詢到的酒店資料(Hotel)轉換為文件型別資料(HotelDoc)

  • 利用JavaRestClient中的BulkRequest批處理,實現批量新增文件

語法說明

批量處理BulkRequest,其本質就是將多個普通的CRUD請求組合在一起傳送。

其中提供了一個add方法,用來新增其他請求:

可以看到,能新增的請求包括:

  • IndexRequest,也就是新增

  • UpdateRequest,也就是修改

  • DeleteRequest,也就是刪除

因此Bulk中添加了多個IndexRequest,就是批量新增功能了。

完整程式碼

我們在匯入酒店資料時,將上述程式碼改造成for迴圈處理即可。

@Test
void testBulkRequest() throws IOException {
    // 批量查詢酒店資料
    List<Hotel> hotels = hotelService.list();

    // 1.建立Request
    BulkRequest request = new BulkRequest();
    // 2.準備引數,新增多個新增的Request
    for (Hotel hotel : hotels) {
        // 2.1.轉換為文件型別HotelDoc
        HotelDoc hotelDoc = new HotelDoc(hotel);
        // 2.2.建立新增文件的Request物件
        request.add(new IndexRequest("hotel")
                    .id(hotelDoc.getId().toString())
                    .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
    }
    // 3.傳送請求
    client.bulk(request, RequestOptions.DEFAULT);
}

  

小結

文件操作的基本步驟:

  • 初始化RestHighLevelClient

  • 建立XxxRequest。XXX是Index、Get、Update、Delete、Bulk

  • 準備引數(Index、Update、Bulk時需要)

  • 傳送請求。呼叫RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete、bulk

  • 解析結果(Get時需要)