一、RestClient
1、什么是RestClient
ES官方提供了各種不同語言的客戶端,用來操作ES,即RestClient。這些客戶端的本質(zhì)就是組裝DSL語句,通過http請求發(fā)送給ES。
官方文檔地址:
https://www.elastic.co/guide/en/elasticsearch/client/index.html
2、導(dǎo)入demo工程
數(shù)據(jù)庫信息如下:
mysql -h localhost -P3306 -uroot -padmian123 testDB < tb_hotel.sql
導(dǎo)入demo工程,基本結(jié)構(gòu)如下:
3、數(shù)據(jù)結(jié)構(gòu)分析與索引庫創(chuàng)建
ES的mapping要考慮的點主要有:
- 字段名(name)
- 字段類型(type)
- 是否參與搜索(index)
- 是否分詞(type/keyword)
- 分詞時,分詞器用哪種(analyzer)
接下來,照著表結(jié)構(gòu),創(chuàng)建ES索引庫:
PUT /hotel
{
"mappings": {
"properties":{
"id":{
"type": "keyword" //注意這個類型
},
"name":{
"type": "text",
"analyzer": "ik_max_word",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false //根據(jù)業(yè)務(wù)場景,用戶剛來,不會去搜地址address,不參與搜索,index改為false,不再默認,類型選用keyword
},
"price":{
"type": "integer"
},
"score":{ //price、score等將來要參與過濾和排序,需要index,用默認的true
"type": "integer"
},
"brand":{ //city、brand品牌參與搜索,且不分詞
"type":"keyword",
"copy_to": "all"
},
"city":{
"type":"keyword"
},
"starName":{ //不用下劃線
"type":"keyword"
},
"business":{
"type": "keyword",
"copy_to": "all"
},
"location":{
"type":"geo_point" //經(jīng)緯度兩個字段合并為location,用ES的特定類型geo_point
},
"pic":{
"type": "keyword",
"index": false //pic既不分詞,也不搜索
},
"all":{ //copy_to用的
"type":"text",
"analyzer": "ik_max_word"
}
}
}
}
用戶就輸入一個虹橋,我既想返回地址帶虹橋的,也想返回商圈在虹橋的,還想返回酒店名稱帶虹橋的,如何實現(xiàn)?
加all字段,給需要的字段里加上從copy_to,這樣all字段就可以代表這些加了copy_to的字段。
實現(xiàn)了在一個字段里搜到多個字段的內(nèi)容。
4、初始化JavaRestClient
- 引入es的RestHighLevelClient依賴
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
- 因為SpringBoot下默認的ES版本是7.6.2,所以我們需要定義properties覆蓋默認的ES版本
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
- 初始化RestHighLevelClient
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://10.4.130.110:9200"),
HttpHost.create("http://10.4.130.111:9200"),
HttpHost.create("http://10.4.130.112:9200") //集群模式寫多個
));
在單元測試里看下效果,打印restHighLevelClient對象:
二、RestClient操作索引庫
1、創(chuàng)建索引庫
示例代碼:
@Test
void testCreateHotelIndex() throws IOException {
// 1.創(chuàng)建Request對象
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2.請求參數(shù),MAPPING_TEMPLATE是靜態(tài)常量字符串,內(nèi)容是創(chuàng)建索引庫的DSL語句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3.發(fā)起請求
client.indices().create(request, RequestOptions.DEFAULT);
}
將創(chuàng)建索引庫的DSL語句以靜態(tài)字符串常量的形式統(tǒng)一寫在常量類里:
運行完成后,查看ES索引庫:
GET /hotel
整個過程,和我們?nèi)iana手動執(zhí)行DSL對比:
2、刪除索引庫
示例代碼:
@Test
void testDeleteHotelIndex() throws IOException {
// 1.創(chuàng)建Request對象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2.發(fā)起請求
client.indices().delete(request, RequestOptions.DEFAULT);
}
3、判斷索引庫是否存在
示例代碼:
@Test
void testExistsHotelIndex() throws IOException {
// 1.創(chuàng)建Request對象
GetIndexRequest request = new GetIndexRequest("hotel");
// 2.發(fā)起請求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 3.輸出
System.out.println(exists);
}
小結(jié):
三、RestClient操作文檔
接下來利用JavaRestClient實現(xiàn)文檔的CRUD,去數(shù)據(jù)庫查詢酒店數(shù)據(jù),導(dǎo)入到hotel索引庫,實現(xiàn)酒店數(shù)據(jù)的CRUD。
和操作索引庫一樣,還是要先完成JavaRestClient的初始化:
public class ElasticsearchDocumentTest {
// 客戶端
private RestHighLevelClient client;
@BeforeEach
void setUp() {
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
));
}
@AfterEach
void tearDown() throws IOException {
client.close();
}
}
接下來要在mysql查數(shù)據(jù),寫下Service層接口,讓它繼承MyBatisPlus的IService<PO>
import com.baomidou.mybatisplus.extension.service.IService;
public interface IHotelService extends IService<Hotel> {
}
1、新增文檔
先看下DSL語法和使用JavaRestClient操作代碼來實現(xiàn)的對比:
以上是簡單邏輯和流程。注意MySQL中查出來的實體類字段和DSL下面的json字段不一樣,這是tb_hotel表對應(yīng)的實體類:
@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;
}
這里寫個新類HotelDoc,將Hotel類封裝成為和ES索引庫字段對應(yīng)的類:
@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) { //有參構(gòu)造,傳入要封裝的對象
this.id = hotel.getId(); //對于這些不用包裝的字段,直接get到后賦值給包裝對象的屬性就行
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();
}
}
接下來實現(xiàn)去數(shù)據(jù)庫查詢酒店數(shù)據(jù),導(dǎo)入到hotel索引庫:
@Resource
IHotelService iHotelService;
@Test
void testIndexDocument() throws IOException {
//從MySQL查
Hotel hotel = iHotelService.getById(60359L);
//封裝
HotelDoc hotelDoc = new HotelDoc(hotel);
//創(chuàng)建request
IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
//放入要新增的json傳
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
//發(fā)請求
client.index(request, RequestOptions.DEFAULT);
}
2、查詢文檔
根據(jù)id查詢到的文檔數(shù)據(jù)是json,再反序列化成Java對象。代碼和DSL語句的對比:
@Test
void testGetDocumentById() throws IOException {
GetRequest request = new GetRequest("hotel","60359");
GetResponse response = client.get(request,RequestOptions.DEFAULT);
//看上圖DSL執(zhí)行返回結(jié)果中有個_source,這個getSource方法就是拿這個數(shù)據(jù)
String json = response.getSourceAsString();
//解析
HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
System.out.println(hotelDoc);
}
3、修改文檔
接下來根據(jù)id去修改ES文檔的酒店數(shù)據(jù)。修改文檔數(shù)據(jù)有兩種方式:
方式一:全量更新。再次寫入id一樣的文檔,就會刪除舊文檔,添加新文檔
方式二:局部更新。只更新部分字段
實現(xiàn)下方式二:
@Test
void testUpdateDocumentById() throws IOException {
UpdateRequest request = new UpdateRequest("hotel","60359");
request.doc(
"price","0.01",
"startName","四星級"
);
client.update(request,RequestOptions.DEFAULT);
}
4、刪除文檔
根據(jù)id刪除文檔數(shù)據(jù):
@Test
void testDeleteDocumentById() throws IOException {
DeleteRequest request = new DeleteRequest("hotel","60359");
client.delete(request,RequestOptions.DEFAULT);
}
再get已經(jīng)無數(shù)據(jù):
小結(jié):
5、批量導(dǎo)入文檔
接下來批量查詢酒店數(shù)據(jù),然后批量導(dǎo)入索引庫中,實現(xiàn)思路:
- 利用mybatis-plus查詢酒店數(shù)據(jù)
- 將查詢到的酒店數(shù)據(jù)(Hotel)轉(zhuǎn)換為文檔類型數(shù)據(jù)(HotelDoc)
- 利用JavaRestClient中的Bulk批處理,實現(xiàn)批量新增文檔
代碼邏輯:
@Test
void testBulk() throws IOException {
//從MySQL查到所有數(shù)據(jù)
List<Hotel> hotels = iHotelService.list();
BulkRequest request = new BulkRequest();
//遍歷Hotel的對象集合
for(Hotel hotel : hotels){
//Hotel轉(zhuǎn)HotelDoc
HotelDoc hotelDoc = new HotelDoc(hotel);
//創(chuàng)建新增文檔的Request對象
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc),XContentType.JSON)
);
}
//發(fā)送請求
client.bulk(request,RequestOptions.DEFAULT);
}
最后查詢單個文檔或者查所有:文章來源:http://www.zghlxwxcb.cn/news/detail-542634.html
//查所有
GET /hotel/_search
文章來源地址http://www.zghlxwxcb.cn/news/detail-542634.html
到了這里,關(guān)于【ElasticSearch】JavaRestClient實現(xiàn)索引庫和文檔的增刪改查的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!