diff --git a/pom.xml b/pom.xml index 244b4af46a..89aaf6659e 100644 --- a/pom.xml +++ b/pom.xml @@ -205,6 +205,9 @@ 2.3.0 0.8.0 2.0.46 + 1.54.0 + 1.3.0 + 1.14.0 11.6.1 5.17.1 4.5.1 diff --git a/vector-stores/spring-ai-azure-store/pom.xml b/vector-stores/spring-ai-azure-store/pom.xml index 25bf7e5f11..c3435643fc 100644 --- a/vector-stores/spring-ai-azure-store/pom.xml +++ b/vector-stores/spring-ai-azure-store/pom.xml @@ -59,6 +59,24 @@ + + + com.azure + azure-identity + ${azure-identity.version} + + + + com.azure + azure-core + ${azure-core.version} + + + + com.azure + azure-json + ${azure-json.version} + com.alibaba.fastjson2 fastjson2 diff --git a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureAiSearchFilterExpressionConverterTests.java b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureAiSearchFilterExpressionConverterTests.java index a97c83740e..198423affd 100644 --- a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureAiSearchFilterExpressionConverterTests.java +++ b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureAiSearchFilterExpressionConverterTests.java @@ -44,10 +44,6 @@ */ public class AzureAiSearchFilterExpressionConverterTests { - private static String format(String text) { - return text.trim().replace(" " + System.lineSeparator(), System.lineSeparator()) + System.lineSeparator(); - } - @Test public void testMissingFilterName() { @@ -79,10 +75,9 @@ public void testEQ() { List.of(MetadataField.text("country"))); // country == "BG" + String expected = "meta_country eq 'BG'"; String vectorExpr = converter.convertExpression(new Expression(EQ, new Key("country"), new Value("BG"))); - assertThat(format(vectorExpr)).isEqualTo(""" - meta_country eq 'BG' - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -91,12 +86,11 @@ public void tesEqAndGte() { List.of(MetadataField.text("genre"), MetadataField.int32("year"))); // genre == "drama" AND year >= 2020 + String expected = "meta_genre eq 'drama' and meta_year ge 2020"; String vectorExpr = converter .convertExpression(new Expression(AND, new Expression(EQ, new Key("genre"), new Value("drama")), new Expression(GTE, new Key("year"), new Value(2020)))); - assertThat(format(vectorExpr)).isEqualTo(""" - meta_genre eq 'drama' and meta_year ge 2020 - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -105,11 +99,10 @@ public void tesIn() { List.of(MetadataField.text("genre"))); // genre in ["comedy", "documentary", "drama"] + String expected = " search.in(meta_genre, 'comedy,documentary,drama', ',')"; String vectorExpr = converter.convertExpression( new Expression(IN, new Key("genre"), new Value(List.of("comedy", "documentary", "drama")))); - assertThat(format(vectorExpr)).isEqualTo(""" - search.in(meta_genre, 'comedy,documentary,drama', ',') - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -118,11 +111,10 @@ public void tesNin() { List.of(MetadataField.text("genre"))); // genre in ["comedy", "documentary", "drama"] + String expected = " not search.in(meta_genre, 'comedy,documentary,drama', ',')"; String vectorExpr = converter.convertExpression( new Expression(NIN, new Key("genre"), new Value(List.of("comedy", "documentary", "drama")))); - assertThat(format(vectorExpr)).isEqualTo(""" - not search.in(meta_genre, 'comedy,documentary,drama', ',') - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -131,13 +123,12 @@ public void testNe() { List.of(MetadataField.text("city"), MetadataField.int64("year"), MetadataField.text("country"))); // year >= 2020 OR country == "BG" AND city != "Sofia" + String expected = "meta_year ge 2020 or meta_country eq 'BG' and meta_city ne 'Sofia'"; String vectorExpr = converter .convertExpression(new Expression(OR, new Expression(GTE, new Key("year"), new Value(2020)), new Expression(AND, new Expression(EQ, new Key("country"), new Value("BG")), new Expression(NE, new Key("city"), new Value("Sofia"))))); - assertThat(format(vectorExpr)).isEqualTo(""" - meta_year ge 2020 or meta_country eq 'BG' and meta_city ne 'Sofia' - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -146,14 +137,13 @@ public void testGroup() { List.of(MetadataField.text("city"), MetadataField.int64("year"), MetadataField.text("country"))); // (year >= 2020 OR country == "BG") AND city != "Sofia" + String expected = "(meta_year ge 2020 or meta_country eq 'BG') and meta_city ne 'Sofia'"; String vectorExpr = converter.convertExpression(new Expression(AND, new Group(new Expression(OR, new Expression(GTE, new Key("year"), new Value(2020)), new Expression(EQ, new Key("country"), new Value("BG")))), new Expression(NE, new Key("city"), new Value("Sofia")))); - assertThat(format(vectorExpr)).isEqualTo(""" - (meta_year ge 2020 or meta_country eq 'BG') and meta_city ne 'Sofia' - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -162,14 +152,13 @@ public void tesBoolean() { List.of(MetadataField.bool("isOpen"), MetadataField.int64("year"), MetadataField.text("country"))); // isOpen == true AND year >= 2020 AND country IN ["BG", "NL", "US"] + String expected = "meta_isOpen eq true and meta_year ge 2020 and search.in(meta_country, 'BG,NL,US', ',')"; String vectorExpr = converter.convertExpression(new Expression(AND, new Expression(AND, new Expression(EQ, new Key("isOpen"), new Value(true)), new Expression(GTE, new Key("year"), new Value(2020))), new Expression(IN, new Key("country"), new Value(List.of("BG", "NL", "US"))))); - assertThat(format(vectorExpr)).isEqualTo(""" - meta_isOpen eq true and meta_year ge 2020 and search.in(meta_country, 'BG,NL,US', ',') - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -178,13 +167,12 @@ public void testDecimal() { List.of(MetadataField.decimal("temperature"))); // temperature >= -15.6 && temperature <= +20.13 + String expected = "meta_temperature ge -15.6 and meta_temperature le 20.13"; String vectorExpr = converter .convertExpression(new Expression(AND, new Expression(GTE, new Key("temperature"), new Value(-15.6)), new Expression(LTE, new Key("temperature"), new Value(20.13)))); - assertThat(format(vectorExpr)).isEqualTo(""" - meta_temperature ge -15.6 and meta_temperature le 20.13 - """); + assertThat(vectorExpr).isEqualTo(expected); } @Test @@ -192,16 +180,13 @@ public void testComplexIdentifiers() { FilterExpressionConverter converter = new AzureAiSearchFilterExpressionConverter( List.of(MetadataField.text("country 1 2 3"))); + String expected = "'meta_country 1 2 3' eq 'BG'"; String vectorExpr = converter .convertExpression(new Expression(EQ, new Key("\"country 1 2 3\""), new Value("BG"))); - assertThat(format(vectorExpr)).isEqualTo(""" - 'meta_country 1 2 3' eq 'BG' - """); + assertThat(vectorExpr).isEqualTo(expected); vectorExpr = converter.convertExpression(new Expression(EQ, new Key("'country 1 2 3'"), new Value("BG"))); - assertThat(format(vectorExpr)).isEqualTo(""" - 'meta_country 1 2 3' eq 'BG' - """); + assertThat(vectorExpr).isEqualTo(expected); } } diff --git a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java index dc87de60fe..4b736caeed 100644 --- a/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java +++ b/vector-stores/spring-ai-azure-store/src/test/java/org/springframework/ai/vectorstore/azure/AzureVectorStoreIT.java @@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit; import com.azure.core.credential.AzureKeyCredential; +import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.search.documents.indexes.SearchIndexClient; import com.azure.search.documents.indexes.SearchIndexClientBuilder; import org.awaitility.Awaitility; @@ -300,6 +301,14 @@ public static class Config { @Bean public SearchIndexClient searchIndexClient() { + // Only set AZURE_AI_SEARCH_TEST_KEYLESS if role-based authentication is set up correctly on the integration service + // https://learn.microsoft.com/azure/search/search-security-rbac + if (System.getenv("AZURE_AI_SEARCH_TEST_KEYLESS").equals("true")) { + return new SearchIndexClientBuilder().endpoint(System.getenv("AZURE_AI_SEARCH_ENDPOINT")) + .credential(new DefaultAzureCredentialBuilder().build()) + .buildClient(); + } + return new SearchIndexClientBuilder().endpoint(System.getenv("AZURE_AI_SEARCH_ENDPOINT")) .credential(new AzureKeyCredential(System.getenv("AZURE_AI_SEARCH_API_KEY"))) .buildClient();