Skip to content

Commit

Permalink
Merge branch 'main' into issue-354
Browse files Browse the repository at this point in the history
  • Loading branch information
dblock authored Feb 28, 2023
2 parents 421a854 + 75c5e59 commit b3ee1e1
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ jobs:
- { opensearch_version: 2.1.0, java: 11 }
- { opensearch_version: 2.2.1, java: 11 }
- { opensearch_version: 2.3.0, java: 11 }
- { opensearch_version: 2.4.1, java: 11 }
- { opensearch_version: 2.5.0, java: 11 }
steps:
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v1
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Update Gradle to 7.6 ([#309](https://github.com/opensearch-project/opensearch-java/pull/309))
- Prevent SPI calls at runtime ([#293](https://github.com/opensearch-project/opensearch-java/pull/293))
- Add support for OpenSearch Serverless ([#339](https://github.com/opensearch-project/opensearch-java/pull/339))
- Fix issue where completion suggestions were failing, due to being parsed as term suggestions ([#347](https://github.com/opensearch-project/opensearch-java/pull/347))
- Fix issue when trackTotalHits is disabled ([#372](https://github.com/opensearch-project/opensearch-java/pull/372))
- Fix completion suggestions failure with missing required property TermSuggestOption.score ([#347](https://github.com/opensearch-project/opensearch-java/pull/347))
- Fix search failure with missing required property HitsMetadata.total when trackTotalHits is disabled ([#372](https://github.com/opensearch-project/opensearch-java/pull/372))

### Deprecated

Expand All @@ -48,6 +48,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Do not double-wrap OpenSearchException on error ([#323](https://github.com/opensearch-project/opensearch-java/pull/323))
- Fix AwsSdk2TransportOptions.responseCompression ([#322](https://github.com/opensearch-project/opensearch-java/pull/322))
- Bulk UpdateOperation misses upsert options ([#353](https://github.com/opensearch-project/opensearch-java/pull/353))
- Fix missing key property in the RangeBucket ([#370](https://github.com/opensearch-project/opensearch-java/pull/370))

### Security

Expand Down
9 changes: 5 additions & 4 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
The below matrix shows the compatibility of the [`opensearch-java-client`](https://search.maven.org/artifact/org.opensearch.client/opensearch-java) with versions of [`OpenSearch`](https://opensearch.org/downloads.html#opensearch).

| Client Version | OpenSearch Version |
| --- | --- |
| 1.0.0 | 1.0.0-1.3.3 |
| 2.0.0 | 1.3.3-2.0.1 |
| 2.1.0 | 1.3.3-2.3.0 |
|----------------|--------------------|
| 1.0.0 | 1.0.0-1.3.3 |
| 2.0.0 | 1.3.3-2.0.1 |
| 2.1.0 | 1.3.3-2.3.0 |
| 2.2.0 | 1.3.3-2.5.0 |

## Upgrading

Expand Down
25 changes: 25 additions & 0 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- [Index data](#index-data)
- [Search for the documents](#search-for-the-documents)
- [Search documents using a match query](#search-documents-using-a-match-query)
- [Bulk requests](#bulk-requests)
- [Aggregations](#aggregations)
- [Delete the document](#delete-the-document)
- [Delete the index](#delete-the-index)
Expand Down Expand Up @@ -142,6 +143,30 @@ for (int i = 0; i < searchResponse.hits().hits().size(); i++) {
}
```

## Bulk requests

```java
ArrayList<BulkOperation> ops = new ArrayList<>();
SimplePojo doc1 = new SimplePojo("Document 1", "The text of document 1");
ops.add(new BulkOperation.Builder().index(
IndexOperation.of(io -> io.index(TEST_INDEX).id("id1").document(doc1))
).build());
SimplePojo doc2 = new SimplePojo("Document 2", "The text of document 2");
ops.add(new BulkOperation.Builder().index(
IndexOperation.of(io -> io.index(TEST_INDEX).id("id2").document(doc2))
).build());
SimplePojo doc3 = getLongDoc("Long Document 3", 100000);
ops.add(new BulkOperation.Builder().index(
IndexOperation.of(io -> io.index(TEST_INDEX).id("id3").document(doc3))
).build());

BulkRequest.Builder bulkReq = new BulkRequest.Builder()
.index(index)
.operations(ops)
.refresh(Refresh.WaitFor);
BulkResponse bulkResponse = client.bulk(bulkReq.build());
```

## Aggregations

```java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@

@JsonpDeserializable
public class RangeBucket extends MultiBucketBase {

@Nullable
private final String key;
@Nullable
private final Double from;

Expand All @@ -68,6 +71,7 @@ public class RangeBucket extends MultiBucketBase {
private RangeBucket(Builder builder) {
super(builder);

this.key = builder.key;
this.from = builder.from;
this.to = builder.to;
this.fromAsString = builder.fromAsString;
Expand All @@ -79,6 +83,14 @@ public static RangeBucket of(Function<Builder, ObjectBuilder<RangeBucket>> fn) {
return fn.apply(new Builder()).build();
}

/**
* API name: {@code key}
*/
@Nullable
public final String key() {
return this.key;
}

/**
* API name: {@code from}
*/
Expand Down Expand Up @@ -114,6 +126,11 @@ public final String toAsString() {
protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {

super.serializeInternal(generator, mapper);
if (this.key != null) {
generator.writeKey("key");
generator.write(this.key);

}
if (this.from != null) {
generator.writeKey("from");
generator.write(this.from);
Expand Down Expand Up @@ -144,6 +161,9 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
*/

public static class Builder extends MultiBucketBase.AbstractBuilder<Builder> implements ObjectBuilder<RangeBucket> {

@Nullable
private String key;
@Nullable
private Double from;

Expand All @@ -156,6 +176,14 @@ public static class Builder extends MultiBucketBase.AbstractBuilder<Builder> imp
@Nullable
private String toAsString;

/**
* API name: {@code key}
*/
public final Builder key(String value) {
this.key = value;
return this;
}

/**
* API name: {@code from}
*/
Expand Down Expand Up @@ -216,6 +244,7 @@ public RangeBucket build() {

protected static void setupRangeBucketDeserializer(ObjectDeserializer<RangeBucket.Builder> op) {
setupMultiBucketBaseDeserializer(op);
op.add(Builder::key, JsonpDeserializer.stringDeserializer(), "key");
op.add(Builder::from, JsonpDeserializer.doubleDeserializer(), "from");
op.add(Builder::to, JsonpDeserializer.doubleDeserializer(), "to");
op.add(Builder::fromAsString, JsonpDeserializer.stringDeserializer(), "from_as_string");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static java.util.Collections.emptyMap;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertTrue;

public abstract class AbstractClusterClientIT extends OpenSearchJavaClientTestCase {
public void testClusterPutSettings() throws IOException {
Expand Down Expand Up @@ -95,11 +96,7 @@ public void testClusterUpdateSettingNonExistent() throws IOException {
} catch (OpenSearchException e) {
assertNotNull(e);
assertEquals(e.response().status(), 400);
assertEquals(
e.getMessage(),
"Request failed: [illegal_argument_exception] " +
"transient setting [no_idea_what_you_are_talking_about], not recognized"
);
assertTrue(e.getMessage().contains("transient setting [no_idea_what_you_are_talking_about], not recognized"));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.client.opensearch.integTest.restclient;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.hc.core5.http.HttpHost;
import org.junit.Test;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
import org.opensearch.client.opensearch._types.Refresh;
import org.opensearch.client.opensearch._types.aggregations.Aggregation;
import org.opensearch.client.opensearch._types.aggregations.AggregationRange;
import org.opensearch.client.opensearch._types.aggregations.DateRangeAggregation;
import org.opensearch.client.opensearch._types.aggregations.DateRangeExpression;
import org.opensearch.client.opensearch._types.aggregations.FieldDateMath;
import org.opensearch.client.opensearch._types.aggregations.RangeAggregation;
import org.opensearch.client.opensearch.core.SearchResponse;
import org.opensearch.client.opensearch.integTest.AbstractRequestIT;
import org.opensearch.client.transport.OpenSearchTransport;
import org.opensearch.client.transport.rest_client.RestClientTransport;
import org.opensearch.common.settings.Settings;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.List;

public class AggregationRequestIT extends AbstractRequestIT {

@Override
public OpenSearchTransport buildTransport(Settings settings, HttpHost[] hosts) throws IOException {
return new RestClientTransport(buildClient(settings, hosts), new JacksonJsonpMapper());
}

@Test
public void testValueRangeAggregation() throws Exception {
var index = "test-value-range-aggregation";
createDateRangeDocuments(index);
var searchResponse = sendAggregateRequest(index, "cost_ranges", getCostValueRangeAggregation());
var costRangesAggregations = searchResponse.aggregations().get("cost_ranges");
var buckets = costRangesAggregations._get()
._toAggregate()
.range()
.buckets()
.array();

assertEquals(3, buckets.size());
assertEquals(2, buckets.get(0).docCount());
assertEquals(2, buckets.get(1).docCount());
assertEquals(2, buckets.get(2).docCount());
}

@Test
public void testDateRangeAggregation() throws Exception {
var index = "test-date-range-aggregation";
createDateRangeDocuments(index);
var searchResponse = sendAggregateRequest(index, "expiry_ranges", getExpiryDateRangeAggregation());
var expiryRangesAggregations = searchResponse.aggregations().get("expiry_ranges");
var buckets = expiryRangesAggregations._get()
._toAggregate()
.dateRange()
.buckets()
.array();

assertEquals(3, buckets.size());
assertEquals(2, buckets.get(0).docCount());
assertEquals(2, buckets.get(1).docCount());
assertEquals(2, buckets.get(2).docCount());
}

private Aggregation getExpiryDateRangeAggregation() {
DateRangeAggregation expiryDateRangeAggregation = new DateRangeAggregation.Builder()
.field("expDate")
.ranges(getDateAggregationRanges())
.build();
return new Aggregation.Builder().dateRange(expiryDateRangeAggregation).build();
}

private Aggregation getCostValueRangeAggregation() {
RangeAggregation costValueRangeAggregation = new RangeAggregation.Builder()
.field("cost")
.ranges(getValueAggregationRanges())
.build();
return new Aggregation.Builder().range(costValueRangeAggregation).build();
}

private SearchResponse<Void> sendAggregateRequest(String index, String key, Aggregation value) throws IOException {
return javaClient().search(
request -> request.index(index)
.size(0)
.aggregations(key, value),
Void.class);
}

private List<DateRangeExpression> getDateAggregationRanges() {
return List.of(
new DateRangeExpression.Builder()
.from(builder -> builder.value((double) getDatePlusDays(1).getTime()))
.to(FieldDateMath.of(builder -> builder.value((double) getDatePlusDays(3).getTime() - 1000)))
.key("from-1-to-2-days")
.build(),
new DateRangeExpression.Builder()
.from(builder -> builder.value((double) getDatePlusDays(3).getTime()))
.to(FieldDateMath.of(builder -> builder.value((double) getDatePlusDays(5).getTime() - 1000)))
.key("from-3-to-4-days")
.build(),
new DateRangeExpression.Builder()
.from(builder -> builder.value((double) getDatePlusDays(5).getTime()))
.to(FieldDateMath.of(builder -> builder.value((double) getDatePlusDays(7).getTime() - 1000)))
.key("from-5-to-6-days")
.build()
);
}

private List<AggregationRange> getValueAggregationRanges() {
return List.of(
new AggregationRange.Builder().to("10").build(),
new AggregationRange.Builder().from("10").to("30").build(),
new AggregationRange.Builder().from("30").build()
);
}

private void createDateRangeDocuments(String index) throws IOException {
javaClient().create(_1 -> _1.index(index).id("1").document(createProduct("egg", 2, 1)).refresh(Refresh.True));
javaClient().create(_1 -> _1.index(index).id("2").document(createProduct("meat", 15, 2)).refresh(Refresh.True));
javaClient().create(_1 -> _1.index(index).id("3").document(createProduct("ham", 30, 3)).refresh(Refresh.True));
javaClient().create(_1 -> _1.index(index).id("4").document(createProduct("cheese", 25, 4)).refresh(Refresh.True));
javaClient().create(_1 -> _1.index(index).id("5").document(createProduct("pasta", 8, 5)).refresh(Refresh.True));
javaClient().create(_1 -> _1.index(index).id("6").document(createProduct("oil", 50, 6)).refresh(Refresh.True));
}

private ProductDetails createProduct(String name, int cost, int plusDays) {
return new ProductDetails(name, cost, getDatePlusDays(plusDays));
}

private Date getDatePlusDays(int plusDays) {
return java.sql.Date.from(LocalDateTime.of(2023, 2, 20, 0, 0, 0).plusDays(plusDays).toInstant(ZoneOffset.UTC));
}

public static class ProductDetails {
private String name;
private int cost;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
private Date expDate;

public ProductDetails() {
}

public ProductDetails(String name, int cost, Date expDate) {
this.name = name;
this.cost = cost;
this.expDate = expDate;
}

public String getName() {
return name;
}

public int getCost() {
return cost;
}

public Date getExpDate() {
return expDate;
}
}
}

0 comments on commit b3ee1e1

Please sign in to comment.