Skip to content

Commit de85c6b

Browse files
authored
Merge pull request #386 from weaviate/feat/minimum_should_match
Add searchOperator (minimum_should_match) to bm25 and hybrid arguments
2 parents 1a02879 + 79c459a commit de85c6b

File tree

5 files changed

+1050
-779
lines changed

5 files changed

+1050
-779
lines changed
Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
package io.weaviate.client.v1.graphql.query.argument;
22

3+
import java.util.LinkedHashSet;
4+
import java.util.Set;
5+
36
import io.weaviate.client.v1.graphql.query.util.Serializer;
47
import lombok.AccessLevel;
8+
import lombok.AllArgsConstructor;
59
import lombok.Builder;
610
import lombok.EqualsAndHashCode;
711
import lombok.Getter;
812
import lombok.ToString;
913
import lombok.experimental.FieldDefaults;
1014

11-
import java.util.LinkedHashSet;
12-
import java.util.Set;
13-
1415
@Getter
1516
@Builder
1617
@ToString
@@ -19,6 +20,7 @@
1920
public class Bm25Argument implements Argument {
2021
String query;
2122
String[] properties;
23+
SearchOperator searchOperator;
2224

2325
@Override
2426
public String build() {
@@ -28,7 +30,34 @@ public String build() {
2830
if (properties != null) {
2931
arg.add(String.format("properties:%s", Serializer.arrayWithQuotes(properties)));
3032
}
33+
if (searchOperator != null) {
34+
arg.add(String.format("searchOperator:%s", searchOperator.build()));
35+
}
3136

3237
return String.format("bm25:{%s}", String.join(" ", arg));
3338
}
39+
40+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
41+
public static class SearchOperator implements Argument {
42+
private static final String OR = "Or";
43+
private static final String AND = "And";
44+
45+
private String operator;
46+
private int minimumMatch;
47+
48+
public static SearchOperator and() {
49+
return new SearchOperator(AND, 0); // minimumMatch ignored for And
50+
}
51+
52+
public static SearchOperator or(int minimumMatch) {
53+
return new SearchOperator(OR, minimumMatch);
54+
}
55+
56+
@Override
57+
public String build() {
58+
// While minimumOrTokensMatch is ignored, it should nevertheless be included
59+
// in the query, otherwise the server refuses to execute it.
60+
return String.format("{operator:%s minimumOrTokensMatch:%s}", operator, minimumMatch);
61+
}
62+
}
3463
}

src/main/java/io/weaviate/client/v1/graphql/query/argument/HybridArgument.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class HybridArgument implements Argument {
2929
String[] targetVectors;
3030
Searches searches;
3131
Targets targets;
32+
Bm25Argument.SearchOperator bm25SearchOperator;
3233

3334
@Override
3435
public String build() {
@@ -63,6 +64,9 @@ public String build() {
6364
}
6465
arg.add(String.format("searches:{%s}", String.join(" ", searchesArgs)));
6566
}
67+
if (bm25SearchOperator != null) {
68+
arg.add(String.format("bm25SearchOperator:%s", bm25SearchOperator.build()));
69+
}
6670
if (targets != null) {
6771
arg.add(String.format("%s", targets.build()));
6872
}
Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package io.weaviate.client.v1.graphql.query.argument;
22

3-
import org.junit.Test;
4-
53
import static org.assertj.core.api.Assertions.assertThat;
64

5+
import org.junit.Test;
6+
77
public class Bm25ArgumentTest {
88

99
@Test
1010
public void shouldCreateArgument() {
1111
Bm25Argument bm25 = Bm25Argument.builder()
12-
.query("I'm a simple string")
13-
.build();
12+
.query("I'm a simple string")
13+
.build();
1414

1515
String str = bm25.build();
1616

@@ -20,26 +20,50 @@ public void shouldCreateArgument() {
2020
@Test
2121
public void shouldCreateArgumentWithProperties() {
2222
Bm25Argument bm25 = Bm25Argument.builder()
23-
.query("I'm a simple string")
24-
.properties(new String[]{"prop1", "prop2"})
25-
.build();
23+
.query("I'm a simple string")
24+
.properties(new String[] { "prop1", "prop2" })
25+
.build();
2626

2727
String str = bm25.build();
2828

2929
assertThat(str).isEqualTo("bm25:{query:\"I'm a simple string\" " +
30-
"properties:[\"prop1\",\"prop2\"]}");
30+
"properties:[\"prop1\",\"prop2\"]}");
31+
}
32+
33+
@Test
34+
public void shouldCreateArgumentWithSearchOperator_And() {
35+
Bm25Argument bm25 = Bm25Argument.builder()
36+
.query("hello")
37+
.searchOperator(Bm25Argument.SearchOperator.and())
38+
.build();
39+
40+
String str = bm25.build();
41+
42+
assertThat(str).isEqualTo("bm25:{query:\"hello\" searchOperator:{operator:And minimumOrTokensMatch:0}}");
43+
}
44+
45+
@Test
46+
public void shouldCreateArgumentWithSearchOperator_Or() {
47+
Bm25Argument bm25 = Bm25Argument.builder()
48+
.query("hello")
49+
.searchOperator(Bm25Argument.SearchOperator.or(2))
50+
.build();
51+
52+
String str = bm25.build();
53+
54+
assertThat(str).isEqualTo("bm25:{query:\"hello\" searchOperator:{operator:Or minimumOrTokensMatch:2}}");
3155
}
3256

3357
@Test
3458
public void shouldCreateArgumentWithChars() {
3559
Bm25Argument bm25 = Bm25Argument.builder()
36-
.query("\"I'm a complex string\" says the {'`:string:`'}")
37-
.properties(new String[]{"prop:\"'`{0}`'\""})
38-
.build();
60+
.query("\"I'm a complex string\" says the {'`:string:`'}")
61+
.properties(new String[] { "prop:\"'`{0}`'\"" })
62+
.build();
3963

4064
String str = bm25.build();
4165

4266
assertThat(str).isEqualTo("bm25:{query:\"\\\"I'm a complex string\\\" says the {'`:string:`'}\" " +
43-
"properties:[\"prop:\\\"'`{0}`'\\\"\"]}");
67+
"properties:[\"prop:\\\"'`{0}`'\\\"\"]}");
4468
}
4569
}

src/test/java/io/weaviate/client/v1/graphql/query/argument/HybridArgumentTest.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,23 @@ public static Object[][] provideTestCases() {
133133
.build())
134134
.build(),
135135
"hybrid:{query:\"ColBERT me if you can!\" searches:{nearVector:{vector:[[1.0,2.0,3.0],[4.0,5.0,6.0]] targetVectors:[\"colbert\"]}}}",
136-
}
136+
},
137+
{
138+
"bm25 search operator And",
139+
HybridArgument.builder()
140+
.query("hello")
141+
.bm25SearchOperator(Bm25Argument.SearchOperator.and())
142+
.build(),
143+
"hybrid:{query:\"hello\" bm25SearchOperator:{operator:And minimumOrTokensMatch:0}}",
144+
},
145+
{
146+
"bm25 search operator Or",
147+
HybridArgument.builder()
148+
.query("hello")
149+
.bm25SearchOperator(Bm25Argument.SearchOperator.or(2))
150+
.build(),
151+
"hybrid:{query:\"hello\" bm25SearchOperator:{operator:Or minimumOrTokensMatch:2}}",
152+
},
137153
};
138154
}
139155

0 commit comments

Comments
 (0)