Skip to content

Commit 7b8d109

Browse files
committed
fix: Fixed GH3577, Fixed the error in the PgVectorFilterExpressionConverter when parsing nested And and Or expressions, and added corresponding unit tests.
Signed-off-by: Sun Yuhan <[email protected]>
1 parent 1cb584a commit 7b8d109

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

vector-stores/spring-ai-pgvector-store/src/main/java/org/springframework/ai/vectorstore/pgvector/PgVectorFilterExpressionConverter.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,26 @@
2525
import org.springframework.ai.vectorstore.filter.converter.AbstractFilterExpressionConverter;
2626

2727
/**
28-
* Converts {@link Expression} into PgVector metadata filter expression format.
29-
* (https://www.postgresql.org/docs/current/functions-json.html)
28+
* Converts {@link Expression} into PgVector metadata filter expression format. (<a href=
29+
* "https://www.postgresql.org/docs/current/functions-json.html">functions-json</a>)
3030
*
3131
* @author Muthukumaran Navaneethakrishnan
3232
* @author Christian Tzolov
33+
* @author Sun Yuhan
3334
*/
3435
public class PgVectorFilterExpressionConverter extends AbstractFilterExpressionConverter {
3536

3637
@Override
3738
protected void doExpression(Expression expression, StringBuilder context) {
38-
if (expression.type() == Filter.ExpressionType.IN) {
39-
handleIn(expression, context);
40-
}
41-
else if (expression.type() == Filter.ExpressionType.NIN) {
42-
handleNotIn(expression, context);
43-
}
44-
else {
45-
this.convertOperand(expression.left(), context);
46-
context.append(getOperationSymbol(expression));
47-
this.convertOperand(expression.right(), context);
39+
switch (expression.type()) {
40+
case IN -> handleIn(expression, context);
41+
case NIN -> handleNotIn(expression, context);
42+
case AND, OR -> handleAndOr(expression, context);
43+
default -> {
44+
this.convertOperand(expression.left(), context);
45+
context.append(getOperationSymbol(expression));
46+
this.convertOperand(expression.right(), context);
47+
}
4848
}
4949
}
5050

@@ -77,6 +77,14 @@ private void handleNotIn(Expression expression, StringBuilder context) {
7777
context.append(")");
7878
}
7979

80+
private void handleAndOr(Expression expression, StringBuilder context) {
81+
context.append("(");
82+
this.convertOperand(expression.left(), context);
83+
context.append(getOperationSymbol(expression));
84+
this.convertOperand(expression.right(), context);
85+
context.append(")");
86+
}
87+
8088
private String getOperationSymbol(Expression exp) {
8189
switch (exp.type()) {
8290
case AND:

vector-stores/spring-ai-pgvector-store/src/test/java/org/springframework/ai/vectorstore/pgvector/PgVectorFilterExpressionConverterTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,16 @@ public void testComplexIdentifiers() {
119119
assertThat(vectorExpr).isEqualTo("$.\"country 1 2 3\" == \"BG\"");
120120
}
121121

122+
@Test
123+
public void testAndAndOrNesting() {
124+
Expression eq1 = new Expression(EQ, new Key("id"), new Value("1"));
125+
Expression eq2 = new Expression(EQ, new Key("id"), new Value("2"));
126+
Expression eqTom = new Expression(EQ, new Key("name"), new Value("tom"));
127+
Expression or = new Expression(OR, eq1, eq2);
128+
Expression and = new Expression(AND, or, eqTom);
129+
130+
String vectorExpr = this.converter.convertExpression(and);
131+
assertThat(vectorExpr).isEqualTo("(($.id == \"1\" || $.id == \"2\") && $.name == \"tom\")");
132+
}
133+
122134
}

0 commit comments

Comments
 (0)