Use the OpenSearch SDK for Java V3.1 to add, update, and delete documents in an OpenSearch table using commit mode. In commit mode, you batch documents into a client buffer and flush them to the index with a single commit() call.
This approach works well for:
Dynamically merging and committing data
Committing a single document
Committing a small number of documents at a time
You can commit data only to fields within the same table. Committing data across tables is not supported.
Prerequisites
Before you begin, make sure you have:
An OpenSearch application and a table to commit data to
An AccessKey pair for a Resource Access Management (RAM) user with the permissions granted by the service-linked role AliyunServiceRoleForOpenSearch. For more information, see Access authorization rules
The OpenSearch SDK for Java V3.1 added to your project
Use the AccessKey pair of a RAM user, not your Alibaba Cloud account root credentials. Root credentials grant access to all API operations and pose a higher security risk. To create a RAM user and an AccessKey pair, see Create a RAM user and Create an AccessKey pair.
Configure environment variables
Store your credentials as environment variables instead of hardcoding them in source code. Hardcoded credentials can be accidentally committed to version control and compromise the security of your account.
Linux and macOS
Replace <access_key_id> and <access_key_secret> with your RAM user's AccessKey ID and AccessKey secret, then run:
export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id>
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret>Windows
Create an environment variable file and add
ALIBABA_CLOUD_ACCESS_KEY_IDandALIBABA_CLOUD_ACCESS_KEY_SECRETwith their corresponding values.Restart Windows for the changes to take effect.
How commit mode works
Commit mode uses a client-side buffer to batch document operations:
Create a
DocumentClientby chainingOpenSearch→OpenSearchClient→DocumentClient.Call
add(),update(), orremove()to stage documents in the buffer.Call
commit(appName, tableName)to flush all staged operations to OpenSearch.Check the result — a successful commit returns
"true"fromosr.getResult(). Errors that occur after the commit (such as field conversion failures) are recorded in the OpenSearch console error logs.
Connect to OpenSearch
All document operations share the same client setup. Replace the placeholder values with your application name, table name, and regional API endpoint.
// Replace with your OpenSearch application name, table name, and regional API endpoint
private static String appName = "<your-app-name>";
private static String tableName = "<your-table-name>";
private static String host = "<your-api-endpoint>";
// Read credentials from environment variables
String accesskey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String secret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Build the client chain: OpenSearch → OpenSearchClient → DocumentClient
OpenSearch openSearch = new OpenSearch(accesskey, secret, host);
OpenSearchClient serviceClient = new OpenSearchClient(openSearch);
DocumentClient documentClient = new DocumentClient(serviceClient);| Placeholder | Description |
|---|---|
<your-app-name> | Name of the OpenSearch application |
<your-table-name> | Name of the table to commit data to |
<your-api-endpoint> | OpenSearch API endpoint for your region |
Full demo code
The following example demonstrates the complete commit-mode workflow: add a document, update it, delete it, and verify the deletion with a search query.
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.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.search.Config;
import com.aliyun.opensearch.sdk.generated.search.SearchFormat;
import com.aliyun.opensearch.sdk.generated.search.SearchParams;
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 testCommitSearch {
private static String appName = "The name of the OpenSearch application to which you want to commit data";
private static String tableName = "The name of the table to which you want to commit data";
private static String host = "Endpoint of the OpenSearch API in your region";
public static void main(String[] args) {
// Read AccessKey credentials from environment variables.
// Configure the environment variables before running this code.
String accesskey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String secret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Print the default file encoding and charset for debugging purposes.
System.out.println(
String.format("file.encoding: %s", System.getProperty("file.encoding"))
);
System.out.println(
String.format("defaultCharset: %s", Charset.defaultCharset().name())
);
// Use a random integer as the primary key for this demo.
Random rand = new Random();
int value = rand.nextInt(Integer.MAX_VALUE);
// ── Step 1: Add a document ───────────────────────────────────────────────
// Build doc1 as a Map. Each key corresponds to a field in the table.
Map<String, Object> doc1 = Maps.newLinkedHashMap();
doc1.put("id", value); // primary key
// Encode the title string as UTF-8 explicitly.
String title_string = "Upload doc1 in commit mode";
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", "1381111****");
doc1.put("int_arr", new int[]{ 33, 44 });
doc1.put("literal_arr", new String[]{
"Upload doc1 in commit mode",
"Test uploading doc1 in commit mode]"
});
doc1.put("float_arr", new float[]{ 1.1f, 1.2f });
doc1.put("cate_id", 1);
// Build the client chain.
OpenSearch openSearch1 = new OpenSearch(accesskey, secret, host);
OpenSearchClient serviceClient1 = new OpenSearchClient(openSearch1);
DocumentClient documentClient1 = new DocumentClient(serviceClient1);
// Stage doc1 as a new document in the client buffer.
documentClient1.add(doc1);
System.out.println(doc1.toString());
try {
// Flush the buffer. All staged documents are submitted in one request.
OpenSearchResult osr = documentClient1.commit(appName, tableName);
// osr.getResult() returns "true" when the commit request itself succeeds.
// Post-commit errors (e.g., field conversion failures) appear in the
// OpenSearch console error logs, not in this result.
if (osr.getResult().equalsIgnoreCase("true")) {
System.out.println("Commit succeeded. Request ID: " +
osr.getTraceInfo().getRequestId());
} else {
System.out.println("Commit failed: " + osr.getTraceInfo());
}
} catch (OpenSearchException e) {
e.printStackTrace();
} catch (OpenSearchClientException e) {
e.printStackTrace();
}
// Wait 10 seconds for the document to be indexed before querying.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// ── Step 2: Update the document ─────────────────────────────────────────
// Build doc2 with the same primary key as doc1 to target the same document.
Map<String, Object> doc2 = Maps.newLinkedHashMap();
doc2.put("id", value); // must match doc1's primary key
String title_string2 = "Update doc2 in commit mode";
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", "1390000****");
doc2.put("int_arr", new int[]{ 22, 22 });
doc2.put("literal_arr", new String[]{
"Update doc1 in commit mode",
"Update doc1 in commit mode"
});
doc2.put("float_arr", new float[]{ 1.1f, 1.2f });
doc2.put("cate_id", 1);
// Stage doc2 as an update. The primary key must be valid for the update to succeed.
documentClient1.update(doc2);
System.out.println(doc2.toString());
try {
OpenSearchResult osr = documentClient1.commit(appName, tableName);
if (osr.getResult().equalsIgnoreCase("true")) {
System.out.println("Commit succeeded. Request ID: " +
osr.getTraceInfo().getRequestId());
} else {
System.out.println("Commit failed: " + osr.getTraceInfo());
}
} catch (OpenSearchException e) {
e.printStackTrace();
} catch (OpenSearchClientException e) {
e.printStackTrace();
}
// Wait 10 seconds for the update to be indexed.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// ── Step 3: Delete the document ─────────────────────────────────────────
// Only the primary key is required to delete a document.
Map<String, Object> doc3 = Maps.newLinkedHashMap();
doc3.put("id", value);
documentClient1.remove(doc3);
System.out.println(doc3.toString());
try {
OpenSearchResult osr = documentClient1.commit(appName, tableName);
if (osr.getResult().equalsIgnoreCase("true")) {
System.out.println("Commit succeeded. Request ID: " +
osr.getTraceInfo().getRequestId());
} else {
System.out.println("Commit failed: " + osr.getTraceInfo());
}
} catch (OpenSearchException e) {
e.printStackTrace();
} catch (OpenSearchClientException e) {
e.printStackTrace();
}
// Wait at least 1 second (10 seconds here) before querying after a delete.
// Querying immediately after removal may still return the deleted document.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// ── Step 4: Verify the deletion with a search query ──────────────────────
OpenSearch openSearch2 = new OpenSearch(accesskey, secret, host);
OpenSearchClient serviceClient2 = new OpenSearchClient(openSearch2);
SearcherClient searcherClient2 = new SearcherClient(serviceClient2);
// Configure paging: start at offset 0, return up to 30 hits per page.
// Supported formats: XML and JSON. FULLJSON is not supported.
Config config = new Config(Lists.newArrayList(appName));
config.setStart(0);
config.setHits(30);
config.setSearchFormat(SearchFormat.JSON);
SearchParams searchParams = new SearchParams(config);
searchParams.setQuery("id:'" + value + "'");
try {
SearchResult searchResult = searcherClient2.execute(searchParams);
String result = searchResult.getResult();
JSONObject obj = new JSONObject(result);
System.out.println("Search results: " + obj.toString());
} catch (OpenSearchException e) {
e.printStackTrace();
} catch (OpenSearchClientException e) {
e.printStackTrace();
}
}
}Usage notes
Commit result vs. indexing errors
A successful commit (osr.getResult() returns "true") means no error occurred when committing the data. It does not guarantee that every document was indexed successfully — whether data is committed also depends on whether errors occur in the OpenSearch console. Post-commit errors — such as field type conversion failures — are recorded in the OpenSearch console error logs. Check the error logs after committing to confirm all documents were indexed.
Timing after commit
OpenSearch indexes committed documents asynchronously. Wait at least one second before querying after a delete operation — documents that have been removed may still appear in search results if queried immediately. The demo uses a 10-second wait to allow enough time for indexing.