본문 바로가기
WIKI 기술 지식 베이스

Java client

원문 보기 위키 갱신

출처: 문서

본문

Java 클라이언트

OpenSearch Java 클라이언트를 사용하면 HTTP 메서드와 원시 JSON 대신 Java 메서드와 데이터 구조를 통해 OpenSearch 클러스터와 상호 작용할 수 있어요. 예를 들어, 객체를 사용하여 클러스터에 요청을 보내 인덱스를 생성하거나, 문서에 데이터를 추가하거나, 클라이언트의 내장 메서드를 사용하여 다른 작업을 수행할 수 있어요. 클라이언트의 전체 API 문서와 추가 예제는 javadoc을 참조하세요.

이 시작 가이드에서는 OpenSearch에 연결하고, 문서를 인덱싱하고, 쿼리를 실행하는 방법을 설명해요. 클라이언트 소스 코드는 opensearch-java 저장소를 참조하세요.

Java 클라이언트 설치하기

Java 클라이언트는 클러스터와 통신하기 위해 전송(transport)이 필요해요. ApacheHttpClient5Transport가 기본 전송이며 새 애플리케이션에 권장되는 선택이에요. RestClient 전송은 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정이에요.

Apache HttpClient 5 Transport를 사용하여 클라이언트 설치하기

OpenSearch Java 클라이언트를 사용하려면 전송을 제공해야 해요. 기본 ApacheHttpClient5TransportBuilder 전송은 Java 클라이언트와 함께 제공돼요. 기본 전송을 사용하여 OpenSearch Java 클라이언트를 사용하려면 pom.xml 파일에 종속성으로 추가하세요:

<dependency>
  <groupId>org.opensearch.client</groupId>
  <artifactId>opensearch-java</artifactId>
  <version>3.10.0</version>
</dependency>

{% include copy.html %}

Gradle을 사용하는 경우 프로젝트에 다음 종속성을 추가하세요:

dependencies {
  implementation 'org.opensearch.client:opensearch-java:3.10.0'
}

{% include copy.html %}

이제 OpenSearch 클러스터를 시작할 수 있어요.

RestClient Transport를 사용하여 클라이언트 설치하기 (더 이상 사용되지 않음)

RestClientTransport 전송과 그것이 래핑하는 org.opensearch.client.RestClient 클래스는 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정이에요. 대신 Apache HttpClient 5 Transport를 사용하세요. {: .warning}

또는 RestClient 기반 전송을 사용하여 Java 클라이언트를 생성할 수 있어요. 이 경우 프로젝트의 pom.xml 파일에 다음 종속성이 있는지 확인하세요:

<dependency>
  <groupId>org.opensearch.client</groupId>
  <artifactId>opensearch-rest-client</artifactId>
  <version>{{site.opensearch_version}}</version>
</dependency>

<dependency>
  <groupId>org.opensearch.client</groupId>
  <artifactId>opensearch-java</artifactId>
  <version>3.10.0</version>
</dependency>

{% include copy.html %}

Gradle을 사용하는 경우 프로젝트에 다음 종속성을 추가하세요:

dependencies {
  implementation 'org.opensearch.client:opensearch-rest-client:{{site.opensearch_version}}'
  implementation 'org.opensearch.client:opensearch-java:3.10.0'
}

{% include copy.html %}

이제 OpenSearch 클러스터를 시작할 수 있어요.

샘플 데이터

다음 섹션의 샘플 프로그램은 문서를 나타내기 위해 Student 클래스를 사용해요. 부분 업데이트가 올바르게 직렬화되도록 gpa를 박스형 Double로 선언하는 다음 래퍼 클래스를 사용하세요:

public class Student {
  private String firstName;
  private String lastName;
  private Double gpa;
  private String gradDate;

  public Student() {}

  public Student(String firstName, String lastName, double gpa, String gradDate) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.gpa = gpa;
    this.gradDate = gradDate;
  }

  public String getFirstName() { return firstName; }
  public void setFirstName(String firstName) { this.firstName = firstName; }
  public String getLastName() { return lastName; }
  public void setLastName(String lastName) { this.lastName = lastName; }
  public Double getGpa() { return gpa; }
  public void setGpa(Double gpa) { this.gpa = gpa; }
  public String getGradDate() { return gradDate; }
  public void setGradDate(String gradDate) { this.gradDate = gradDate; }

  @Override
  public String toString() {
    return String.format("Student{firstName='%s', lastName='%s', gpa=%s, gradDate=%s}",
      firstName, lastName, gpa, gradDate);
  }
}

{% include copy.html %}

OpenSearch에 연결하기

다음 예제는 Apache HttpClient 5 전송 또는 더 이상 사용되지 않는 RestClient 전송을 사용하여 보안 플러그인이 활성화된 클러스터에 연결해요.

Apache HttpClient 5 Transport 사용하기

이 코드 예제는 admin 사용자를 사용해요. <custom-admin-password>를 OpenSearch를 설치할 때 설정한 관리자 비밀번호로 바꾸세요.

다음 샘플 코드는 SSL과 TLS를 활성화하여 클라이언트를 초기화해요:

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;

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.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.core5.function.Factory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.OpenSearchTransport;
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;

public class OpenSearchClientExample {
  public static void main(String[] args) throws Exception {
    final HttpHost host = new HttpHost("https", "localhost", 9200);
    final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    // Only for demo purposes. Don't specify your credentials in code.
    credentialsProvider.setCredentials(new AuthScope(host), new UsernamePasswordCredentials("admin", "<custom-admin-password>".toCharArray()));

    // Trusts all certificates, including self-signed certificates. For testing only. Don't use in production.
    final SSLContext sslcontext = SSLContextBuilder
      .create()
      .loadTrustMaterial(null, (chains, authType) -> true)
      .build();

    final ApacheHttpClient5TransportBuilder builder = ApacheHttpClient5TransportBuilder.builder(host);
    builder.setHttpClientConfigCallback(httpClientBuilder -> {
      final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
        .setSslContext(sslcontext)
        // See https://issues.apache.org/jira/browse/HTTPCLIENT-2219
        .setTlsDetailsFactory(new Factory<SSLEngine, TlsDetails>() {
          @Override
          public TlsDetails create(final SSLEngine sslEngine) {
            return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol());
          }
        })
        .build();

      final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder
        .create()
        .setTlsStrategy(tlsStrategy)
        .build();

      return httpClientBuilder
        .setDefaultCredentialsProvider(credentialsProvider)
        .setConnectionManager(connectionManager);
    });

    final OpenSearchTransport transport = builder.build();
    OpenSearchClient client = new OpenSearchClient(transport);
  }
}

{% include copy.html %}

보안 구성 시 문제가 발생하면 TLS 문제 해결을 참조하세요.

RestClient Transport 사용하기 (더 이상 사용되지 않음)

RestClientTransport 전송과 그것이 래핑하는 org.opensearch.client.RestClient 클래스는 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정이에요. 대신 Apache HttpClient 5 Transport를 사용하세요. {: .warning}

이 코드 예제는 admin 사용자를 사용해요. <custom-admin-password>를 OpenSearch를 설치할 때 설정한 관리자 비밀번호로 바꾸세요.

RestClient 전송은 Java truststore를 사용하여 클러스터의 인증서를 검증해요. 자체 서명된 인증서나 데모 인증서를 사용하는 경우 다음 명령을 사용하여 루트 인증 기관(CA) 인증서가 포함된 truststore를 생성하세요. 메시지가 표시되면 truststore의 비밀번호를 입력하세요:

keytool -importcert -file <path-to-root-ca-cert> -alias <alias> -keystore <truststore-name>

{% include copy.html %}

신뢰할 수 있는 CA의 인증서를 사용하는 경우 truststore를 구성할 필요가 없어요.

다음 코드에서 /full/path/to/keystore를 truststore 경로로, password-to-keystore를 truststore 비밀번호로 바꾸세요. 다음 샘플 코드는 SSL과 TLS를 활성화하여 클라이언트를 초기화해요:

import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.opensearch.client.RestClient;
import org.opensearch.client.RestClientBuilder;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.OpenSearchTransport;
import org.opensearch.client.transport.rest_client.RestClientTransport;

public class OpenSearchClientExample {
  public static void main(String[] args) throws Exception {
    System.setProperty("javax.net.ssl.trustStore", "/full/path/to/keystore");
    System.setProperty("javax.net.ssl.trustStorePassword", "password-to-keystore");

    final HttpHost host = new HttpHost("https", "localhost", 9200);
    final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    //Only for demo purposes. Don't specify your credentials in code.
    credentialsProvider.setCredentials(new AuthScope(host), new UsernamePasswordCredentials("admin", "<custom-admin-password>".toCharArray()));

    //Initialize the client with SSL and TLS enabled
    final RestClient restClient = RestClient.builder(host).
      setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
        }
      }).build();

    final OpenSearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
    final OpenSearchClient client = new OpenSearchClient(transport);
  }
}

{% include copy.html %}

Amazon OpenSearch Service에 연결하기

Amazon OpenSearch Service 또는 Amazon OpenSearch Serverless에 연결하려면 AWS SDK for Java 2.x를 사용하여 요청에 서명하는 AwsSdk2Transport를 사용하세요. opensearch-java 외에도 AWS SDK HTTP 클라이언트 및 인증 모듈을 pom.xml 파일에 추가하세요:

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>aws-crt-client</artifactId>
  <version>2.55.9</version>
</dependency>

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>auth</artifactId>
  <version>2.55.9</version>
</dependency>

{% include copy.html %}

Gradle을 사용하는 경우 프로젝트에 다음 종속성을 추가하세요:

dependencies {
  implementation 'software.amazon.awssdk:aws-crt-client:2.55.9'
  implementation 'software.amazon.awssdk:auth:2.55.9'
}

{% include copy.html %}

예제에서는 AwsCrtHttpClient를 사용해요. AWS SDK의 ApacheHttpClient는 GET 또는 DELETE 요청에서 요청 본문을 지원하지 않으므로 AwsSdk2Transport가 clearScroll() 및 deletePit()와 같은 작업에 대해 TransportException을 발생시키기 때문에 사용하지 마세요. {: .note}

다음 예제에서 엔드포인트를 Amazon OpenSearch Service 콘솔의 도메인 세부 정보 페이지에 나열된 도메인 엔드포인트로 바꾸세요.

AwsSdk2Transport는 AWS SDK 기본 자격 증명 공급자 체인에서 AWS 자격 증명을 가져와요. 다음 예제는 Amazon OpenSearch Service에 연결하는 방법을 보여줘요:

import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.opensearch.core.InfoResponse;
import org.opensearch.client.transport.aws.AwsSdk2Transport;
import org.opensearch.client.transport.aws.AwsSdk2TransportOptions;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtHttpClient;
import software.amazon.awssdk.regions.Region;

SdkHttpClient httpClient = AwsCrtHttpClient.builder().build();

OpenSearchClient client = new OpenSearchClient(
    new AwsSdk2Transport(
        httpClient,
        "search-<domain-name>-<id>.us-east-1.es.amazonaws.com", // OpenSearch endpoint, without https://
        "es",
        Region.US_EAST_1, // signing service region
        AwsSdk2TransportOptions.builder().build()
    )
);

InfoResponse info = client.info();
System.out.println(info.version().distribution() + ": " + info.version().number());

httpClient.close();

{% include copy.html %}

Amazon OpenSearch Serverless에 연결하기

다음 예제에서 엔드포인트를 Amazon OpenSearch Service 콘솔의 컬렉션 세부 정보 페이지에 나열된 컬렉션 엔드포인트로 바꾸세요.

다음 예제는 Amazon OpenSearch Serverless에 연결하는 방법을 보여줘요. Amazon OpenSearch Serverless는 루트 엔드포인트를 지원하지 않으므로 예제에서는 인덱스가 존재하는지 확인해요:

import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.aws.AwsSdk2Transport;
import org.opensearch.client.transport.aws.AwsSdk2TransportOptions;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.crt.AwsCrtHttpClient;
import software.amazon.awssdk.regions.Region;

SdkHttpClient httpClient = AwsCrtHttpClient.builder().build();

OpenSearchClient client = new OpenSearchClient(
    new AwsSdk2Transport(
        httpClient,
        "<collection-id>.us-east-1.aoss.amazonaws.com", // OpenSearch Serverless collection endpoint, without https://
        "aoss",
        Region.US_EAST_1, // signing service region
        AwsSdk2TransportOptions.builder().build()
    )
);

boolean exists = client.indices().exists(e -> e.index("students")).value();
System.out.println("Index exists: " + exists);

httpClient.close();

{% include copy.html %}

Amazon OpenSearch Serverless는 OpenSearch API 작업의 하위 집합을 지원하며 이 페이지의 예제에서 사용된 refresh 매개변수를 지원하지 않아요. 자세한 내용은 Amazon OpenSearch Serverless의 지원되는 작업 및 플러그인을 참조하세요. {: .note}

인덱스 생성하기

다음 예제는 기본 샤드 1개와 복제본 1개로 인덱스를 생성해요. gradDate 필드를 yyyy-MM-dd 형식의 date로 명시적으로 매핑해요. OpenSearch는 문서를 인덱싱할 때 다른 문서 필드를 동적으로 매핑해요:

String index = "students";
CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
  .index(index)
  .settings(s -> s
    .numberOfShards(1)
    .numberOfReplicas(1))
  .mappings(m -> m
    .properties("gradDate", p -> p.date(d -> d.format("yyyy-MM-dd"))))
  .build();
client.indices().create(createIndexRequest);

{% include copy.html %}

문서 인덱싱하기

다음 코드를 사용하여 문서를 인덱싱하세요:

Student student = new Student("John", "Doe", 3.89, "2022-05-15");
IndexRequest<Student> indexRequest = new IndexRequest.Builder<Student>()
  .index(index).id("1").document(student).refresh(Refresh.True).build();
IndexResponse indexResponse = client.index(indexRequest);

{% include copy.html %}

벌크 인덱싱

다음 코드를 사용하여 단일 요청으로 여러 문서를 인덱싱하세요:

List<BulkOperation> operations = new ArrayList<>();
operations.add(new BulkOperation.Builder().index(
  new IndexOperation.Builder<Student>()
    .index(index).id("2")
    .document(new Student("Paulo", "Santos", 3.93, "2021-05-20")).build()
).build());
operations.add(new BulkOperation.Builder().index(
  new IndexOperation.Builder<Student>()
    .index(index).id("3")
    .document(new Student("Shirley", "Rodriguez", 3.91, "2019-05-10")).build()
).build());
BulkRequest bulkRequest = new BulkRequest.Builder()
  .index(index).operations(operations).refresh(Refresh.True).build();
BulkResponse bulkResponse = client.bulk(bulkRequest);

{% include copy.html %}

문서 검색하기

다음 코드를 사용하여 인덱스의 모든 문서를 검색하세요:

SearchResponse<Student> searchResponse = client.search(s -> s.index(index), Student.class);
for (int i = 0; i < searchResponse.hits().hits().size(); i++) {
  System.out.println(searchResponse.hits().hits().get(i).source());
}

{% include copy.html %}

searchResponse.hits().hits()의 각 히트는 Hit<Student> 객체이며, hit.id()에 문서 ID가 포함되고 hit.source()에 Student 객체가 포함되며, 그 필드는 getter를 통해 사용할 수 있어요. Hit 클래스를 사용하려면 org.opensearch.client.opensearch.core.search.Hit을 임포트하세요:

for (Hit<Student> hit : searchResponse.hits().hits()) {
  Student student = hit.source();
  System.out.println("ID: " + hit.id() + ", name: " + student.getFirstName() + " " + student.getLastName()
      + ", GPA: " + student.getGpa() + ", graduation date: " + student.getGradDate());
}

{% include copy.html %}

범위 쿼리를 사용하여 검색해요. gte 및 lte 경계는 JsonData 값을 사용하므로 org.opensearch.client.json.JsonData를 임포트하세요:

SearchResponse<Student> searchResponse = client.search(s -> s
  .index(index)
  .query(q -> q.range(r -> r
    .field("gradDate")
    .gte(JsonData.of("2019-01-01"))
    .lte(JsonData.of("2019-12-31")))),
  Student.class);

{% include copy.html %}

결과 페이지 매기기

결과를 페이지로 나누려면 from 및 size 매개변수를 사용하세요. 다음 예제는 학생을 졸업 날짜별로 정렬하고 결과를 한 번에 두 개씩 검색해요. 첫 번째 요청은 첫 번째 페이지 결과를 반환하고, 두 번째 요청은 다음 페이지를 반환해요. SortOrder 열거형을 사용하려면 org.opensearch.client.opensearch._types.SortOrder를 임포트하세요:

SearchResponse<Student> firstPageResponse = client.search(s -> s
  .index(index)
  .from(0)
  .size(2)
  .sort(so -> so.field(f -> f.field("gradDate").order(SortOrder.Asc))),
  Student.class);
for (int i = 0; i < firstPageResponse.hits().hits().size(); i++) {
  System.out.println(firstPageResponse.hits().hits().get(i).source());
}

SearchResponse<Student> nextPageResponse = client.search(s -> s
  .index(index)
  .from(2)
  .size(2)
  .sort(so -> so.field(f -> f.field("gradDate").order(SortOrder.Asc))),
  Student.class);
for (int i = 0; i < nextPageResponse.hits().hits().size(); i++) {
  System.out.println(nextPageResponse.hits().hits().get(i).source());
}

{% include copy.html %}

from 및 size 매개변수는 처음 몇 페이지의 결과에 잘 작동해요. 많은 수의 결과를 페이지로 나누려면 search_after와 함께 포인트 인 타임을 사용하세요. 자세한 내용은 결과 페이지 매기기를 참조하세요.

문서 업데이트하기

부분 문서 객체를 사용하여 문서를 업데이트해요. null로 설정된 필드는 전송되지 않으므로 지정된 필드만 업데이트돼요:

Student updatedFields = new Student();
updatedFields.setGpa(3.92);
UpdateRequest<Student, Student> updateRequest = new UpdateRequest.Builder<Student, Student>()
  .index(index).id("1").doc(updatedFields).build();
UpdateResponse<Student> updateResponse = client.update(updateRequest, Student.class);

{% include copy.html %}

문서 삭제하기

다음 코드를 사용하여 문서를 삭제하세요:

client.delete(b -> b.index(index).id("3").refresh(Refresh.True));

{% include copy.html %}

인덱스 삭제하기

다음 코드를 사용하여 인덱스를 삭제하세요:

DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(index).build();
DeleteIndexResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest);

{% include copy.html %}

샘플 프로그램

이 샘플 프로그램은 앞 섹션의 코드를 결합해요. 보안 플러그인이 활성화된 클러스터에 연결해요. 보안 플러그인이 없는 클러스터에 연결하려면 // Without security 주석으로 표시된 줄을 변경하세요. 샘플 프로그램을 실행하기 전에 프로젝트에 Student 클래스가 정의되어 있는지 확인하세요. 클러스터 구성에 맞게 자격 증명을 변경해야 해요.

이 샘플 프로그램은 테스트 전용이에요. 코드에 자격 증명을 지정하고 인증서 검증을 비활성화하여 자체 서명된 인증서를 사용하는 클러스터에 연결할 수 있도록 해요. 프로덕션에서는 안전한 위치에서 자격 증명을 로드하고 클러스터의 인증서를 검증하세요. {: .warning}

다음 샘플 프로그램은 클라이언트를 생성하고, 인덱스를 생성하고, 문서를 개별적으로 및 벌크로 인덱싱하고, 문서를 검색하고, 문서를 업데이트하고, 문서를 삭제한 다음 인덱스를 삭제해요:

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;

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.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.core5.function.Factory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.opensearch.client.json.JsonData;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.opensearch._types.Refresh;
import org.opensearch.client.opensearch._types.SortOrder;
import org.opensearch.client.opensearch.core.IndexRequest;
import org.opensearch.client.opensearch.core.IndexResponse;
import org.opensearch.client.opensearch.core.SearchResponse;
import org.opensearch.client.opensearch.core.UpdateRequest;
import org.opensearch.client.opensearch.core.UpdateResponse;
import org.opensearch.client.opensearch.core.GetResponse;
import org.opensearch.client.opensearch.core.BulkRequest;
import org.opensearch.client.opensearch.core.BulkResponse;
import org.opensearch.client.opensearch.core.DeleteResponse;
import org.opensearch.client.opensearch.core.bulk.BulkOperation;
import org.opensearch.client.opensearch.core.bulk.IndexOperation;
import org.opensearch.client.opensearch.indices.*;
import org.opensearch.client.transport.OpenSearchTransport;
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class OpenSearchClientExample {
  public static void main(String[] args) throws Exception {
    final HttpHost host = new HttpHost("https", "localhost", 9200); // Without security, use new HttpHost("http", "localhost", 9200)
    final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); // Without security, remove this line
    // Without security, remove this line
    credentialsProvider.setCredentials(new AuthScope(host), new UsernamePasswordCredentials("admin", "<custom-admin-password>".toCharArray()));

    final SSLContext sslcontext = SSLContextBuilder.create()
      .loadTrustMaterial(null, (chains, authType) -> true)
      .build();

    final ApacheHttpClient5TransportBuilder builder = ApacheHttpClient5TransportBuilder.builder(host);
    builder.setHttpClientConfigCallback(httpClientBuilder -> {
      final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
        .setSslContext(sslcontext)
        .setTlsDetailsFactory(new Factory<SSLEngine, TlsDetails>() {
          @Override
          public TlsDetails create(final SSLEngine sslEngine) {
            return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol());
          }
        })
        .build();

      final PoolingAsyncClientConnectionManager connectionManager =
        PoolingAsyncClientConnectionManagerBuilder.create()
          .setTlsStrategy(tlsStrategy)
          .build();

      return httpClientBuilder
        .setDefaultCredentialsProvider(credentialsProvider) // Without security, remove this line
        .setConnectionManager(connectionManager);
    });

    final OpenSearchTransport transport = builder.build();
    final OpenSearchClient client = new OpenSearchClient(transport);

    try {
      // Create the index
      String index = "students";
      System.out.println("Creating index......");
      CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
        .index(index)
        .settings(s -> s
          .numberOfShards(1)
          .numberOfReplicas(1))
        .mappings(m -> m
          .properties("gradDate", p -> p.date(d -> d.format("yyyy-MM-dd"))))
        .build();
      CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest);
      System.out.println("Index created: " + createIndexResponse.index());

      // Index a document
      System.out.println("\nIndexing one student......");
      Student student = new Student("John", "Doe", 3.89, "2022-05-15");
      IndexRequest<Student> indexRequest = new IndexRequest.Builder<Student>()
        .index(index).id("1").document(student).refresh(Refresh.True).build();
      IndexResponse indexResponse = client.index(indexRequest);
      System.out.println("Result: " + indexResponse.result().jsonValue() + ", id: " + indexResponse.id() + ", version: " + indexResponse.version());

      // Bulk index documents
      System.out.println("\nIndexing many students......");
      List<BulkOperation> operations = new ArrayList<>();
      operations.add(new BulkOperation.Builder().index(
        new IndexOperation.Builder<Student>()
          .index(index).id("2")
          .document(new Student("Paulo", "Santos", 3.93, "2021-05-20")).build()
      ).build());
      operations.add(new BulkOperation.Builder().index(
        new IndexOperation.Builder<Student>()
          .index(index).id("3")
          .document(new Student("Shirley", "Rodriguez", 3.91, "2019-05-10")).build()
      ).build());
      BulkRequest bulkRequest = new BulkRequest.Builder()
        .index(index).operations(operations).refresh(Refresh.True).build();
      BulkResponse bulkResponse = client.bulk(bulkRequest);
      System.out.println("Errors: " + bulkResponse.errors());
      bulkResponse.items().forEach(item ->
        System.out.println("  " + item.result() + " id: " + item.id()));

      // Search for all students
      System.out.println("\nSearching for all students......");
      SearchResponse<Student> searchResponse = client.search(s -> s
        .index(index)
        .from(0)
        .size(2)
        .sort(so -> so.field(f -> f.field("gradDate").order(SortOrder.Asc))),
        Student.class);
      System.out.println("Total hits: " + searchResponse.hits().total().value());
      System.out.println("Page 1:");
      for (int i = 0; i < searchResponse.hits().hits().size(); i++) {
        System.out.println("  " + searchResponse.hits().hits().get(i).source());
      }
      SearchResponse<Student> nextPageResponse = client.search(s -> s
        .index(index)
        .from(2)
        .size(2)
        .sort(so -> so.field(f -> f.field("gradDate").order(SortOrder.Asc))),
        Student.class);
      System.out.println("Page 2:");
      for (int i = 0; i < nextPageResponse.hits().hits().size(); i++) {
        System.out.println("  " + nextPageResponse.hits().hits().get(i).source());
      }

      // Search for students who graduated in 2019
      System.out.println("\nSearching for students who graduated in 2019......");
      SearchResponse<Student> searchResponse2 = client.search(s -> s
        .index(index)
        .query(q -> q.range(r -> r
          .field("gradDate")
          .gte(JsonData.of("2019-01-01"))
          .lte(JsonData.of("2019-12-31")))),
        Student.class);
      System.out.println("Total hits: " + searchResponse2.hits().total().value());
      for (int i = 0; i < searchResponse2.hits().hits().size(); i++) {
        System.out.println("  " + searchResponse2.hits().hits().get(i).source());
      }

      // Update a document
      System.out.println("\nUpdating a student's GPA......");
      Student updatedFields = new Student();
      updatedFields.setGpa(3.92);
      UpdateRequest<Student, Student> updateRequest = new UpdateRequest.Builder<Student, Student>()
        .index(index).id("1").doc(updatedFields).build();
      UpdateResponse<Student> updateResponse = client.update(updateRequest, Student.class);
      System.out.println("Result: " + updateResponse.result().jsonValue() + ", version: " + updateResponse.version());

      // Get the updated document
      GetResponse<Student> getResponse = client.get(g -> g.index(index).id("1"), Student.class);
      System.out.println("Updated document: " + getResponse.source());

      // Delete a document
      System.out.println("\nDeleting a student......");
      DeleteResponse deleteResponse = client.delete(b -> b.index(index).id("3").refresh(Refresh.True));
      System.out.println("Result: " + deleteResponse.result().jsonValue());

      // Delete the index
      System.out.println("\nDeleting the index......");
      DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(index).build();
      DeleteIndexResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest);
      System.out.println("Acknowledged: " + deleteIndexResponse.acknowledged());

    } finally {
      transport.close();
    }
  }
}

{% include copy.html %}

프로그램은 다음 출력을 생성해요:

Creating index......
Index created: students

Indexing one student......
Result: created, id: 1, version: 1

Indexing many students......
Errors: false
  created id: 2
  created id: 3

Searching for all students......
Total hits: 3
Page 1:
  Student{firstName='Shirley', lastName='Rodriguez', gpa=3.91, gradDate=2019-05-10}
  Student{firstName='Paulo', lastName='Santos', gpa=3.93, gradDate=2021-05-20}
Page 2:
  Student{firstName='John', lastName='Doe', gpa=3.89, gradDate=2022-05-15}

Searching for students who graduated in 2019......
Total hits: 1
  Student{firstName='Shirley', lastName='Rodriguez', gpa=3.91, gradDate=2019-05-10}

Updating a student's GPA......
Result: updated, version: 2
Updated document: Student{firstName='John', lastName='Doe', gpa=3.92, gradDate=2022-05-15}

Deleting a student......
Result: deleted

Deleting the index......
Acknowledged: true

관련 문서

더 알아보기 (Learn more)