Skip to content

Commit 1b13ee2

Browse files
opensearch-trigger-bot[bot]github-actions[bot]uriofferup
authored
Fixes #1137 - Adding query_image to Neural query (#1138) (#1139)
* Fixes #1137 * Adds missing documentation. Added changelog * Added deserialization test --------- (cherry picked from commit 7b3719b) Signed-off-by: uri.nudelman <[email protected]> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: uri.nudelman <[email protected]>
1 parent 5b632ff commit 1b13ee2

File tree

5 files changed

+137
-6
lines changed

5 files changed

+137
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
33

44
## [Unreleased 2.x]
55
### Added
6+
- Adds `queryImage` (query_image) field to `NeuralQuery`, following definition in ([Neural Query](https://opensearch.org/docs/latest/query-dsl/specialized/neural/)) ([#1137](https://github.com/opensearch-project/opensearch-java/pull/1138))
67

78
### Dependencies
89

java-client/src/main/java/org/opensearch/client/opensearch/_types/query_dsl/NeuralQuery.java

+43-5
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
import org.opensearch.client.json.ObjectBuilderDeserializer;
1818
import org.opensearch.client.json.ObjectDeserializer;
1919
import org.opensearch.client.util.ApiTypeHelper;
20+
import org.opensearch.client.util.MissingRequiredPropertiesException;
2021
import org.opensearch.client.util.ObjectBuilder;
2122

2223
@JsonpDeserializable
2324
public class NeuralQuery extends QueryBase implements QueryVariant {
2425

2526
private final String field;
2627
private final String queryText;
28+
private final String queryImage;
2729
private final int k;
2830
@Nullable
2931
private final String modelId;
@@ -34,7 +36,11 @@ private NeuralQuery(NeuralQuery.Builder builder) {
3436
super(builder);
3537

3638
this.field = ApiTypeHelper.requireNonNull(builder.field, this, "field");
37-
this.queryText = ApiTypeHelper.requireNonNull(builder.queryText, this, "queryText");
39+
if (builder.queryText == null && builder.queryImage == null && !ApiTypeHelper.requiredPropertiesCheckDisabled()) {
40+
throw new MissingRequiredPropertiesException(this, "queryText", "queryImage");
41+
}
42+
this.queryText = builder.queryText;
43+
this.queryImage = builder.queryImage;
3844
this.k = ApiTypeHelper.requireNonNull(builder.k, this, "k");
3945
this.modelId = builder.modelId;
4046
this.filter = builder.filter;
@@ -64,14 +70,25 @@ public final String field() {
6470
}
6571

6672
/**
67-
* Required - Search query text.
73+
* Required - The query_text if query_image is not set.
74+
* Optional - The query_text if query_image is set.
6875
*
6976
* @return Search query text.
7077
*/
7178
public final String queryText() {
7279
return this.queryText;
7380
}
7481

82+
/**
83+
* Required - The query_image if query_text is not set.
84+
* Optional - The query_image if query_text is set.
85+
*
86+
* @return Search query image.
87+
*/
88+
public final String queryImage() {
89+
return this.queryImage;
90+
}
91+
7592
/**
7693
* Required - The number of neighbors to return.
7794
*
@@ -112,7 +129,13 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
112129

113130
super.serializeInternal(generator, mapper);
114131

115-
generator.write("query_text", this.queryText);
132+
if (this.queryText != null) {
133+
generator.write("query_text", this.queryText);
134+
}
135+
136+
if (this.queryImage != null) {
137+
generator.write("query_image", this.queryImage);
138+
}
116139

117140
if (this.modelId != null) {
118141
generator.write("model_id", this.modelId);
@@ -129,7 +152,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
129152
}
130153

131154
public Builder toBuilder() {
132-
return new Builder().field(field).queryText(queryText).k(k).modelId(modelId).filter(filter);
155+
return new Builder().field(field).queryText(queryText).queryImage(queryImage).k(k).modelId(modelId).filter(filter);
133156
}
134157

135158
/**
@@ -138,6 +161,7 @@ public Builder toBuilder() {
138161
public static class Builder extends QueryBase.AbstractBuilder<NeuralQuery.Builder> implements ObjectBuilder<NeuralQuery> {
139162
private String field;
140163
private String queryText;
164+
private String queryImage;
141165
private Integer k;
142166
@Nullable
143167
private String modelId;
@@ -156,7 +180,8 @@ public NeuralQuery.Builder field(@Nullable String field) {
156180
}
157181

158182
/**
159-
* Required - Search query text.
183+
* Required - The query_text if query_image is not set.
184+
* Optional - The query_text if query_image is set.
160185
*
161186
* @param queryText Search query text.
162187
* @return This builder.
@@ -166,6 +191,18 @@ public NeuralQuery.Builder queryText(@Nullable String queryText) {
166191
return this;
167192
}
168193

194+
/**
195+
* Required - The query_image if query_text is not set.
196+
* Optional - The query_image if query_text is set.
197+
*
198+
* @param queryImage Search query image.
199+
* @return This builder.
200+
*/
201+
public NeuralQuery.Builder queryImage(@Nullable String queryImage) {
202+
this.queryImage = queryImage;
203+
return this;
204+
}
205+
169206
/**
170207
* Optional - The model_id field if the default model for the index or field is set.
171208
* Required - The model_id field if there is no default model set for the index or field.
@@ -227,6 +264,7 @@ protected static void setupNeuralQueryDeserializer(ObjectDeserializer<NeuralQuer
227264
setupQueryBaseDeserializer(op);
228265

229266
op.add(NeuralQuery.Builder::queryText, JsonpDeserializer.stringDeserializer(), "query_text");
267+
op.add(NeuralQuery.Builder::queryImage, JsonpDeserializer.stringDeserializer(), "query_image");
230268
op.add(NeuralQuery.Builder::modelId, JsonpDeserializer.stringDeserializer(), "model_id");
231269
op.add(NeuralQuery.Builder::k, JsonpDeserializer.integerDeserializer(), "k");
232270
op.add(NeuralQuery.Builder::filter, Query._DESERIALIZER, "filter");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.client.util;
10+
11+
import java.util.StringJoiner;
12+
13+
/**
14+
* Thrown by {@link ObjectBuilder#build()} when one of the required properties is missing.
15+
* <p>
16+
* If you think this is an error and that the reported property is actually optional, a workaround is
17+
* available in {@link ApiTypeHelper} to disable checks. Use with caution.
18+
*/
19+
public class MissingRequiredPropertiesException extends RuntimeException {
20+
private Class<?> clazz;
21+
private String[] properties;
22+
23+
public MissingRequiredPropertiesException(Object obj, String... properties) {
24+
super(
25+
"Missing at least one required property between "
26+
+ buildPropertiesMsg(properties)
27+
+ " in '"
28+
+ obj.getClass().getSimpleName()
29+
+ "'"
30+
);
31+
this.clazz = obj.getClass();
32+
this.properties = properties;
33+
}
34+
35+
/**
36+
* The class where the missing property was found
37+
*/
38+
public Class<?> getObjectClass() {
39+
return clazz;
40+
}
41+
42+
public String[] getPropertiesName() {
43+
return properties;
44+
}
45+
46+
private static String buildPropertiesMsg(String[] properties) {
47+
final StringJoiner sj = new StringJoiner(",", "'", "'");
48+
for (final String property : properties) {
49+
sj.add(property);
50+
}
51+
return sj.toString();
52+
}
53+
}

java-client/src/test/java/org/opensearch/client/opensearch/_types/query_dsl/NeuralQueryTest.java

+35-1
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010

1111
import org.junit.Test;
1212
import org.opensearch.client.opensearch.model.ModelTestCase;
13+
import org.opensearch.client.util.MissingRequiredPropertiesException;
1314

1415
public class NeuralQueryTest extends ModelTestCase {
1516
@Test
16-
public void toBuilder() {
17+
public void toBuilder_queryText() {
1718
NeuralQuery origin = new NeuralQuery.Builder().field("field")
1819
.queryText("queryText")
1920
.k(1)
@@ -23,4 +24,37 @@ public void toBuilder() {
2324

2425
assertEquals(toJson(copied), toJson(origin));
2526
}
27+
28+
@Test
29+
public void toBuilder_queryImage() {
30+
NeuralQuery origin = new NeuralQuery.Builder().field("field")
31+
.queryImage("queryImage")
32+
.k(1)
33+
.filter(IdsQuery.of(builder -> builder.values("Some_ID")).toQuery())
34+
.build();
35+
NeuralQuery copied = origin.toBuilder().build();
36+
37+
assertEquals(toJson(copied), toJson(origin));
38+
}
39+
40+
@Test
41+
public void toBuilder_both() {
42+
NeuralQuery origin = new NeuralQuery.Builder().field("field")
43+
.queryText("queryText")
44+
.queryImage("queryImage")
45+
.k(1)
46+
.filter(IdsQuery.of(builder -> builder.values("Some_ID")).toQuery())
47+
.build();
48+
NeuralQuery copied = origin.toBuilder().build();
49+
50+
assertEquals(toJson(copied), toJson(origin));
51+
}
52+
53+
@Test
54+
public void toBuilder_missing_query() {
55+
assertThrows(
56+
MissingRequiredPropertiesException.class,
57+
() -> new NeuralQuery.Builder().field("field").k(1).filter(IdsQuery.of(builder -> builder.values("Some_ID")).toQuery()).build()
58+
);
59+
}
2660
}

java-client/src/test/java/org/opensearch/client/opensearch/model/VariantsTest.java

+5
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ public void testNeuralQueryFromJson() {
234234
+ " \"neural\": {\n"
235235
+ " \"passage_embedding\": {\n"
236236
+ " \"query_text\": \"Hi world!\",\n"
237+
+ " \"query_image\": \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+L+U4T8ABu8CpCYJ1DQAAAAASUVORK5CYII=\",\n"
237238
+ " \"model_id\": \"bQ1J8ooBpBj3wT4HVUsb\",\n"
238239
+ " \"k\": 100\n"
239240
+ " }\n"
@@ -245,6 +246,10 @@ public void testNeuralQueryFromJson() {
245246

246247
assertEquals("passage_embedding", searchRequest.query().neural().field());
247248
assertEquals("Hi world!", searchRequest.query().neural().queryText());
249+
assertEquals(
250+
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+L+U4T8ABu8CpCYJ1DQAAAAASUVORK5CYII=",
251+
searchRequest.query().neural().queryImage()
252+
);
248253
assertEquals("bQ1J8ooBpBj3wT4HVUsb", searchRequest.query().neural().modelId());
249254
assertEquals(100, searchRequest.query().neural().k());
250255
}

0 commit comments

Comments
 (0)