Skip to content

Commit b1b1216

Browse files
committed
add validation for invalid nested hybrid query
Signed-off-by: Will Hwang <[email protected]>
1 parent c5625db commit b1b1216

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

src/main/java/org/opensearch/neuralsearch/query/HybridQueryBuilder.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,14 @@ public static HybridQueryBuilder fromXContent(XContentParser parser) throws IOEx
225225
String.format(Locale.ROOT, "Number of sub-queries exceeds maximum supported by [%s] query", NAME)
226226
);
227227
}
228-
queries.add(parseInnerQueryBuilder(parser));
228+
QueryBuilder query = parseInnerQueryBuilder(parser);
229+
if (query.getName().equals(NAME)) {
230+
throw new ParsingException(
231+
parser.getTokenLocation(),
232+
String.format(Locale.ROOT, "[%s] query cannot be nested in another [%s] query", NAME, NAME)
233+
);
234+
}
235+
queries.add(query);
229236
token = parser.nextToken();
230237
}
231238
} else {

src/test/java/org/opensearch/neuralsearch/query/HybridQueryBuilderTests.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,68 @@ public void testDoToQuery_whenTooManySubqueries_thenFail() {
354354
assertThat(exception.getMessage(), containsString("Number of sub-queries exceeds maximum supported"));
355355
}
356356

357+
@SneakyThrows
358+
public void testDoToQuery_whenNestedHybridSubqueries_thenFail() {
359+
// create query with nested hybrid subqueries, which should not be allowed
360+
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
361+
.startObject()
362+
.startArray("queries")
363+
.startObject()
364+
.startObject(HybridQueryBuilder.NAME)
365+
.startArray("queries")
366+
.startObject()
367+
.startObject(NeuralQueryBuilder.NAME)
368+
.startObject(VECTOR_FIELD_NAME)
369+
.field(QUERY_TEXT_FIELD.getPreferredName(), QUERY_TEXT)
370+
.field(MODEL_ID_FIELD.getPreferredName(), MODEL_ID)
371+
.field(K_FIELD.getPreferredName(), K)
372+
.field(BOOST_FIELD.getPreferredName(), BOOST)
373+
.endObject()
374+
.endObject()
375+
.endObject()
376+
.startObject()
377+
.startObject(TermQueryBuilder.NAME)
378+
.field(TEXT_FIELD_NAME, TERM_QUERY_TEXT)
379+
.endObject()
380+
.endObject()
381+
.endArray()
382+
.endObject()
383+
.endObject()
384+
.startObject()
385+
.startObject(TermQueryBuilder.NAME)
386+
.field(TEXT_FIELD_NAME, TERM_QUERY_TEXT)
387+
.endObject()
388+
.endObject()
389+
.endArray()
390+
.field("pagination_depth", 10)
391+
.endObject();
392+
393+
NamedXContentRegistry namedXContentRegistry = new NamedXContentRegistry(
394+
List.of(
395+
new NamedXContentRegistry.Entry(QueryBuilder.class, new ParseField(TermQueryBuilder.NAME), TermQueryBuilder::fromXContent),
396+
new NamedXContentRegistry.Entry(
397+
QueryBuilder.class,
398+
new ParseField(NeuralQueryBuilder.NAME),
399+
NeuralQueryBuilder::fromXContent
400+
),
401+
new NamedXContentRegistry.Entry(
402+
QueryBuilder.class,
403+
new ParseField(HybridQueryBuilder.NAME),
404+
HybridQueryBuilder::fromXContent
405+
)
406+
)
407+
);
408+
XContentParser contentParser = createParser(
409+
namedXContentRegistry,
410+
xContentBuilder.contentType().xContent(),
411+
BytesReference.bytes(xContentBuilder)
412+
);
413+
contentParser.nextToken();
414+
415+
ParsingException exception = expectThrows(ParsingException.class, () -> HybridQueryBuilder.fromXContent(contentParser));
416+
assertThat(exception.getMessage(), containsString("[hybrid] query cannot be nested in another [hybrid] query"));
417+
}
418+
357419
/**
358420
* Tests basic query:
359421
* {

0 commit comments

Comments
 (0)