このページでは、OpenSearch SDK for Java V3.1 を使用してドキュメントを OpenSearch アプリケーションにプッシュする方法を説明します。例では、ADD、UPDATE、DELETE の各操作を単一のバッチプッシュで実行し、その後検索クエリを実行して結果を検証します。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
少なくとも 1 つのテーブルが設定済みの OpenSearch アプリケーション
AliyunServiceRoleForOpenSearchロールに必要な権限が付与された RAM ユーザーの AccessKey ID と AccessKey Secret。 ロールの詳細については、「AliyunServiceRoleForOpenSearch」をご参照ください。 権限の詳細については、「アクセス権限付与ルール」をご参照くださいプロジェクトに OpenSearch SDK for Java V3.1 が追加済みであること
RAM ユーザーの AccessKey ペアを、Alibaba Cloud アカウントの AccessKey ペアの代わりに使用してください。アカウントレベルの AccessKey ペアは、すべての API オペレーションへのアクセスを許可し、セキュリティリスクが高くなります。RAM ユーザーを作成する方法については、「RAM ユーザーの作成」をご参照ください。AccessKey ペアを作成する方法については、「AccessKey ペアの作成」をご参照ください。
認証情報の設定
AccessKey ペアを環境変数として保存します。これにより、認証情報がソースコードに含まれるのを防ぎます。
Linux および macOS
export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id>
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret><access_key_id> および <access_key_secret> を、ご利用の RAM ユーザーの AccessKey ID および AccessKey Secret に置き換えてください。
Windows
環境変数ファイルを作成し、
ALIBABA_CLOUD_ACCESS_KEY_IDおよびALIBABA_CLOUD_ACCESS_KEY_SECRETをそれぞれ対応する値に設定します。変更を有効にするために Windows を再起動します。
仕組み
プッシュのワークフローは、以下の 3 つのステップで構成されます。
各ドキュメントをフィールド値を含む
Mapオブジェクトとして構築し、それをコマンド(ADDまたはDELETE)とともにJSONObjectでラップします。すべての
JSONObjectエントリをJSONArrayに収集し、documentClient.push()を呼び出して、バッチをアプリケーションに送信します。プッシュ後に、
SearcherClientを使用した検索クエリを実行し、ドキュメントが検索結果に正しく表示されることを検証します。
1 回のプッシュ呼び出しでは、同一テーブルに属するフィールドのみをプッシュできます。異なるテーブルのフィールドを 1 回の呼び出しでプッシュすることはサポートされていません。
制限事項とデータ形式
データセットは有効なデータ形式である必要があります。サンプルファイルをテンプレートとしてダウンロードするには、OpenSearch コンソールにログインし、「インスタンス管理」ページに移動してご利用のアプリケーションを見つけ、その他の操作 > ファイルのアップロード を 操作 列から選択します。
以下の例に示すように、
JSONObjectおよびJSONArrayオブジェクトを直接使用してドキュメントを構築します。1 回のプッシュで送信するドキュメント数が上限を超えると、エラーが発生してプッシュは失敗します。
標準アプリケーションでは、ドキュメントの追加および完全な置き換えの両方に対して
ADDコマンドがサポートされています。UPDATEコマンド(一部フィールドの更新)は、高度アプリケーションでのみサポートされています。
ドキュメントのプッシュと検索
以下の例では、1 回の呼び出しで 4 つのドキュメントをプッシュします。具体的には、2 つのドキュメント(doc1、doc2)を追加し、1 つのドキュメント(doc2 を doc3 で置き換え)を更新し、1 つのドキュメント(doc1)を削除します。その後、プライマリキーによる検索を実行して結果を検証します。
package com.aliyun.opensearch;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Maps;
import com.aliyun.opensearch.sdk.dependencies.org.json.JSONArray;
import com.aliyun.opensearch.sdk.dependencies.org.json.JSONObject;
import com.aliyun.opensearch.sdk.generated.OpenSearch;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchResult;
import com.aliyun.opensearch.sdk.generated.document.Command;
import com.aliyun.opensearch.sdk.generated.document.DocumentConstants;
import com.aliyun.opensearch.sdk.generated.search.*;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Random;
public class testPushSearch2 {
private String appName = "Name of the OpenSearch application that you want to manage"; // (1)
private String tableName = "Name of the table to which data is to be uploaded"; // (2)
private String host = "Endpoint of the OpenSearch API in your region"; // (3)
public static void main(String[] args) {
// Read credentials from environment variables // (4)
String accesskey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String secret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
System.out.println(String.format("file.encoding: %s", System.getProperty("file.encoding")));
System.out.println(String.format("defaultCharset: %s", Charset.defaultCharset().name()));
// ---- Build documents ----
// Generate random primary key values for doc1 and doc2 // (5)
Random rand = new Random();
int value1 = rand.nextInt(Integer.MAX_VALUE);
int value2 = rand.nextInt(Integer.MAX_VALUE);
// doc1: ADD — adds a new document // (6)
Map<String, Object> doc1 = Maps.newLinkedHashMap();
doc1.put("id", value1);
String title_string = "Upload doc1 in push mode";// UTF-8.
byte[] bytes;
try {
bytes = title_string.getBytes("utf-8");
String utf8_string = new String(bytes, "utf-8");
doc1.put("name", utf8_string);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
doc1.put("phone", "137****1111");
int[] int_arr = {11,11};
doc1.put("int_arr", int_arr);
String[] literal_arr1 = {"Upload doc1 in push mode","Test uploading doc1 in push mode"};
doc1.put("literal_arr", literal_arr1);
float[] float_arr = {(float)1.1,(float)1.1};
doc1.put("float_arr", float_arr);
doc1.put("cate_id", 1);
// Standard applications use ADD for both adding and fully replacing documents. // (7)
// UPDATE (partial field update) is not supported for standard applications.
JSONObject json1 = new JSONObject();
json1.put(DocumentConstants.DOC_KEY_CMD, Command.ADD.toString());
json1.put(DocumentConstants.DOC_KEY_FIELDS, doc1);
// doc2: ADD — adds a new document // (8)
Map<String, Object> doc2 = Maps.newLinkedHashMap();
doc2.put("id", value2);
String title_string2 = "Upload doc2 in push mode";// UTF-8.
byte[] bytes2;
try {
bytes2 = title_string2.getBytes("utf-8");
String utf8_string2 = new String(bytes2, "utf-8");
doc2.put("name", utf8_string2);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
doc2.put("phone", "137****2222");
int[] int_arr2 = {22,22};
doc2.put("int_arr", int_arr2);
String[] literal_arr2 = {"Upload doc2 in push mode","Test uploading doc2 in push mode"};
doc2.put("literal_arr", literal_arr2);
float[] float_arr2 = {(float)2.2,(float)2.2};
doc2.put("float_arr", float_arr2);
doc2.put("cate_id", 1);
JSONObject json2 = new JSONObject();
json2.put(DocumentConstants.DOC_KEY_CMD, Command.ADD.toString());
json2.put(DocumentConstants.DOC_KEY_FIELDS, doc2);
// doc3: ADD with doc2's primary key — replaces doc2 with doc3's field values // (9)
Map<String, Object> doc3 = Maps.newLinkedHashMap();
doc3.put("id", value2); // same primary key as doc2
String title_string3 = "Update doc2 to doc3 in push mode";// UTF-8.
byte[] bytes3;
try {
bytes3 = title_string3.getBytes("utf-8");
String utf8_string3 = new String(bytes3, "utf-8");
doc3.put("name", utf8_string3);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
doc3.put("phone", "137****3333");
int[] int_arr3 = {33,33};
doc3.put("int_arr", int_arr3);
String[] literal_arr3 = {"Update doc2 to doc3 in push mode","Update doc2 to doc3 in push mode"};
doc3.put("literal_arr", literal_arr3);
float[] float_arr3 = {(float)3.3,(float)3.3};
doc3.put("float_arr", float_arr3);
doc3.put("cate_id", 1);
JSONObject json3 = new JSONObject();
json3.put(DocumentConstants.DOC_KEY_CMD, Command.ADD.toString());
json3.put(DocumentConstants.DOC_KEY_FIELDS, doc3);
// doc4: DELETE — removes doc1 by primary key only // (10)
Map<String, Object> doc4 = Maps.newLinkedHashMap();
doc4.put("id", value1); // only the primary key is needed for deletion
JSONObject json4 = new JSONObject();
json4.put(DocumentConstants.DOC_KEY_CMD, Command.DELETE.toString());
json4.put(DocumentConstants.DOC_KEY_FIELDS, doc4);
// ---- Push documents ----
JSONArray docsJsonArr = new JSONArray();
docsJsonArr.put(json1); // add doc1
docsJsonArr.put(json2); // add doc2
docsJsonArr.put(json3); // replace doc2 with doc3
docsJsonArr.put(json4); // delete doc1
String docsJson = docsJsonArr.toString();
// Initialize the client // (11)
OpenSearch openSearch = new OpenSearch(accesskey, secret, host);
OpenSearchClient serviceClient = new OpenSearchClient(openSearch);
DocumentClient documentClient = new DocumentClient(serviceClient);
try {
OpenSearchResult osr = documentClient.push(docsJson, appName, tableName); // (12)
// A "true" result means the push request was accepted without errors.
// Check the OpenSearch console error logs for any post-push processing errors
// (such as field type conversion failures).
if (osr.getResult().equalsIgnoreCase("true")) {
System.out.println("Push accepted. Request ID: " + osr.getTraceInfo().getRequestId());
} else {
System.out.println("Push failed: " + osr.getTraceInfo());
}
} catch (OpenSearchException e) {
e.printStackTrace();
} catch (OpenSearchClientException e) {
e.printStackTrace();
}
// ---- Query to verify ----
// Wait 1 second for indexing to complete before querying // (13)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SearcherClient searcherClient = new SearcherClient(serviceClient);
// Configure paging and return format // (14)
Config config = new Config(Lists.newArrayList(appName));
config.setStart(0);
config.setHits(30);
config.setSearchFormat(SearchFormat.JSON); // supported formats: XML, JSON (FULLJSON not supported)
config.setFetchFields(Lists.newArrayList("id", "name", "phone", "int_arr", "literal_arr", "float_arr", "cate_id"));
SearchParams searchParams = new SearchParams(config);
// Query by primary key — match either value1 or value2 // (15)
// To query on multiple index fields, combine them in one setQuery call.
// Each additional setQuery call overwrites the previous one.
searchParams.setQuery("id:'" + value1 + "'|'" + value2 + "'");
searchParams.setFilter("cate_id<=3");
// Sort by id descending; break ties by RANK ascending // (16)
Sort sorter = new Sort();
sorter.addToSortFields(new SortField("id", Order.DECREASE));
sorter.addToSortFields(new SortField("RANK", Order.INCREASE));
searchParams.setSort(sorter);
try {
SearchResult searchResult = searcherClient.execute(searchParams);
String result = searchResult.getResult();
JSONObject obj = new JSONObject(result);
System.out.println(obj.toString());
} catch (OpenSearchException e) {
e.printStackTrace();
} catch (OpenSearchClientException e) {
e.printStackTrace();
}
}
}アノテーションの説明:
| # | 説明 |
|---|---|
| (1) | appName をご利用の OpenSearch アプリケーション名に設定します。 |
| (2) | tableName を、データをプッシュするアプリケーション内のテーブル名に設定します。 |
| (3) | host を、ご利用のリージョンにおける OpenSearch API のエンドポイントに設定します。 |
| (4) | 認証情報は、「認証情報の設定」で設定した環境変数から読み込まれます。 |
| (5) | このデモでは、ランダム整数をプライマリキー値として使用しています。本番環境では、実際のドキュメント ID を使用してください。 |
| (6) | 各ドキュメントは Map<String, Object> として構築され、その後 JSONObject でラップされ、DOC_KEY_CMD および DOC_KEY_FIELDS が設定されます。 |
| (7) | Command.ADD は、プライマリキーが存在しない場合は新規ドキュメントを追加し、存在する場合は既存ドキュメントを完全に置き換えます。 |
| (8) | 2 つ目のドキュメント(doc2)は、独自のユニークなプライマリキー(value2)で追加されます。 |
| (9) | doc3 は doc2 と同じプライマリキー(value2)を使用するため、ADD コマンドによって doc2 が doc3 のフィールド値で完全に置き換えられます。 |
| (10) | Command.DELETE はプライマリキーでドキュメントを削除します。ペイロードにはプライマリキーのフィールドのみが必要です。 |
| (11) | 認証情報およびエンドポイントを用いて OpenSearch オブジェクトを作成し、これをもとに OpenSearchClient および DocumentClient を初期化します。 |
| (12) | documentClient.push() は、1 回のリクエストでバッチ全体を送信します。「true」という結果はリクエストが受理されたことを意味します。プッシュ後の処理エラー(例:フィールド型変換失敗など)については、コンソールのエラーログを確認してください。 |
| (13) | インデックス作成は非同期です。検証クエリを実行する前に、1 秒間待機することでインデックス作成に十分な時間を確保します。本番環境では、リトライまたはポーリング戦略を実装してください。 |
| (14) | Config はページングパラメーター(start、hits)および応答フォーマットを設定します。fetchFields は返されるフィールドを制御します。 |
| (15) | クエリでは、id インデックスフィールドを使用して、いずれかのプライマリキーに一致させます。複数のフィールドを組み合わせてクエリする場合は、単一の setQuery 呼び出しで指定する必要があります。各呼び出しは前の呼び出しを上書きします。 |
| (16) | 結果は id を降順でソートされます。id の値が同じ複数のドキュメントがある場合、関連性スコア(RANK)を昇順でソートします。 |