PolarSearch完全兼容OpenSearch的官方客户端,您可以使用相应的客户端与PolarSearch进行交互。这使得您能够通过Java或Python等常用编程语言高效地管理索引、操作文档(包括增、删、改、查)以及执行复杂搜索,从而将搜索功能无缝集成到您的应用程序中。
准备工作
已创建含有PolarSearch节点的集群并设置了节点的管理员账号。
获取连接地址:在集群的数据库节点区域,将鼠标悬浮在搜索节点,根据您的业务环境,获取PolarSearch节点的私网或公网地址。
连接集群
Java client
1. 选择传输层并添加依赖
OpenSearch Java客户端需要搭配一个传输层框架来处理HTTP请求。您可以根据项目需求选择Apache HttpClient5或RestClient。
【推荐】Apache HttpClient5
Maven
在pom.xml文件中添加以下依赖:<!-- OpenSearch Java Client核心库 --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-java</artifactId> <version>2.19.0</version> </dependency> <!-- Apache HttpClient5 传输层 --> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2.1</version> </dependency>Gradle
在build.gradle文件中添加以下依赖:dependencies { // OpenSearch Java Client核心库 implementation 'org.opensearch.client:opensearch-java:2.19.0' // Apache HttpClient5 传输层 implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1' }
RestClient
Maven
在pom.xml文件中添加以下依赖:<!-- OpenSearch Java Client核心库 --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-java</artifactId> <version>2.19.0</version> </dependency> <!-- RestClient 传输层 --> <dependency> <groupId>org.opensearch.client</groupId> <artifactId>opensearch-rest-client</artifactId> <version>2.19.0</version> </dependency>Gradle
在build.gradle文件中添加以下依赖:dependencies { // OpenSearch Java Client核心库 implementation 'org.opensearch.client:opensearch-java:2.19.0' // RestClient 传输层 implementation 'org.opensearch.client:opensearch-rest-client:2.19.0' }
2. 设置数据类
创建一个测试数据类,以供后续测试PolarSearch功能使用。
static class IndexData {
private String title;
private String text;
public IndexData() {}
public IndexData(String title, String text) {
this.title = title;
this.text = text;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return String.format("IndexData{title='%s', text='%s'}", title, text);
}
}3. 初始化客户端
根据您选择的传输层,使用PolarSearch的连接信息初始化客户端。在实际使用中,您可以根据以下代码配置将PolarSearch的相关信息设置为环境变量,或直接将其赋值为参数的默认值,以便于测试使用。
Apache HttpClient5
以下示例展示了如何初始化一个客户端,当前示例代码禁用了SSL。
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;
public class CreateClient {
public static void main(String[] args) throws Exception {
var env = System.getenv();
var hostname = env.getOrDefault("HOST", "<polarsearch_host>");
var port = Integer.parseInt(env.getOrDefault("PORT", "<polarsearch_port>"));
var user = env.getOrDefault("USERNAME", "<polarsearch_username>");
var pass = env.getOrDefault("PASSWORD", "<polarsearch_password>");
final var hosts = new HttpHost[] { new HttpHost("http", hostname, port) };
final var sslContext = SSLContextBuilder.create().loadTrustMaterial(null, (chains, authType) -> true).build();
final var transport = ApacheHttpClient5TransportBuilder.builder(hosts)
.setMapper(new JacksonJsonpMapper())
.setHttpClientConfigCallback(httpClientBuilder -> {
final var credentialsProvider = new BasicCredentialsProvider();
for (final var host : hosts) {
credentialsProvider.setCredentials(new AuthScope(host), new UsernamePasswordCredentials(user, pass.toCharArray()));
}
// Disable SSL/TLS verification as our local testing clusters use self-signed certificates
final var tlsStrategy = ClientTlsStrategyBuilder.create()
.setSslContext(sslContext)
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
final var connectionManager = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(tlsStrategy).build();
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider).setConnectionManager(connectionManager);
})
.build();
OpenSearchClient client = new OpenSearchClient(transport);
}
}RestClient
以下示例展示了如何初始化一个客户端,当前示例代码禁用了SSL。
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.opensearch.client.RestClient;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.rest_client.RestClientTransport;
public class CreateRestClient {
public static void main(String[] args) throws Exception {
var env = System.getenv();
var hostname = env.getOrDefault("HOST", "<polarsearch_host>");
var port = Integer.parseInt(env.getOrDefault("PORT", "<polarsearch_port>"));
var user = env.getOrDefault("USERNAME", "<polarsearch_username>");
var pass = env.getOrDefault("PASSWORD", "<polarsearch_password>");
final org.apache.http.HttpHost[] restHosts = new org.apache.http.HttpHost[] {new org.apache.http.HttpHost(hostname, port, "http")};
RestClient restClient = RestClient.builder(restHosts)
.setHttpClientConfigCallback(httpClientBuilder -> {
final org.apache.http.impl.client.BasicCredentialsProvider credentialsProvider = new org.apache.http.impl.client.BasicCredentialsProvider();
for (final org.apache.http.HttpHost ignored : restHosts) {
credentialsProvider.setCredentials(org.apache.http.auth.AuthScope.ANY, new org.apache.http.auth.UsernamePasswordCredentials(user, pass));
}
try {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
// disable the certificate since our testing cluster just uses the default security configuration
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setSSLContext(SSLContextBuilder.create().loadTrustMaterial(null, (chains, authType) -> true).build());
} catch (Exception e) {
throw new RuntimeException(e);
}
}).build();
final RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
final OpenSearchClient client = new OpenSearchClient(transport);
}
}4. 执行基本操作
以下代码片段展示了如何执行常见的索引和文档操作。
创建索引
String index = "sample-index";
CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder().index(index).build();
client.indices().create(createIndexRequest);写入文档
IndexData indexData = new IndexData("first_name", "Bruce");
IndexRequest<IndexData> indexRequest = new IndexRequest.Builder<IndexData>().index(index).id("1").document(indexData).build();
client.index(indexRequest);搜索文档
SearchResponse<IndexData> searchResponse = client.search(s -> s.index(index), IndexData.class);
for (int i = 0; i< searchResponse.hits().hits().size(); i++) {
System.out.println(searchResponse.hits().hits().get(i).source());
}删除文档
client.delete(b -> b.index(index).id("1"));删除索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(index).build();
DeleteIndexResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest);Java high-level REST client
建议您使用Java client,因为Java high-level REST client已在OpenSearch中被废弃,未来版本将不再支持该客户端。
1. 添加依赖
在pom.xml文件中添加以下依赖:
<!-- OpenSearch Java high-level REST client核心库 -->
<dependency>
<groupId>org.opensearch.client</groupId>
<artifactId>opensearch-rest-high-level-client</artifactId>
<version>2.19.0</version>
</dependency>2. 配置安全连接
在使用REST客户端之前,需配置应用程序的信任库(truststore),以连接到安全插件(Security plugin)。
如果您使用的是由受信任的证书颁发机构(CA)签发的证书,则无需额外配置。
如果您使用的是自签名证书(例如在测试或演示环境中),则可以使用以下命令创建一个自定义信任库,并将根CA证书加入其中。
创建信任库并导入证书:
使用Java的keytool工具,将根CA证书导入到一个新的信任库文件(例如truststore.jks)中。keytool -importcert -file <path/to/your/root-ca.pem> -alias <certificate_alias> -keystore <path/to/your/truststore.jks>执行此命令时,系统会提示您为新的信任库设置密码。
在应用程序中指定信任库:
在您的Java应用程序启动时,通过设置系统属性,告知JVM使用您刚刚创建的信任库。// 在客户端初始化代码之前执行 System.setProperty("javax.net.ssl.trustStore", "/full_path/to/your/truststore.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "password-for-truststore");
如果您在配置安全功能时遇到问题,可以参考OpenSearch官方的常见问题和TLS 故障排查文档。
3. 初始化客户端
在实际使用中,您可以根据以下代码配置将PolarSearch的相关信息设置为环境变量,或直接将其赋值为参数的默认值,以便于测试使用。
// 仅用于演示目的,请勿在生产代码中硬编码凭证。
// 设置用于基本认证的凭证
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("<polarsearch_username>", "<polarsearch_password>"));
// 构建 RestClient,并设置 HTTP 客户端配置回调以应用凭证
RestClientBuilder builder = RestClient.builder(new HttpHost("<polarsearch_host>", <polarsearch_port>, "https"))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
// 创建 RestHighLevelClient 实例
RestHighLevelClient client = new RestHighLevelClient(builder);4. 执行基本操作
以下代码片段展示了如何执行常见的索引和文档操作。
创建索引
// 创建一个带有自定义设置和映射的索引
CreateIndexRequest createIndexRequest = new CreateIndexRequest("custom-index");
createIndexRequest.settings(Settings.builder()
.put("index.number_of_shards", 4)
.put("index.number_of_replicas", 3)
);
HashMap<String, String> typeMapping = new HashMap<String,String>();
typeMapping.put("type", "integer");
HashMap<String, Object> ageMapping = new HashMap<String, Object>();
ageMapping.put("age", typeMapping);
HashMap<String, Object> mapping = new HashMap<String, Object>();
mapping.put("properties", ageMapping);
createIndexRequest.mapping(mapping);
CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);写入文档
// 向索引中添加数据
IndexRequest request = new IndexRequest("custom-index");
request.id("1");
HashMap<String, String> stringMapping = new HashMap<String, String>();
stringMapping.put("message:", "Testing Java REST client");
request.source(stringMapping);
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);搜索文档
GetRequest getRequest = new GetRequest("custom-index", "1");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println("Retrieved document: " + getResponse.getSourceAsString());删除文档
DeleteRequest deleteDocumentRequest = new DeleteRequest("custom-index", "1");
DeleteResponse deleteResponse = client.delete(deleteDocumentRequest, RequestOptions.DEFAULT);
System.out.println("Document deleted with result: " + deleteResponse.getResult());删除索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("custom-index");
AcknowledgedResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println("Index deletion acknowledged: " + deleteIndexResponse.isAcknowledged());Low-level Python client
建议您使用Low-level Python client,因为High-level Python client在OpenSearch 2.1.0版本后已被废弃。
1.配置环境
根据实际业务需求,进入指定的项目目录。此处以
/home/PolarSearchTestPython为例。mkdir /home/PolarSearchTestPython cd /home/PolarSearchTestPython在
/home/PolarSearchTestPython目录中,创建虚拟环境(venv)隔离项目依赖,避免全局污染。python3 -m venv myenv激活虚拟环境
source myenv/bin/activate安装所需的Python依赖库。
pip3 install opensearch-py
2. 连接PolarSearch
在您的Python代码中导入OpenSearch类,并使用PolarSearch的连接信息创建客户端实例。在实际使用中,您可以根据以下代码配置将PolarSearch的相关信息设置为环境变量,或直接将其赋值为参数的默认值,以便于测试使用。
from opensearchpy import OpenSearch
host = os.getenv("HOST", default="<polarsearch_host>")
port = int(os.getenv("PORT", <polarsearch_port>))
auth = (os.getenv("USERNAME", "<polarsearch_username>"), os.getenv("PASSWORD", "<polarsearch_password>"))
client = OpenSearch(
hosts=[{"host": host, "port": port}],
http_auth=auth,
use_ssl=False,
verify_certs=False,
ssl_show_warn=False,
)3. 操作示例
以下代码片段展示了如何执行常见的索引和文档操作。
创建索引
使用client.indices.create()方法创建一个新索引。
index_name = 'python-test-index'
index_body = {
'settings': {
'index': {
'number_of_shards': 4
}
}
}
response = client.indices.create(index=index_name, body=index_body)写入文档
使用client.index()方法向指定索引中添加一个文档。
document = {
'title': 'Moneyball',
'director': 'Bennett Miller',
'year': '2011'
}
response = client.index(
index = 'python-test-index',
body = document,
id = '1',
refresh = True
)执行批量操作
使用client.bulk()方法可以一次性执行多个操作,操作之间用\n分隔。
movies = '{ "index" : { "_index" : "my-dsl-index", "_id" : "2" } } \n { "title" : "Interstellar", "director" : "Christopher Nolan", "year" : "2014"} \n { "create" : { "_index" : "my-dsl-index", "_id" : "3" } } \n { "title" : "Star Trek Beyond", "director" : "Justin Lin", "year" : "2015"} \n { "update" : {"_id" : "3", "_index" : "my-dsl-index" } } \n { "doc" : {"year" : "2016"} }'
client.bulk(body=movies)搜索文档
使用client.search()方法根据查询条件搜索文档。
q = 'miller'
query = {
'size': 5,
'query': {
'multi_match': {
'query': q,
'fields': ['title^2', 'director']
}
}
}
response = client.search(
body = query,
index = 'python-test-index'
)删除文档
使用client.delete()方法删除指定ID的文档。
response = client.delete(
index = 'python-test-index',
id = '1'
)删除索引
使用client.indices.delete()方法删除整个索引。
response = client.indices.delete(
index = 'python-test-index'
)完整示例代码
下面是一个完整的示例,演示了从创建索引到最终删除索引的全过程。
Java client
示例代码
运行方式
mvn clean package
mvn exec:java -Dexec.mainClass=samples.OpenSearchClientExampleJava high-level REST client
示例代码
Low-level Python client
依赖配置
pip3 install opensearch-py示例程序
import os
from opensearchpy import OpenSearch
host = os.getenv("HOST", default="<polarsearch_host>")
port = int(os.getenv("PORT", <polarsearch_port>))
auth = (os.getenv("USERNAME", "<polarsearch_username>"), os.getenv("PASSWORD", "<polarsearch_password>"))
client = OpenSearch(
hosts=[{"host": host, "port": port}],
http_auth=auth,
use_ssl=False,
verify_certs=False,
ssl_show_warn=False,
)
# Create an index with non-default settings.
index_name = 'python-test-index'
index_body = {
'settings': {
'index': {
'number_of_shards': 4
}
}
}
response = client.indices.create(index=index_name, body=index_body)
print('\nCreating index:')
print(response)
# Add a document to the index.
document = {
'title': 'Moneyball',
'director': 'Bennett Miller',
'year': '2011'
}
id = '1'
response = client.index(
index = index_name,
body = document,
id = id,
refresh = True
)
print('\nAdding document:')
print(response)
# Perform bulk operations
movies = '{ "index" : { "_index" : "my-dsl-index", "_id" : "2" } } \n { "title" : "Interstellar", "director" : "Christopher Nolan", "year" : "2014"} \n { "create" : { "_index" : "my-dsl-index", "_id" : "3" } } \n { "title" : "Star Trek Beyond", "director" : "Justin Lin", "year" : "2015"} \n { "update" : {"_id" : "3", "_index" : "my-dsl-index" } } \n { "doc" : {"year" : "2016"} }'
client.bulk(body=movies)
# Search for the document.
q = 'miller'
query = {
'size': 5,
'query': {
'multi_match': {
'query': q,
'fields': ['title^2', 'director']
}
}
}
response = client.search(
body = query,
index = index_name
)
print('\nSearch results:')
print(response)
# Delete the document.
response = client.delete(
index = index_name,
id = id
)
print('\nDeleting document:')
print(response)
# Delete the index.
response = client.indices.delete(
index = index_name
)
print('\nDeleting index:')
print(response)