Skip to content

Commit

Permalink
Add zeroTermsQuery for matchPhraseQuery (#648)
Browse files Browse the repository at this point in the history
Add zeroTermsQuery for matchPhraseQuery
  • Loading branch information
swethakann authored Apr 16, 2024
1 parent 732d655 commit ed29d9f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
9 changes: 9 additions & 0 deletions clientlib/src/main/proto/yelp/nrtsearch/search.proto
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,15 @@ message MatchPhraseQuery {
string query = 2; // The text to query with.
int32 slop = 3; // Edit distance between respective positions of tokens generated by analyzing this query and the positions of terms in a document.
Analyzer analyzer = 4; // Analyzer used to analyze the query. If not provided, the default search analyzer for the field would be used instead.
ZeroTerms zeroTermsQuery = 5; // Indicates whether none or all documents are returned if the analyzer removes all tokens. Valid values are NONE_ZERO_TERMS and ALL_ZERO_TERMS.

// Zero Terms options when analyzer removes all tokens.
enum ZeroTerms {
// No documents are returned if the analyzer removes all tokens.
NONE_ZERO_TERMS = 0;
// All documents are returned if the analyzer removes all tokens.
ALL_ZERO_TERMS = 1;
}
}

// A query that matches documents containing terms in the same order as those in the analyzed query string. The final analyzed token is treated as a prefix
Expand Down
9 changes: 9 additions & 0 deletions docs/queries/match_phrase.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,13 @@ Proto definition:
string query = 2; // The text to query with.
int32 slop = 3; // Edit distance between respective positions of tokens generated by analyzing this query and the positions of terms in a document.
Analyzer analyzer = 4; // Analyzer used to analyze the query. If not provided, the default search analyzer for the field would be used instead.
ZeroTerms zeroTermsQuery = 5; // Indicates whether none or all documents are returned if the analyzer removes all tokens. Valid values are NONE_ZERO_TERMS and ALL_ZERO_TERMS.
// Zero Terms options when analyzer removes all tokens.
enum ZeroTerms {
// No documents are returned if the analyzer removes all tokens.
NONE_ZERO_TERMS = 0;
// All documents are returned if the analyzer removes all tokens.
ALL_ZERO_TERMS = 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,18 @@ private Query getMatchPhraseQuery(MatchPhraseQuery matchPhraseQuery, IndexState

// This can happen if there are no tokens found after analyzing the query text
if (phraseQuery == null) {
return new MatchNoDocsQuery();
MatchPhraseQuery.ZeroTerms zeroTermsQuery = matchPhraseQuery.getZeroTermsQuery();
switch (zeroTermsQuery) {
case NONE_ZERO_TERMS -> {
return new MatchNoDocsQuery();
}
case ALL_ZERO_TERMS -> {
return new MatchAllDocsQuery();
}
default -> throw new IllegalArgumentException(
zeroTermsQuery
+ " not valid. ZeroTermsQuery should be NONE_ZERO_TERMS or ALL_ZERO_TERMS");
}
}
return phraseQuery;
}
Expand Down
42 changes: 42 additions & 0 deletions src/test/java/com/yelp/nrtsearch/server/grpc/QueryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,48 @@ public void testSearchMatchPhraseQueryEmptyAfterAnalysis() {
testQuery(query, responseTester);
}

@Test
public void testSearchMatchPhraseQueryZeroTermsIsNone() {
Query query =
Query.newBuilder()
.setMatchPhraseQuery(
MatchPhraseQuery.newBuilder()
.setField("vendor_name")
.setQuery("/?/ ?//?")
.setSlop(1)
.setZeroTermsQuery(MatchPhraseQuery.ZeroTerms.NONE_ZERO_TERMS))
.build();

Consumer<SearchResponse> responseTester =
searchResponse -> {
assertEquals(0, searchResponse.getTotalHits().getValue());
assertEquals(0, searchResponse.getHitsList().size());
};

testQuery(query, responseTester);
}

@Test
public void testSearchMatchPhraseQueryZeroTermsIsAll() {
Query query =
Query.newBuilder()
.setMatchPhraseQuery(
MatchPhraseQuery.newBuilder()
.setField("vendor_name")
.setQuery("/?/ ?//?")
.setSlop(1)
.setZeroTermsQuery(MatchPhraseQuery.ZeroTerms.ALL_ZERO_TERMS))
.build();

Consumer<SearchResponse> responseTester =
searchResponse -> {
assertEquals(2, searchResponse.getTotalHits().getValue());
assertEquals(2, searchResponse.getHitsList().size());
};

testQuery(query, responseTester);
}

@Test
public void testSearchMatchPhraseQueryCustomAnalyzer() {
Query query =
Expand Down

0 comments on commit ed29d9f

Please sign in to comment.