1.mysqlとelasticsearch
mysql と elasticsearch の概念を統一した方法で比較してみましょう。
MySQL | エラスティックサーチ | 説明する |
---|---|---|
テーブル | 索引 | インデックスは、データベースのテーブルに似たドキュメントのコレクションです。 |
行 | 書類 | ドキュメント (Document) はデータベースの行 (Row) と同様のデータであり、ドキュメントは JSON 形式です |
桁 | 分野 | フィールド (Field) は、データベースの列 (Column) に似た、JSON ドキュメント内のフィールドです。 |
スキーマ | マッピング | マッピングは、フィールド タイプの制約など、インデックス内のドキュメントに対する制約です。データベースのようなテーブル構造 (スキーマ) |
SQL | DSL | DSL は elasticsearch によって提供される JSON スタイルのリクエスト ステートメントであり、elasticsearch の操作と CRUD の実装に使用されます。 |
elasticsearchを学んだ後はmysqlはもう必要ないということですか?
実際にはそうではありませんが、どちらにも独自の長所と短所があります。
-
Mysql: トランザクション型の操作が得意で、データのセキュリティと一貫性を確保できます。
-
Elasticsearch: 大量のデータの検索、分析、計算が得意です。
したがって、企業では、この 2 つが組み合わせて使用されることがよくあります。
- 高度なセキュリティ要件が必要な書き込み操作の場合は、mysql を使用して実装します。
- 高いクエリ パフォーマンスを必要とする検索要件の場合は、elasticsearch を使用して、
- この 2 つは、データの同期を実現し、一貫性を確保するための特定の方法に基づいています。
2. インデックスライブラリの操作
インデックス ライブラリはデータベース テーブルに似ており、マッピング マッピングはテーブル構造に似ています。
esにデータを格納したい場合は、まず「ライブラリ」と「テーブル」を作成する必要があります。
2.1.mapping マッピングプロパティ
マッピングは、インデックス ライブラリ内のドキュメントに対する制約です。一般的なマッピング属性には次のものがあります。
- type: フィールド データ型、一般的な単純型は次のとおりです。
- 文字列: テキスト (セグメント化できるテキスト)、キーワード (ブランド、国、IP アドレスなどの正確な値)
- 値:long、integer、short、byte、double、float、
- ブール値: ブール値
- 日付: 日付
- オブジェクト: オブジェクト
- Index: インデックスを作成するかどうか、デフォルトは true
- アナライザー: どのトークナイザーを使用するか
- プロパティ: このフィールドのサブフィールド
たとえば、次の json ドキュメント:
{
"age": 21,
"weight": 52.1,
"isMarried": false,
"info": "黑马程序员Java讲师",
"email": "[email protected]",
"score": [99.1, 99.5, 98.9],
"name": {
"firstName": "云",
"lastName": "赵"
}
}
各フィールドのマッピング(マッピング)に対応:
- age: 型は整数です。検索に参加するため、インデックスは true である必要があります。トークナイザーは必要ありません。
- Weight: 型は float です。検索に参加するため、インデックスは true である必要があります。トークナイザーは必要ありません。
- isMarried: タイプはブール型です。検索に参加するため、インデックスは true である必要があります。トークナイザーは必要ありません。
- info: タイプは文字列で、単語の分割が必要なのでテキストです。検索に参加するには、インデックスが true である必要があります。単語の分割では ik_smart を使用できます。
- email: タイプは文字列ですが、単語の分割は必要ないため、キーワードになります。検索には関与しないため、インデックスは false である必要があります。単語の分割は必要ありません。
- スコア: 配列ですが、要素の型 (float) のみを確認します。検索に参加するため、インデックスは true である必要があります。トークナイザーは必要ありません。
- name: タイプはオブジェクトであり、複数のサブ属性を定義する必要があります
- name.firstName; タイプは文字列ですが、単語の分割は必要ないため、キーワードです。検索に参加するため、インデックスは true である必要があります。単語の分割は必要ありません。
- name.lastName; タイプは文字列ですが、単語の分割は必要ないため、キーワードになります。検索に参加するため、インデックスは true である必要があります。単語の分割は必要ありません。
2.2. インデックスライブラリのCRUD
ここでは、一様に Kibana を使用して DSL を記述し、デモを行います。
2.2.1. インデックスライブラリとマッピングの作成
基本的な構文:
- リクエストメソッド:PUT
- リクエスト パス: /index ライブラリ名 (カスタマイズ可能)
- リクエストパラメータ: マッピング マッピング
フォーマット:
PUT /索引库名称
{
"mappings": {
"properties": {
"字段名":{
"type": "text",
"analyzer": "ik_smart"
},
"字段名2":{
"type": "keyword",
"index": "false"
},
"字段名3":{
"properties": {
"子字段": {
"type": "keyword"
}
}
},
// ...略
}
}
}
例:
PUT /heima
{
"mappings": {
"properties": {
"info":{
"type": "text",
"analyzer": "ik_smart"
},
"email":{
"type": "keyword",
"index": "falsae"
},
"name":{
"properties": {
"firstName": {
"type": "keyword"
}
}
},
// ... 略
}
}
}
2.2.2. クエリインデックスライブラリ
基本的な構文:
-
リクエストメソッド:GET
-
リクエストパス: /index ライブラリ名
-
リクエストパラメータ: なし
形式:
GET /索引库名
例:
2.2.3. インデックスライブラリの変更
転置インデックスの構造は複雑ではありませんが、データ構造が変更されると (たとえば、トークナイザーが変更される)、転置インデックスを再作成する必要があり、これは大変なことです。したがって、インデックス ライブラリが作成されると、マッピングを変更することはできません。
マッピング内の既存のフィールドは変更できませんが、逆インデックスには影響しないため、マッピングに新しいフィールドを追加することはできます。
文法説明:
PUT /索引库名/_mapping
{
"properties": {
"新字段名":{
"type": "integer"
}
}
}
例:
2.2.4. インデックスライブラリの削除
文法:
-
リクエストメソッド:DELETE
-
リクエストパス: /index ライブラリ名
-
リクエストパラメータ: なし
フォーマット:
DELETE /索引库名
キバナでのテスト:
2.2.5. 概要
インデックスライブラリの操作とは何ですか?
- インデックス ライブラリを作成します: PUT /インデックス ライブラリ名
- クエリインデックスライブラリ: GET / インデックスライブラリ名
- インデックス ライブラリの削除: DELETE / インデックス ライブラリ名
- フィールドを追加: PUT /index ライブラリ名/_mapping
3. 文書操作
3.1. 新しいドキュメント
文法:
POST /索引库名/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
"字段3": {
"子属性1": "值3",
"子属性2": "值4"
},
// ...
}
例:
POST /heima/_doc/1
{
"info": "黑马程序员Java讲师",
"email": "[email protected]",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
応答:
3.2. ドキュメントのクエリ
REST スタイルによれば、新しい追加は post であり、クエリは get である必要がありますが、クエリには通常条件が必要です。ここではドキュメント ID を持ってきます。
文法:
GET /{
索引库名称}/_doc/{
id}
kibana を通じてデータを表示します。
GET /heima/_doc/1
結果の表示:
3.3. 文書の削除
削除には DELETE リクエストを使用します。同様に、ID に従って削除する必要があります。
文法:
DELETE /{
索引库名}/_doc/id值
例:
# 根据id删除数据
DELETE /heima/_doc/1
結果:
3.4. ドキュメントの変更
変更するには 2 つの方法があります。
- 完全な変更: 元のドキュメントを直接上書きします。
- 増分変更: ドキュメント内の一部のフィールドを変更します。
3.4.1. 完全な修正
完全な変更は元のドキュメントを上書きすることです。その本質は次のとおりです。
- 指定された ID に基づいてドキュメントを削除します
- 同じIDを持つ新しいドキュメントを追加します
注:idによる削除時にそのidが存在しない場合は、2段階目の追加も実行され、変更から追加へ動作が変わります。
文法:
PUT /{
索引库名}/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
// ... 略
}
例:
PUT /heima/_doc/1
{
"info": "黑马程序员高级Java讲师",
"email": "[email protected]",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
3.4.2. 増分修正
増分変更とは、指定された ID に一致するドキュメント内の一部のフィールドのみを変更することです。
文法:
POST /{
索引库名}/_update/文档id
{
"doc": {
"字段名": "新的值",
}
}
例:
POST /heima/_update/1
{
"doc": {
"email": "[email protected]"
}
}
3.5. 概要
文書操作とは何ですか?
- ドキュメントの作成: POST /{インデックス ライブラリ名}/_doc/ドキュメント ID { json ドキュメント }
- ドキュメントのクエリ: GET /{インデックス ライブラリ名}/_doc/ドキュメント ID
- ドキュメントの削除: DELETE /{インデックス ライブラリ名}/_doc/ドキュメント ID
- ドキュメントを変更します。
- 完全な変更: PUT /{インデックス ライブラリ名}/_doc/ドキュメント ID { json ドキュメント }
- 増分変更: POST /{インデックス ライブラリ名}/_update/ドキュメント ID { “doc”: {フィールド}}
4.RestAPI
ESは、ESを操作するためのさまざまな言語のクライアントを正式に提供します。これらのクライアントの本質は、DSL ステートメントを組み立て、http リクエストを通じて ES に送信することです。公式ドキュメントのアドレス: https://www.elastic.co/guide/en/elasticsearch/client/index.html
Java Rest クライアントには 2 つのタイプが含まれます。
- Java 低レベル REST クライアント
- Java高レベルRESTクライアント
私たちが学習しているのは、Java HighLevel Rest Client クライアント API です。
4.0. デモプロジェクトをインポートする
4.0.1. データのインポート
データ構造は次のとおりです。
CREATE TABLE `tb_hotel` (
`id` bigint(20) NOT NULL COMMENT '酒店id',
`name` varchar(255) NOT NULL COMMENT '酒店名称;例:7天酒店',
`address` varchar(255) NOT NULL COMMENT '酒店地址;例:航头路',
`price` int(10) NOT NULL COMMENT '酒店价格;例:329',
`score` int(2) NOT NULL COMMENT '酒店评分;例:45,就是4.5分',
`brand` varchar(32) NOT NULL COMMENT '酒店品牌;例:如家',
`city` varchar(32) NOT NULL COMMENT '所在城市;例:上海',
`star_name` varchar(16) DEFAULT NULL COMMENT '酒店星级,从低到高分别是:1星到5星,1钻到5钻',
`business` varchar(255) DEFAULT NULL COMMENT '商圈;例:虹桥',
`latitude` varchar(32) NOT NULL COMMENT '纬度;例:31.2497',
`longitude` varchar(32) NOT NULL COMMENT '经度;例:120.3925',
`pic` varchar(255) DEFAULT NULL COMMENT '酒店图片;例:/img/1.jpg',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.0.2.マッピング マッピング分析
インデックス ライブラリを作成する鍵となるのはマッピングであり、マッピングに関して考慮すべき情報には次のものが含まれます。
- フィールド名
- フィールドのデータ型
- 捜索に参加するかどうか
- 単語の分割が必要ですか
- 単語の分割の場合、トークナイザーとは何ですか?
の:
- フィールド名、フィールドのデータ型、データテーブル構造の名前と型を参照できます
- 検索に参加するかどうかは画像アドレスなどの事業内容を分析して判断する必要があり、検索に参加する必要はありません
- 単語の分割がコンテンツに依存するかどうか。コンテンツが全体である場合、単語の分割は必要ありません。それ以外の場合、単語の分割が必要です。
- Tokenizer、ik_max_word を均一に使用できます
ホテル データのインデックス ライブラリ構造を見てみましょう。
PUT /hotel
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name":{
"type": "text",
"analyzer": "ik_max_word",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false
},
"price":{
"type": "integer"
},
"score":{
"type": "integer"
},
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword",
"copy_to": "all"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
いくつかの特別なフィールドの説明:
- location: 精度と緯度を含む地理座標
- all: 結合フィールド。その目的は、copy_to を使用して複数のフィールドの値を結合し、検索のためにユーザーに提供することです。
地理座標の説明:
コピー先の説明:
4.0.3. RestClientの初期化
elasticsearch が提供する API では、elasticsearch とのすべての対話は RestHighLevelClient という名前のクラスにカプセル化されており、elasticsearch との接続を確立するには、最初にこのオブジェクトの初期化を完了する必要があります。
3 つのステップに分かれています。
1) es の RestHighLevelClient 依存関係を導入します。
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
2) SpringBoot のデフォルトの ES バージョンは 7.6.2 であるため、デフォルトの ES バージョンをオーバーライドする必要があります。
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
3) RestHighLevelClient を初期化します。
初期化コードは次のとおりです。
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
));
ここでは、単体テストの便宜のために、テスト クラス HotelIndexTest を作成し、@BeforeEach メソッドに初期化コードを記述します。
package cn.itcast.hotel;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
public class HotelIndexTest {
private RestHighLevelClient client;
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
4.1. インデックスライブラリの作成
4.1.1. コードの解釈
インデックス ライブラリを作成するための API は次のとおりです。
コードは 3 つのステップに分かれています。
- 1) リクエストオブジェクトを作成します。インデックス ライブラリを作成する操作であるため、リクエストは CreateIndexRequest です。
- 2) リクエスト パラメータの追加は、実際には DSL の JSON パラメータ部分です。json 文字列は非常に長いため、コードをより洗練されたものにするために静的文字列定数 MAPPING_TEMPLATE がここで定義されています。
- 3) リクエストを送信する場合、 client.indices() メソッドの戻り値は、インデックス ライブラリ操作に関連するすべてのメソッドをカプセル化する IndicesClient タイプです。
4.1.2. 完全な例
Hotel-demo の cn.itcast.hotel.constants パッケージの下に、マッピング マッピングの JSON 文字列定数を定義するクラスを作成します。
package cn.itcast.hotel.constants;
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" +
"}";
}
Hotel-demo の HotelIndexTest テスト クラスで、インデックスを作成する単体テストを作成します。
@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);
}
4.2. インデックスライブラリの削除
インデックス ストアを削除する DSL ステートメントは非常に簡単です。
DELETE /hotel
インデックス ライブラリの作成と比較すると、次のようになります。
- リクエストメソッドが PUT から DELTE に変更されました
- リクエストのパスは変更されません
- リクエストパラメータがありません
したがって、コードの違いは Request オブジェクトに反映される必要があります。まだ 3 つのステップがあります。
- 1) リクエストオブジェクトを作成します。今回は DeleteIndexRequest オブジェクトです
- 2) パラメータを準備します。ここにはパラメータはありません
- 3) リクエストを送信します。代わりに delete メソッドを使用してください
Hotel-demo の HotelIndexTest テスト クラスで、インデックスを削除する単体テストを作成します。
@Test
void testDeleteHotelIndex() throws IOException {
// 1.创建Request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
4.3. インデックスライブラリが存在するかどうかを確認する
インデックス ライブラリが存在するかどうかを判断する本質はクエリであり、対応する DSL は次のとおりです。
GET /hotel
つまり、削除された Java コード フローと似ています。まだ 3 つのステップがあります。
- 1) リクエストオブジェクトを作成します。今回は GetIndexRequest オブジェクト
- 2) パラメータを準備します。ここにはパラメータはありません
- 3) リクエストを送信します。代わりにexistsメソッドを使用してください
@Test
void testExistsHotelIndex() throws IOException {
// 1.创建Request对象
GetIndexRequest request = new GetIndexRequest("hotel");
// 2.发送请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 3.输出
System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}
4.4. 概要
JavaRestClient が elasticsearch を操作するプロセスは基本的に同様です。中心となるのは、インデックス ライブラリの操作オブジェクトを取得する client.indices() メソッドです。
インデックス ライブラリ操作の基本的な手順は次のとおりです。
- RestHighLevelClient を初期化する
- XxxIndexRequest を作成します。XXX は作成、取得、削除です
- DSL の準備 (作成時に必須、その他はパラメーターなし)
- リクエストを送信します。RestHighLevelClient#indices().xxx() メソッドを呼び出します。xxx は create、existent、delete です。
5.RestClient操作ドキュメント
インデックス ライブラリの操作から分離するために、次の 2 つのことを行うテスト クラスを再度追加します。
- RestHighLevelClient を初期化する
- ホテルのデータはデータベース内にあり、クエリには IHotelService を使用する必要があるため、このインターフェイスを挿入します。
package cn.itcast.hotel;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.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://192.168.150.101:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
5.1. 新しいドキュメント
データベースからホテル データをクエリし、elasticsearch に書き込みたいと考えています。
5.1.1. インデックスライブラリエンティティクラス
データベース クエリの結果は、ホテル タイプのオブジェクトです。構造は次のとおりです。
@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;
}
インデックス ライブラリの構造には次のような違いがあります。
- 経度と緯度を位置に結合する必要がある
したがって、インデックス ライブラリの構造に一致する新しい型を定義する必要があります。
package cn.itcast.hotel.pojo;
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();
}
}
5.1.2. 構文の説明
新しく追加されたドキュメントの DSL ステートメントは次のとおりです。
POST /{
索引库名}/_doc/1
{
"name": "Jack",
"age": 21
}
これも次の 3 段階のプロセスです。
- 1) リクエストオブジェクトを作成する
- 2) リクエストパラメータ(DSL 内の JSON ドキュメント)を準備します。
- 3) リクエストの送信
変更点は、ここでは client.xxx() の API が直接使用され、 client.indices() が不要になったことです。
5.1.3. 完全なコード
ホテル データをインポートする場合、基本的なプロセスは同じですが、考慮する必要がある変更がいくつかあります。
- ホテル データはデータベースから取得されます。ホテル オブジェクトを取得するには、まずデータベースにクエリを実行する必要があります。
- ホテル オブジェクトは HotelDoc オブジェクトに変換する必要があります
- HotelDoc は json 形式にシリアル化する必要があります
したがって、コードの全体的な手順は次のようになります。
- 1) ホテルデータをクエリ ID に基づいてホテルを検索します
- 2) ホテルを HotelDoc としてパッケージ化
- 3) HotelDoc を JSON にシリアル化する
- 4) IndexRequest を作成し、インデックス ライブラリの名前と ID を指定します。
- 5) リクエストパラメータ(JSONドキュメント)を準備します。
- 6) リクエストの送信
Hotel-demo の HotelDocumentTest テスト クラスで、単体テストを作成します。
@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);
}
5.2. ドキュメントのクエリ
5.2.1. 構文の説明
クエリ DSL ステートメントは次のとおりです。
GET /hotel/_doc/{
id}
非常にシンプルなので、コードは大きく 2 つのステップに分かれています。
- リクエストオブジェクトを準備する
- リクエストを送信する
ただし、クエリの目的は、HotelDoc に解析される結果を取得することなので、結果の解析が困難になります。完全なコードは次のとおりです。
ご覧のとおり、結果は JSON であり、ドキュメントが_source
属性に配置されているため、解析ではそれを取得し_source
、Java オブジェクトに逆シリアル化します。
以前と同様に、これも 3 つのステップからなるプロセスです。
- 1) Request オブジェクトを準備します。今回はクエリなのでGetRequest
- 2) リクエストを送信し、結果を取得します。クエリなのでここで client.get() メソッドが呼び出されます。
- 3) 解析結果は、JSON を逆シリアル化します。
5.2.2. 完全なコード
Hotel-demo の HotelDocumentTest テスト クラスで、単体テストを作成します。
@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);
}
5.3. 文書の削除
削除用の DSL は次のようなものです。
DELETE /hotel/_doc/{
id}
クエリと比較すると、リクエスト メソッドが DELETE から GET に変わるだけですが、Java コードは引き続き 3 つのステップを踏む必要があると考えられます。
- 1) Request オブジェクトを準備します。削除されるため、今回は DeleteRequest オブジェクトです。インデックス ライブラリの名前と ID を指定するには
- 2) パラメータを準備する、パラメータなし
- 3) リクエストを送信します。削除されるのでclient.delete()メソッドです
Hotel-demo の HotelDocumentTest テスト クラスで、単体テストを作成します。
@Test
void testDeleteDocument() throws IOException {
// 1.准备Request
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
5.4. ドキュメントの変更
5.4.1. 構文の説明
2 つの方法について説明しました。
- 完全な変更: 本質は、最初に ID に従って削除し、次に追加することです。
- 増分変更: ドキュメント内の指定されたフィールド値を変更します。
RestClient API では、完全な変更は新しく追加された API とまったく同じであり、判断は ID に基づいて行われます。
- 追加時にIDがすでに存在する場合は変更してください
- 追加時にIDが存在しない場合は追加してください
ここでは詳細には触れませんが、主に増分修正に焦点を当てます。
これも次の 3 段階のプロセスです。
- 1) Request オブジェクトを準備します。今回は修正なのでUpdateRequestです
- 2) パラメータを準備します。つまり、変更するフィールドを含む JSON ドキュメントです。
- 3) ドキュメントを更新します。ここで client.update() メソッドを呼び出します
5.4.2. 完全なコード
Hotel-demo の HotelDocumentTest テスト クラスで、単体テストを作成します。
@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.5. ドキュメントのバッチインポート
ケースの要件: BulkRequest を使用して、データベース データをインデックス ライブラリにバッチでインポートします。
次のように進めます。
-
mybatis-plus を使用してホテル データをクエリする
-
クエリされたホテル データ (Hotel) をドキュメント タイプ データ (HotelDoc) に変換します。
-
JavaRestClient で BulkRequest バッチ処理を使用してドキュメントをバッチで追加する
5.5.1. 構文の説明
BulkRequest バッチ処理の本質は、複数の通常の CRUD リクエストを結合して一緒に送信することです。
他のリクエストを追加するための add メソッドが提供されます。
ご覧のとおり、追加できるリクエストには次のものがあります。
- 追加する IndexRequest
- UpdateRequest、変更するものです
- DeleteRequest、つまり削除
実際には、まだ 3 つのステップがあります。
- 1) リクエストオブジェクトを作成します。一括リクエストはこちら
- 2) パラメータを準備します。バッチ処理のパラメータは他の Request オブジェクトです。ここでは複数の IndexRequest が使用されます。
- 3) リクエストを開始します。これはバッチ処理であり、呼び出されるメソッドは client.bulk() メソッドです
ホテル データをインポートするときに、上記のコードを for ループに変換できます。
5.5.2. 完全なコード
Hotel-demo の HotelDocumentTest テスト クラスで、単体テストを作成します。
@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);
}
5.6. 概要
ドキュメント操作の基本的な手順は次のとおりです。
- RestHighLevelClient を初期化する
- XxxRequest を作成します。XXX はインデックス、取得、更新、削除、一括です
- パラメータを準備します (インデックス、更新、一括に必要)
- リクエストを送信します。RestHighLevelClient#.xxx() メソッドを呼び出します。xxx は、index、get、update、delete、bulk です。
- 解析結果 (Get に必要)