Skip to content

Commit 1b6eb95

Browse files
committed
fix(autocomplete): use Tuple.getElement() for payload lookup in autocomplete (#673)
When both withScore() and withPayload() options are enabled, the code incorrectly passed the Tuple object directly to the hash lookup instead of extracting the string element first. This caused a ClassCastException: "class redis.clients.jedis.resps.Tuple cannot be cast to class java.lang.String" Closes #673
1 parent 810a2f1 commit 1b6eb95

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public List<Suggestion> getSuggestion(String key, String prefix, AutoCompleteOpt
135135
String[] keyParts = key.split(":");
136136
String payLoadKey = String.format("sugg:payload:%s:%s", keyParts[keyParts.length - 2],
137137
keyParts[keyParts.length - 1]);
138-
Object payload = template.opsForHash().get(payLoadKey, suggestion);
138+
Object payload = template.opsForHash().get(payLoadKey, suggestion.getElement());
139139
String json = payload != null ? payload.toString() : "{}";
140140
Map<String, Object> payloadMap = gson.fromJson(json, new TypeToken<Map<String, Object>>() {
141141
}.getType());

tests/src/test/java/com/redis/om/spring/annotations/autocompletable/AutoCompleteTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,33 @@ void testGetAutocompleteSuggestionsWithScores() {
9898
0.27));
9999
}
100100

101+
/**
102+
* Test for Issue #673: ClassCastException when using withScore() and withPayload() together.
103+
*
104+
* When both options are enabled, the code incorrectly passes the Tuple object
105+
* (instead of its string element) to the hash lookup for payload retrieval.
106+
*
107+
* @see <a href="https://github.com/redis/redis-om-spring/issues/673">Issue #673</a>
108+
*/
109+
@Test
110+
void testGetAutocompleteSuggestionsWithScoresAndPayload() {
111+
Map<String, Object> columbusPayload = Map.of("code", "CMH", "state", "OH");
112+
Map<String, Object> columbiaPayload = Map.of("code", "CAE", "state", "SC");
113+
Map<String, Object> coloradoSpringsPayload = Map.of("code", "COS", "state", "CO");
114+
115+
// This combination caused ClassCastException before the fix:
116+
// "class redis.clients.jedis.resps.Tuple cannot be cast to class java.lang.String"
117+
List<Suggestion> suggestions = repository.autoCompleteName("col",
118+
AutoCompleteOptions.get().withScore().withPayload());
119+
120+
List<String> suggestionsString = suggestions.stream().map(Suggestion::getValue).collect(Collectors.toList());
121+
List<Double> scores = suggestions.stream().map(Suggestion::getScore).collect(Collectors.toList());
122+
List<Map<String, Object>> payloads = suggestions.stream().map(Suggestion::getPayload).collect(Collectors.toList());
123+
124+
assertThat(suggestionsString).containsAll(List.of("Columbia", "Columbus", "Colorado Springs"));
125+
assertThat(scores).usingComparatorForType(new DoubleComparator(0.1), Double.class).containsAll(List.of(0.41, 0.41,
126+
0.27));
127+
assertThat(payloads).hasSize(3).contains(columbusPayload, columbiaPayload, coloradoSpringsPayload);
128+
}
129+
101130
}

0 commit comments

Comments
 (0)