55import com .microsoft .semantickernel .connectors .data .jdbc .JDBCVectorStoreRecordCollectionOptions ;
66import com .microsoft .semantickernel .connectors .data .mysql .MySQLVectorStoreQueryProvider ;
77import com .microsoft .semantickernel .connectors .data .postgres .PostgreSQLVectorStoreQueryProvider ;
8+ import com .microsoft .semantickernel .connectors .data .jdbc .filter .SQLEqualToFilterClause ;
9+ import com .microsoft .semantickernel .data .vectorsearch .VectorSearchFilter ;
810import com .microsoft .semantickernel .data .vectorsearch .VectorSearchResult ;
911import com .microsoft .semantickernel .data .vectorstorage .options .GetRecordOptions ;
1012import com .microsoft .semantickernel .data .vectorstorage .options .VectorSearchOptions ;
@@ -103,13 +105,22 @@ private List<Hotel> getHotels() {
103105
104106 return List .of (
105107 new Hotel ("id_1" , "Hotel 1" , 1 , "Hotel 1 description" , Arrays .asList (0.5f , 3.2f , 7.1f , -4.0f , 2.8f , 10.0f , -1.3f , 5.5f ),null , null , null , 4.0 ),
106- new Hotel ("id_2" , "Hotel 2" , 2 , "Hotel 2 description" , Arrays .asList (-2.0f , 8.1f , 0.9f , 5.4f , -3.3f , 2.2f , 9.9f , -4.5f ),null , null , null , 3 .0 ),
108+ new Hotel ("id_2" , "Hotel 2" , 2 , "Hotel 2 description" , Arrays .asList (-2.0f , 8.1f , 0.9f , 5.4f , -3.3f , 2.2f , 9.9f , -4.5f ),null , null , null , 4 .0 ),
107109 new Hotel ("id_3" , "Hotel 3" , 3 , "Hotel 3 description" , Arrays .asList (4.5f , -6.2f , 3.1f , 7.7f , -0.8f , 1.1f , -2.2f , 8.3f ),null , null , null , 5.0 ),
108- new Hotel ("id_4" , "Hotel 4" , 4 , "Hotel 4 description" , Arrays .asList (7.0f , 1.2f , -5.3f , 2.5f , 6.6f , -7.8f , 3.9f , -0.1f ),null , null , null , 2 .0 ),
109- new Hotel ("id_5" , "Hotel 5" , 5 , "Hotel 5 description" , Arrays .asList (-3.5f , 4.4f , -1.2f , 9.9f , 5.7f , -6.1f , 7.8f , -2.0f ),null , null , null , 1 .0 )
110+ new Hotel ("id_4" , "Hotel 4" , 4 , "Hotel 4 description" , Arrays .asList (7.0f , 1.2f , -5.3f , 2.5f , 6.6f , -7.8f , 3.9f , -0.1f ),null , null , null , 4 .0 ),
111+ new Hotel ("id_5" , "Hotel 5" , 5 , "Hotel 5 description" , Arrays .asList (-3.5f , 4.4f , -1.2f , 9.9f , 5.7f , -6.1f , 7.8f , -2.0f ),null , null , null , 4 .0 )
110112 );
111113 }
112114
115+ /**
116+ * Search embeddings similar to the third hotel embeddings.
117+ * In order of similarity:
118+ * 1. Hotel 3
119+ * 2. Hotel 1
120+ * 3. Hotel 4
121+ */
122+ private static final List <Float > SEARCH_EMBEDDINGS = Arrays .asList (4.5f , -6.2f , 3.1f , 7.7f , -0.8f , 1.1f , -2.2f , 8.2f );
123+
113124 @ ParameterizedTest
114125 @ EnumSource (QueryProvider .class )
115126 public void upsertAndGetRecordAsync (QueryProvider provider ) {
@@ -315,7 +326,7 @@ public void getBatchWithNoVectors(QueryProvider provider) {
315326 }
316327 }
317328
318- private static Stream <Arguments > provideParameters () {
329+ private static Stream <Arguments > provideSearchParameters () {
319330 return Stream .of (
320331 Arguments .of (QueryProvider .MySQL , "euclidean" ),
321332 Arguments .of (QueryProvider .MySQL , "cosineDistance" ),
@@ -327,9 +338,9 @@ private static Stream<Arguments> provideParameters() {
327338 }
328339
329340 @ ParameterizedTest
330- @ MethodSource ("provideParameters " )
341+ @ MethodSource ("provideSearchParameters " )
331342 public void exactSearch (QueryProvider provider , String embeddingName ) {
332- String collectionName = "search" ;
343+ String collectionName = "search" + embeddingName ;
333344 JDBCVectorStoreRecordCollection <Hotel > recordCollection = buildRecordCollection (provider , collectionName );
334345
335346 List <Hotel > hotels = getHotels ();
@@ -341,8 +352,7 @@ public void exactSearch(QueryProvider provider, String embeddingName) {
341352 .build ();
342353
343354 // Embeddings similar to the third hotel
344- List <Float > embeddings = Arrays .asList (4.5f , -6.2f , 3.1f , 7.7f , -0.8f , 1.1f , -2.2f , 8.2f );
345- List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (embeddings , options ).block ();
355+ List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (SEARCH_EMBEDDINGS , options ).block ();
346356 assertNotNull (results );
347357 assertEquals (3 , results .size ());
348358 // The third hotel should be the most similar
@@ -355,7 +365,7 @@ public void exactSearch(QueryProvider provider, String embeddingName) {
355365 .build ();
356366
357367 // Skip the first result
358- results = recordCollection .searchAsync (embeddings , options ).block ();
368+ results = recordCollection .searchAsync (SEARCH_EMBEDDINGS , options ).block ();
359369 assertNotNull (results );
360370 assertEquals (1 , results .size ());
361371 // The first hotel should be the most similar
@@ -377,14 +387,37 @@ public void approximateSearch(QueryProvider provider) {
377387 .build ();
378388
379389 // Embeddings similar to the third hotel
380- List <Float > embeddings = Arrays .asList (4.5f , -6.2f , 3.1f , 7.7f , -0.8f , 1.1f , -2.2f , 8.2f );
381- List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (embeddings , options ).block ();
390+ List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (SEARCH_EMBEDDINGS , options ).block ();
382391 assertNotNull (results );
383392 assertEquals (5 , results .size ());
384393 // The third hotel should be the most similar
385394 assertEquals (hotels .get (2 ).getId (), results .get (0 ).getRecord ().getId ());
386395 }
387396
397+ @ ParameterizedTest
398+ @ MethodSource ("provideSearchParameters" )
399+ public void searchWithFilter (QueryProvider provider , String embeddingName ) {
400+ String collectionName = "searchWithFilter" ;
401+ JDBCVectorStoreRecordCollection <Hotel > recordCollection = buildRecordCollection (provider , collectionName );
402+
403+ List <Hotel > hotels = getHotels ();
404+ recordCollection .upsertBatchAsync (hotels , null ).block ();
405+
406+ VectorSearchOptions options = VectorSearchOptions .builder ()
407+ .withVectorFieldName (embeddingName )
408+ .withLimit (3 )
409+ .withBasicVectorSearchFilter (
410+ VectorSearchFilter .builder ().withEqualToFilterClause (new SQLEqualToFilterClause ("rating" , 4.0 )).build ())
411+ .build ();
412+
413+ // Embeddings similar to the third hotel, but as the filter is set to 4.0, the third hotel should not be returned
414+ List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (SEARCH_EMBEDDINGS , options ).block ();
415+ assertNotNull (results );
416+ assertEquals (3 , results .size ());
417+ // The first hotel should be the most similar
418+ assertEquals (hotels .get (0 ).getId (), results .get (0 ).getRecord ().getId ());
419+ }
420+
388421 // MySQL will always return the vectors as they're needed to compute the distances
389422 @ Test
390423 public void postgresSearchIncludeAndNotIncludeVectors () {
@@ -394,9 +427,7 @@ public void postgresSearchIncludeAndNotIncludeVectors() {
394427 List <Hotel > hotels = getHotels ();
395428 recordCollection .upsertBatchAsync (hotels , null ).block ();
396429
397- // Embeddings similar to the third hotel
398- List <Float > embeddings = Arrays .asList (4.5f , -6.2f , 3.1f , 7.7f , -0.8f , 1.1f , -2.2f , 8.2f );
399- List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (embeddings , null ).block ();
430+ List <VectorSearchResult <Hotel >> results = recordCollection .searchAsync (SEARCH_EMBEDDINGS , null ).block ();
400431 assertNotNull (results );
401432 assertEquals (3 , results .size ());
402433 // The third hotel should be the most similar
@@ -407,7 +438,7 @@ public void postgresSearchIncludeAndNotIncludeVectors() {
407438 .withIncludeVectors (true )
408439 .build ();
409440
410- results = recordCollection .searchAsync (embeddings , options ).block ();
441+ results = recordCollection .searchAsync (SEARCH_EMBEDDINGS , options ).block ();
411442 assertNotNull (results );
412443 assertEquals (3 , results .size ());
413444 // The third hotel should be the most similar
0 commit comments