|
58 | 58 | import org.opensearch.index.mapper.TextFieldMapper;
|
59 | 59 | import org.opensearch.index.query.BoolQueryBuilder;
|
60 | 60 | import org.opensearch.index.query.QueryBuilders;
|
| 61 | +import org.opensearch.index.query.DisMaxQueryBuilder; |
61 | 62 | import org.opensearch.index.query.QueryShardContext;
|
62 | 63 | import org.opensearch.index.query.TermQueryBuilder;
|
63 | 64 | import org.opensearch.index.remote.RemoteStoreEnums;
|
@@ -516,6 +517,104 @@ public void testWrappedHybridQuery_whenHybridWrappedIntoBool_thenFail() {
|
516 | 517 | releaseResources(directory, w, reader);
|
517 | 518 | }
|
518 | 519 |
|
| 520 | + @SneakyThrows |
| 521 | + public void testWrappedHybridQuery_whenHybridNestedInDisjunctionQuery_thenFail() { |
| 522 | + HybridQueryPhaseSearcher hybridQueryPhaseSearcher = new HybridQueryPhaseSearcher(); |
| 523 | + QueryShardContext mockQueryShardContext = mock(QueryShardContext.class); |
| 524 | + when(mockQueryShardContext.index()).thenReturn(dummyIndex); |
| 525 | + TextFieldMapper.TextFieldType fieldType = (TextFieldMapper.TextFieldType) createMapperService().fieldType(TEXT_FIELD_NAME); |
| 526 | + when(mockQueryShardContext.fieldMapper(eq(TEXT_FIELD_NAME))).thenReturn(fieldType); |
| 527 | + MapperService mapperService = mock(MapperService.class); |
| 528 | + when(mapperService.hasNested()).thenReturn(false); |
| 529 | + |
| 530 | + Directory directory = newDirectory(); |
| 531 | + IndexWriter w = new IndexWriter(directory, newIndexWriterConfig(new MockAnalyzer(random()))); |
| 532 | + FieldType ft = new FieldType(TextField.TYPE_NOT_STORED); |
| 533 | + ft.setIndexOptions(random().nextBoolean() ? IndexOptions.DOCS : IndexOptions.DOCS_AND_FREQS); |
| 534 | + ft.setOmitNorms(random().nextBoolean()); |
| 535 | + ft.freeze(); |
| 536 | + int docId1 = RandomizedTest.randomInt(); |
| 537 | + w.addDocument(getDocument(TEXT_FIELD_NAME, docId1, TEST_DOC_TEXT1, ft)); |
| 538 | + w.commit(); |
| 539 | + |
| 540 | + IndexReader reader = DirectoryReader.open(w); |
| 541 | + SearchContext searchContext = mock(SearchContext.class); |
| 542 | + |
| 543 | + ContextIndexSearcher contextIndexSearcher = new ContextIndexSearcher( |
| 544 | + reader, |
| 545 | + IndexSearcher.getDefaultSimilarity(), |
| 546 | + IndexSearcher.getDefaultQueryCache(), |
| 547 | + IndexSearcher.getDefaultQueryCachingPolicy(), |
| 548 | + true, |
| 549 | + null, |
| 550 | + searchContext |
| 551 | + ); |
| 552 | + |
| 553 | + ShardId shardId = new ShardId(dummyIndex, 1); |
| 554 | + SearchShardTarget shardTarget = new SearchShardTarget( |
| 555 | + randomAlphaOfLength(10), |
| 556 | + shardId, |
| 557 | + randomAlphaOfLength(10), |
| 558 | + OriginalIndices.NONE |
| 559 | + ); |
| 560 | + when(searchContext.shardTarget()).thenReturn(shardTarget); |
| 561 | + when(searchContext.searcher()).thenReturn(contextIndexSearcher); |
| 562 | + when(searchContext.size()).thenReturn(4); |
| 563 | + QuerySearchResult querySearchResult = new QuerySearchResult(); |
| 564 | + when(searchContext.queryResult()).thenReturn(querySearchResult); |
| 565 | + when(searchContext.numberOfShards()).thenReturn(1); |
| 566 | + when(searchContext.searcher()).thenReturn(contextIndexSearcher); |
| 567 | + IndexShard indexShard = mock(IndexShard.class); |
| 568 | + when(indexShard.shardId()).thenReturn(new ShardId("test", "test", 0)); |
| 569 | + when(indexShard.getSearchOperationListener()).thenReturn(mock(SearchOperationListener.class)); |
| 570 | + when(searchContext.indexShard()).thenReturn(indexShard); |
| 571 | + when(searchContext.bucketCollectorProcessor()).thenReturn(SearchContext.NO_OP_BUCKET_COLLECTOR_PROCESSOR); |
| 572 | + when(searchContext.mapperService()).thenReturn(mapperService); |
| 573 | + when(searchContext.getQueryShardContext()).thenReturn(mockQueryShardContext); |
| 574 | + IndexMetadata indexMetadata = getIndexMetadata(); |
| 575 | + Settings settings = Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, Integer.toString(1)).build(); |
| 576 | + IndexSettings indexSettings = new IndexSettings(indexMetadata, settings); |
| 577 | + when(mockQueryShardContext.getIndexSettings()).thenReturn(indexSettings); |
| 578 | + |
| 579 | + LinkedList<QueryCollectorContext> collectors = new LinkedList<>(); |
| 580 | + boolean hasFilterCollector = randomBoolean(); |
| 581 | + boolean hasTimeout = randomBoolean(); |
| 582 | + |
| 583 | + // Create a HybridQueryBuilder |
| 584 | + HybridQueryBuilder hybridQueryBuilder = new HybridQueryBuilder(); |
| 585 | + hybridQueryBuilder.add(QueryBuilders.termQuery(TEXT_FIELD_NAME, QUERY_TEXT1)); |
| 586 | + hybridQueryBuilder.add(QueryBuilders.termQuery(TEXT_FIELD_NAME, QUERY_TEXT2)); |
| 587 | + hybridQueryBuilder.paginationDepth(10); |
| 588 | + |
| 589 | + // Create a regular term query |
| 590 | + TermQueryBuilder termQuery = QueryBuilders.termQuery(TEXT_FIELD_NAME, QUERY_TEXT2); |
| 591 | + |
| 592 | + // Create a disjunction query (OR) with the hybrid query and the term query |
| 593 | + DisMaxQueryBuilder disjunctionMaxQueryBuilder = QueryBuilders.disMaxQuery().add(hybridQueryBuilder).add(termQuery); |
| 594 | + |
| 595 | + Query query = disjunctionMaxQueryBuilder.toQuery(mockQueryShardContext); |
| 596 | + when(searchContext.query()).thenReturn(query); |
| 597 | + |
| 598 | + IllegalArgumentException exception = expectThrows( |
| 599 | + IllegalArgumentException.class, |
| 600 | + () -> hybridQueryPhaseSearcher.searchWith( |
| 601 | + searchContext, |
| 602 | + contextIndexSearcher, |
| 603 | + query, |
| 604 | + collectors, |
| 605 | + hasFilterCollector, |
| 606 | + hasTimeout |
| 607 | + ) |
| 608 | + ); |
| 609 | + |
| 610 | + org.hamcrest.MatcherAssert.assertThat( |
| 611 | + exception.getMessage(), |
| 612 | + containsString("hybrid query must be a top level query and cannot be wrapped into other queries") |
| 613 | + ); |
| 614 | + |
| 615 | + releaseResources(directory, w, reader); |
| 616 | + } |
| 617 | + |
519 | 618 | @SneakyThrows
|
520 | 619 | public void testWrappedHybridQuery_whenHybridWrappedIntoBoolAndIncorrectStructure_thenFail() {
|
521 | 620 | HybridQueryPhaseSearcher hybridQueryPhaseSearcher = new HybridQueryPhaseSearcher();
|
|
0 commit comments