From 5235696160da0519b09cc89a97287a707f5e9e17 Mon Sep 17 00:00:00 2001 From: leevh0908 <1213185851@li> Date: Mon, 4 Nov 2024 20:45:30 +0800 Subject: [PATCH] Change NIN filter to use "not in" operator in Milvus - Milvus requires "not in" operator syntax instead of "nin" for filtering. - See https://milvus.io/docs/boolean.md - Updated test and added additional test coverage --- .../MilvusFilterExpressionConverter.java | 2 +- .../MilvusFilterExpressionConverterTests.java | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverter.java b/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverter.java index fd8cde2d49..2a27e487cc 100644 --- a/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverter.java +++ b/vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverter.java @@ -58,7 +58,7 @@ private String getOperationSymbol(Expression exp) { case IN: return " in "; case NIN: - return " nin "; + return " not in "; default: throw new RuntimeException("Not supported expression type:" + exp.type()); } diff --git a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverterTests.java b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverterTests.java index dd0b8ef82d..a2ef038897 100644 --- a/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverterTests.java +++ b/vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/MilvusFilterExpressionConverterTests.java @@ -29,8 +29,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.AND; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.EQ; +import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.GT; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.GTE; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.IN; +import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.LT; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.LTE; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.NE; import static org.springframework.ai.vectorstore.filter.Filter.ExpressionType.NIN; @@ -86,11 +88,11 @@ public void testGroup() { new Expression(EQ, new Key("country"), new Value("BG")))), new Expression(NIN, new Key("city"), new Value(List.of("Sofia", "Plovdiv"))))); assertThat(vectorExpr).isEqualTo( - "metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\" && metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\" && metadata[\"city\"] nin [\"Sofia\",\"Plovdiv\"]"); + "metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\" && metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\" && metadata[\"city\"] not in [\"Sofia\",\"Plovdiv\"]"); } @Test - public void tesBoolean() { + public void testBoolean() { // isOpen == true AND year >= 2020 AND country IN ["BG", "NL", "US"] String vectorExpr = this.converter.convertExpression(new Expression(AND, new Expression(AND, new Expression(EQ, new Key("isOpen"), new Value(true)), @@ -121,4 +123,36 @@ public void testComplexIdentifiers() { assertThat(vectorExpr).isEqualTo("metadata[\"country 1 2 3\"] == \"BG\""); } + @Test + public void testLt() { + // temperature < 0 + String vectorExpr = this.converter.convertExpression(new Expression(LT, new Key("temperature"), new Value(0))); + assertThat(vectorExpr).isEqualTo("metadata[\"temperature\"] < 0"); + } + + @Test + public void testLte() { + // humidity <= 100 + String vectorExpr = this.converter.convertExpression(new Expression(LTE, new Key("humidity"), new Value(100))); + assertThat(vectorExpr).isEqualTo("metadata[\"humidity\"] <= 100"); + } + + @Test + public void testGt() { + // price > 1000 + String vectorExpr = this.converter.convertExpression(new Expression(GT, new Key("price"), new Value(1000))); + assertThat(vectorExpr).isEqualTo("metadata[\"price\"] > 1000"); + } + + @Test + public void testCombinedComparisons() { + // price > 1000 && temperature < 25 && humidity <= 80 + String vectorExpr = this.converter.convertExpression(new Expression(AND, + new Expression(AND, new Expression(GT, new Key("price"), new Value(1000)), + new Expression(LT, new Key("temperature"), new Value(25))), + new Expression(LTE, new Key("humidity"), new Value(80)))); + assertThat(vectorExpr) + .isEqualTo("metadata[\"price\"] > 1000 && metadata[\"temperature\"] < 25 && metadata[\"humidity\"] <= 80"); + } + }