Skip to content

Commit cb28ba3

Browse files
authored
Fix group precedence in MilvusFilterExpressionConverter
The `doGroup` override converted a parenthesized filter group into `content && content`, duplicating the group body and dropping the parentheses that expressed the grouping. Because Milvus binds `&&` tighter than `||`, a filter such as (year >= 2020 OR country == 'BG') AND city != 'Sofia' was emitted without parentheses, so the trailing `AND` no longer applied to the whole group and the query silently matched the wrong documents. Replace the override with the conventional `doStartGroup`/`doEndGroup` hooks that wrap the group content in parentheses, consistent with the other filter expression converters such as `PgVectorFilterExpressionConverter`. Update the affected test, which asserted the incorrect output, and add a test covering a group used as the right-hand operand. Closes #6543 Signed-off-by: Seol-JY <70826982+Seol-JY@users.noreply.github.com>
1 parent b84c9a8 commit cb28ba3

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

vector-stores/spring-ai-milvus-store/src/main/java/org/springframework/ai/vectorstore/milvus/MilvusFilterExpressionConverter.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.ai.vectorstore.milvus;
1818

1919
import org.springframework.ai.vectorstore.filter.Filter.Expression;
20-
import org.springframework.ai.vectorstore.filter.Filter.ExpressionType;
2120
import org.springframework.ai.vectorstore.filter.Filter.Group;
2221
import org.springframework.ai.vectorstore.filter.Filter.Key;
2322
import org.springframework.ai.vectorstore.filter.converter.AbstractFilterExpressionConverter;
@@ -70,8 +69,13 @@ private String getOperationSymbol(Expression exp) {
7069
}
7170

7271
@Override
73-
protected void doGroup(Group group, StringBuilder context) {
74-
this.convertOperand(new Expression(ExpressionType.AND, group.content(), group.content()), context); // trick
72+
protected void doStartGroup(Group group, StringBuilder context) {
73+
context.append("(");
74+
}
75+
76+
@Override
77+
protected void doEndGroup(Group group, StringBuilder context) {
78+
context.append(")");
7579
}
7680

7781
@Override

vector-stores/spring-ai-milvus-store/src/test/java/org/springframework/ai/vectorstore/milvus/MilvusFilterExpressionConverterTests.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,18 @@ public void testGroup() {
9898
new Expression(EQ, new Key("country"), new Value("BG")))),
9999
new Expression(NIN, new Key("city"), new Value(List.of("Sofia", "Plovdiv")))));
100100
assertThat(vectorExpr).isEqualTo(
101-
"metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\" && metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\" && metadata[\"city\"] not in [\"Sofia\",\"Plovdiv\"]");
101+
"(metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\") && metadata[\"city\"] not in [\"Sofia\",\"Plovdiv\"]");
102+
}
103+
104+
@Test
105+
public void testGroupAsRightOperand() {
106+
// city == "Sofia" AND (year >= 2020 OR country == "BG")
107+
String vectorExpr = this.converter
108+
.convertExpression(new Expression(AND, new Expression(EQ, new Key("city"), new Value("Sofia")),
109+
new Group(new Expression(OR, new Expression(GTE, new Key("year"), new Value(2020)),
110+
new Expression(EQ, new Key("country"), new Value("BG"))))));
111+
assertThat(vectorExpr).isEqualTo(
112+
"metadata[\"city\"] == \"Sofia\" && (metadata[\"year\"] >= 2020 || metadata[\"country\"] == \"BG\")");
102113
}
103114

104115
@Test

0 commit comments

Comments
 (0)