28
28
import org .opensearch .index .query .BoolQueryBuilder ;
29
29
import org .opensearch .index .query .MatchQueryBuilder ;
30
30
import org .opensearch .index .query .NestedQueryBuilder ;
31
+ import org .opensearch .index .query .QueryBuilder ;
31
32
import org .opensearch .index .query .QueryBuilders ;
32
33
import org .opensearch .index .query .RangeQueryBuilder ;
33
34
import org .opensearch .index .query .TermQueryBuilder ;
40
41
public class HybridQueryIT extends BaseNeuralSearchIT {
41
42
private static final String TEST_BASIC_INDEX_NAME = "test-hybrid-basic-index" ;
42
43
private static final String TEST_BASIC_VECTOR_DOC_FIELD_INDEX_NAME = "test-hybrid-vector-doc-field-index" ;
44
+ private static final String TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME = "test-hybrid-multi-doc-nested-fields-index" ;
43
45
private static final String TEST_MULTI_DOC_INDEX_NAME = "test-hybrid-multi-doc-index" ;
44
46
private static final String TEST_MULTI_DOC_INDEX_NAME_ONE_SHARD = "test-hybrid-multi-doc-single-shard-index" ;
45
47
private static final String TEST_MULTI_DOC_INDEX_WITH_NESTED_TYPE_NAME_ONE_SHARD =
@@ -256,7 +258,7 @@ public void testComplexQuery_whenMultipleIdenticalSubQueries_thenSuccessful() {
256
258
public void testNoMatchResults_whenOnlyTermSubQueryWithoutMatch_thenEmptyResult () {
257
259
String modelId = null ;
258
260
try {
259
- initializeIndexIfNotExist (TEST_MULTI_DOC_INDEX_NAME );
261
+ initializeIndexIfNotExist (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME );
260
262
modelId = prepareModel ();
261
263
createSearchPipelineWithResultsPostProcessor (SEARCH_PIPELINE );
262
264
TermQueryBuilder termQueryBuilder = QueryBuilders .termQuery (TEST_TEXT_FIELD_NAME_1 , TEST_QUERY_TEXT );
@@ -266,7 +268,7 @@ public void testNoMatchResults_whenOnlyTermSubQueryWithoutMatch_thenEmptyResult(
266
268
hybridQueryBuilderOnlyTerm .add (termQuery2Builder );
267
269
268
270
Map <String , Object > searchResponseAsMap = search (
269
- TEST_MULTI_DOC_INDEX_NAME ,
271
+ TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME ,
270
272
hybridQueryBuilderOnlyTerm ,
271
273
null ,
272
274
10 ,
@@ -283,7 +285,7 @@ public void testNoMatchResults_whenOnlyTermSubQueryWithoutMatch_thenEmptyResult(
283
285
assertNotNull (total .get ("relation" ));
284
286
assertEquals (RELATION_EQUAL_TO , total .get ("relation" ));
285
287
} finally {
286
- wipeOfTestResources (TEST_MULTI_DOC_INDEX_NAME , null , modelId , SEARCH_PIPELINE );
288
+ wipeOfTestResources (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME , null , modelId , SEARCH_PIPELINE );
287
289
}
288
290
}
289
291
@@ -578,6 +580,102 @@ public void testRequestCache_whenMultipleShardsQueryReturnResults_thenSuccessful
578
580
}
579
581
}
580
582
583
+ @ SneakyThrows
584
+ public void testWrappedQueryWithFilter_whenIndexAliasHasFilterAndIndexWithNestedFields_thenSuccess () {
585
+ String modelId = null ;
586
+ String alias = "alias_with_filter" ;
587
+ try {
588
+ initializeIndexIfNotExist (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME );
589
+ modelId = prepareModel ();
590
+ createSearchPipelineWithResultsPostProcessor (SEARCH_PIPELINE );
591
+ // create alias for index
592
+ QueryBuilder aliasFilter = QueryBuilders .boolQuery ()
593
+ .mustNot (QueryBuilders .matchQuery (TEST_TEXT_FIELD_NAME_1 , TEST_QUERY_TEXT3 ));
594
+ createIndexAlias (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME , alias , aliasFilter );
595
+
596
+ NeuralQueryBuilder neuralQueryBuilder = new NeuralQueryBuilder (
597
+ TEST_KNN_VECTOR_FIELD_NAME_1 ,
598
+ TEST_QUERY_TEXT ,
599
+ "" ,
600
+ modelId ,
601
+ 5 ,
602
+ null ,
603
+ null
604
+ );
605
+ HybridQueryBuilder hybridQueryBuilder = new HybridQueryBuilder ();
606
+ hybridQueryBuilder .add (neuralQueryBuilder );
607
+
608
+ Map <String , Object > searchResponseAsMap = search (
609
+ alias ,
610
+ hybridQueryBuilder ,
611
+ null ,
612
+ 10 ,
613
+ Map .of ("search_pipeline" , SEARCH_PIPELINE )
614
+ );
615
+
616
+ assertEquals (2 , getHitCount (searchResponseAsMap ));
617
+ assertTrue (getMaxScore (searchResponseAsMap ).isPresent ());
618
+ assertEquals (1.0f , getMaxScore (searchResponseAsMap ).get (), DELTA_FOR_SCORE_ASSERTION );
619
+
620
+ Map <String , Object > total = getTotalHits (searchResponseAsMap );
621
+ assertNotNull (total .get ("value" ));
622
+ assertEquals (2 , total .get ("value" ));
623
+ assertNotNull (total .get ("relation" ));
624
+ assertEquals (RELATION_EQUAL_TO , total .get ("relation" ));
625
+ } finally {
626
+ deleteIndexAlias (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME , alias );
627
+ wipeOfTestResources (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME , null , modelId , SEARCH_PIPELINE );
628
+ }
629
+ }
630
+
631
+ @ SneakyThrows
632
+ public void testWrappedQueryWithFilter_whenIndexAliasHasFilters_thenSuccess () {
633
+ String modelId = null ;
634
+ String alias = "alias_with_filter" ;
635
+ try {
636
+ initializeIndexIfNotExist (TEST_MULTI_DOC_INDEX_NAME );
637
+ modelId = prepareModel ();
638
+ createSearchPipelineWithResultsPostProcessor (SEARCH_PIPELINE );
639
+ // create alias for index
640
+ QueryBuilder aliasFilter = QueryBuilders .boolQuery ()
641
+ .mustNot (QueryBuilders .matchQuery (TEST_TEXT_FIELD_NAME_1 , TEST_QUERY_TEXT3 ));
642
+ createIndexAlias (TEST_MULTI_DOC_INDEX_NAME , alias , aliasFilter );
643
+
644
+ NeuralQueryBuilder neuralQueryBuilder = new NeuralQueryBuilder (
645
+ TEST_KNN_VECTOR_FIELD_NAME_1 ,
646
+ TEST_QUERY_TEXT ,
647
+ "" ,
648
+ modelId ,
649
+ 5 ,
650
+ null ,
651
+ null
652
+ );
653
+ HybridQueryBuilder hybridQueryBuilder = new HybridQueryBuilder ();
654
+ hybridQueryBuilder .add (neuralQueryBuilder );
655
+
656
+ Map <String , Object > searchResponseAsMap = search (
657
+ alias ,
658
+ hybridQueryBuilder ,
659
+ null ,
660
+ 10 ,
661
+ Map .of ("search_pipeline" , SEARCH_PIPELINE )
662
+ );
663
+
664
+ assertEquals (2 , getHitCount (searchResponseAsMap ));
665
+ assertTrue (getMaxScore (searchResponseAsMap ).isPresent ());
666
+ assertEquals (1.0f , getMaxScore (searchResponseAsMap ).get (), DELTA_FOR_SCORE_ASSERTION );
667
+
668
+ Map <String , Object > total = getTotalHits (searchResponseAsMap );
669
+ assertNotNull (total .get ("value" ));
670
+ assertEquals (2 , total .get ("value" ));
671
+ assertNotNull (total .get ("relation" ));
672
+ assertEquals (RELATION_EQUAL_TO , total .get ("relation" ));
673
+ } finally {
674
+ deleteIndexAlias (TEST_MULTI_DOC_INDEX_NAME , alias );
675
+ wipeOfTestResources (TEST_MULTI_DOC_INDEX_NAME , null , modelId , SEARCH_PIPELINE );
676
+ }
677
+ }
678
+
581
679
@ SneakyThrows
582
680
private void initializeIndexIfNotExist (String indexName ) throws IOException {
583
681
if (TEST_BASIC_INDEX_NAME .equals (indexName ) && !indexExists (TEST_BASIC_INDEX_NAME )) {
@@ -628,10 +726,28 @@ private void initializeIndexIfNotExist(String indexName) throws IOException {
628
726
assertEquals (3 , getDocCount (TEST_BASIC_VECTOR_DOC_FIELD_INDEX_NAME ));
629
727
}
630
728
729
+ if (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME .equals (indexName ) && !indexExists (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME )) {
730
+ createIndexWithConfiguration (
731
+ indexName ,
732
+ buildIndexConfiguration (
733
+ Collections .singletonList (new KNNFieldConfig (TEST_KNN_VECTOR_FIELD_NAME_1 , TEST_DIMENSION , TEST_SPACE_TYPE )),
734
+ List .of (TEST_NESTED_TYPE_FIELD_NAME_1 ),
735
+ 1
736
+ ),
737
+ ""
738
+ );
739
+ addDocsToIndex (TEST_MULTI_DOC_WITH_NESTED_FIELDS_INDEX_NAME );
740
+ }
741
+
631
742
if (TEST_MULTI_DOC_INDEX_NAME .equals (indexName ) && !indexExists (TEST_MULTI_DOC_INDEX_NAME )) {
632
- prepareKnnIndex (
633
- TEST_MULTI_DOC_INDEX_NAME ,
634
- Collections .singletonList (new KNNFieldConfig (TEST_KNN_VECTOR_FIELD_NAME_1 , TEST_DIMENSION , TEST_SPACE_TYPE ))
743
+ createIndexWithConfiguration (
744
+ indexName ,
745
+ buildIndexConfiguration (
746
+ Collections .singletonList (new KNNFieldConfig (TEST_KNN_VECTOR_FIELD_NAME_1 , TEST_DIMENSION , TEST_SPACE_TYPE )),
747
+ List .of (),
748
+ 1
749
+ ),
750
+ ""
635
751
);
636
752
addDocsToIndex (TEST_MULTI_DOC_INDEX_NAME );
637
753
}
0 commit comments