Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
359cbec
fix: rework search API generics to replace unnecessary type params wi…
viktoriya-kutsarova Apr 7, 2026
742d05b
fix: rework search API generics to replace unnecessary type params wi…
viktoriya-kutsarova Apr 20, 2026
ab79f50
Add verification tests
a-TODO-rov Apr 23, 2026
33343a2
Expand codec verification tests and revert K for field names and INKEYS.
viktoriya-kutsarova Apr 30, 2026
67ba954
Add more verification tests
a-TODO-rov May 8, 2026
6f1ea6d
Add more codec tests ana parametrize them.
viktoriya-kutsarova May 11, 2026
b24c456
Fix prefix issue.
viktoriya-kutsarova May 11, 2026
6508a72
Fix params issue.
viktoriya-kutsarova May 12, 2026
61e9130
Add more tests for search on HASH using codec.
viktoriya-kutsarova May 12, 2026
1d077ab
Remove generics from FieldArgs and update all affected files.
viktoriya-kutsarova Jun 30, 2026
d453d1b
Remove generics from SugGetArgs and update all affected files.
viktoriya-kutsarova Jun 30, 2026
7204b58
Remove generics from ftSugadd, ftSugdel, ftSugget, their params and u…
viktoriya-kutsarova Jul 1, 2026
aac1ff1
Fix RESP2 inability to properly parse scores because they are sent as…
viktoriya-kutsarova Jul 1, 2026
dcc86ef
Remove generics from ftTagvals command and all affected files.
viktoriya-kutsarova Jul 1, 2026
c8e9189
Rework most of the generic fields in CreateArgs apart from the prefix…
viktoriya-kutsarova Jul 1, 2026
3dc3689
Rework SearchArgs to remove K and V and all affected files.
viktoriya-kutsarova Jul 2, 2026
8c1f3fe
Rework AggregateArg to remove generics and all affected files.
viktoriya-kutsarova Jul 2, 2026
38cad1c
Rework HybridArgs to remove generics and fix all affected files.
viktoriya-kutsarova Jul 2, 2026
668dc49
Rework SearchReply and HybridReply to remove K and V generics where n…
viktoriya-kutsarova Jul 3, 2026
ecaa00a
Remove phantom-V leftover from search module files.
viktoriya-kutsarova Jul 10, 2026
335530c
Fix issues with tests.
viktoriya-kutsarova Jul 10, 2026
05ed7d3
Remove generic from withPrefix in CreateArgs and fix all affected files.
viktoriya-kutsarova Jul 21, 2026
52b2946
Update redis-search docs.
viktoriya-kutsarova Jul 21, 2026
41e9aca
Introduce FieldValue to allow for mixed types (vectors and strings) t…
viktoriya-kutsarova Jul 22, 2026
e00e813
Decode FT.HYBRID document keys with the connection codec.
viktoriya-kutsarova Jul 23, 2026
03a3031
Add support for COLLECT reducer
uglide Jul 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ dependency-reduced-pom.xml
*.java-version
*.DS_Store
prDescription.md
.vscode*
.vscode*
.augment
369 changes: 196 additions & 173 deletions docs/user-guide/redis-search.md

Large diffs are not rendered by default.

66 changes: 33 additions & 33 deletions src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public abstract class AbstractRedisAsyncCommands<K, V> implements RedisAclAsyncC
RedisSortedSetAsyncCommands<K, V>, RedisScriptingAsyncCommands<K, V>, RedisServerAsyncCommands<K, V>,
RedisHLLAsyncCommands<K, V>, BaseRedisAsyncCommands<K, V>, RedisTransactionalAsyncCommands<K, V>,
RedisGeoAsyncCommands<K, V>, RedisClusterAsyncCommands<K, V>, RedisJsonAsyncCommands<K, V>,
RedisVectorSetAsyncCommands<K, V>, RediSearchAsyncCommands<K, V>, RedisArrayAsyncCommands<K, V>,
RedisVectorSetAsyncCommands<K, V>, RediSearchAsyncCommands<K>, RedisArrayAsyncCommands<K, V>,
RedisBloomFilterAsyncCommands<K, V>, RedisCuckooFilterAsyncCommands<K, V>, RedisTopKAsyncCommands<K, V> {

private final StatefulConnection<K, V> connection;
Expand Down Expand Up @@ -1684,12 +1684,12 @@ public RedisFuture<String> info(String section) {
}

@Override
public RedisFuture<String> ftCreate(String index, CreateArgs<K, V> options, List<FieldArgs<K>> fieldArgs) {
public RedisFuture<String> ftCreate(String index, CreateArgs options, List<FieldArgs> fieldArgs) {
return dispatch(searchCommandBuilder.ftCreate(index, options, fieldArgs));
}

@Override
public RedisFuture<String> ftCreate(String index, List<FieldArgs<K>> fieldArgs) {
public RedisFuture<String> ftCreate(String index, List<FieldArgs> fieldArgs) {
return dispatch(searchCommandBuilder.ftCreate(index, null, fieldArgs));
}

Expand All @@ -1709,92 +1709,92 @@ public RedisFuture<String> ftAliasdel(String alias) {
}

@Override
public RedisFuture<String> ftAlter(String index, boolean skipInitialScan, List<FieldArgs<K>> fieldArgs) {
public RedisFuture<String> ftAlter(String index, boolean skipInitialScan, List<FieldArgs> fieldArgs) {
return dispatch(searchCommandBuilder.ftAlter(index, skipInitialScan, fieldArgs));
}

@Override
public RedisFuture<List<V>> ftTagvals(String index, String fieldName) {
public RedisFuture<List<String>> ftTagvals(String index, String fieldName) {
return dispatch(searchCommandBuilder.ftTagvals(index, fieldName));
}

@Override
public RedisFuture<SpellCheckResult<V>> ftSpellcheck(String index, V query) {
public RedisFuture<SpellCheckResult> ftSpellcheck(String index, String query) {
return dispatch(searchCommandBuilder.ftSpellcheck(index, query));
}

@Override
public RedisFuture<SpellCheckResult<V>> ftSpellcheck(String index, V query, SpellCheckArgs<K, V> args) {
public RedisFuture<SpellCheckResult> ftSpellcheck(String index, String query, SpellCheckArgs args) {
return dispatch(searchCommandBuilder.ftSpellcheck(index, query, args));
}

@Override
public RedisFuture<Long> ftDictadd(String dict, V... terms) {
public RedisFuture<Long> ftDictadd(String dict, String... terms) {
return dispatch(searchCommandBuilder.ftDictadd(dict, terms));
}

@Override
public RedisFuture<Long> ftDictdel(String dict, V... terms) {
public RedisFuture<Long> ftDictdel(String dict, String... terms) {
return dispatch(searchCommandBuilder.ftDictdel(dict, terms));
}

@Override
public RedisFuture<List<V>> ftDictdump(String dict) {
public RedisFuture<List<String>> ftDictdump(String dict) {
return dispatch(searchCommandBuilder.ftDictdump(dict));
}

@Override
public RedisFuture<String> ftExplain(String index, V query) {
public RedisFuture<String> ftExplain(String index, String query) {
return dispatch(searchCommandBuilder.ftExplain(index, query));
}

@Override
public RedisFuture<String> ftExplain(String index, V query, ExplainArgs<K, V> args) {
public RedisFuture<String> ftExplain(String index, String query, ExplainArgs args) {
return dispatch(searchCommandBuilder.ftExplain(index, query, args));
}

@Override
public RedisFuture<List<V>> ftList() {
public RedisFuture<List<String>> ftList() {
return dispatch(searchCommandBuilder.ftList());
}

@Override
public RedisFuture<Map<V, List<V>>> ftSyndump(String index) {
public RedisFuture<Map<String, List<String>>> ftSyndump(String index) {
return dispatch(searchCommandBuilder.ftSyndump(index));
}

@Override
public RedisFuture<String> ftSynupdate(String index, V synonymGroupId, V... terms) {
public RedisFuture<String> ftSynupdate(String index, String synonymGroupId, String... terms) {
return dispatch(searchCommandBuilder.ftSynupdate(index, synonymGroupId, terms));
}

@Override
public RedisFuture<String> ftSynupdate(String index, V synonymGroupId, SynUpdateArgs<K, V> args, V... terms) {
public RedisFuture<String> ftSynupdate(String index, String synonymGroupId, SynUpdateArgs args, String... terms) {
return dispatch(searchCommandBuilder.ftSynupdate(index, synonymGroupId, args, terms));
}

@Override
public RedisFuture<Long> ftSugadd(K key, V string, double score) {
return dispatch(searchCommandBuilder.ftSugadd(key, string, score));
public RedisFuture<Long> ftSugadd(K key, String suggestion, double score) {
return dispatch(searchCommandBuilder.ftSugadd(key, suggestion, score));
}

@Override
public RedisFuture<Long> ftSugadd(K key, V string, double score, SugAddArgs<K, V> args) {
return dispatch(searchCommandBuilder.ftSugadd(key, string, score, args));
public RedisFuture<Long> ftSugadd(K key, String suggestion, double score, SugAddArgs args) {
return dispatch(searchCommandBuilder.ftSugadd(key, suggestion, score, args));
}

@Override
public RedisFuture<Boolean> ftSugdel(K key, V string) {
return dispatch(searchCommandBuilder.ftSugdel(key, string));
public RedisFuture<Boolean> ftSugdel(K key, String suggestion) {
return dispatch(searchCommandBuilder.ftSugdel(key, suggestion));
}

@Override
public RedisFuture<List<Suggestion<V>>> ftSugget(K key, V prefix) {
public RedisFuture<List<Suggestion>> ftSugget(K key, String prefix) {
return dispatch(searchCommandBuilder.ftSugget(key, prefix));
}

@Override
public RedisFuture<List<Suggestion<V>>> ftSugget(K key, V prefix, SugGetArgs<K, V> args) {
public RedisFuture<List<Suggestion>> ftSugget(K key, String prefix, SugGetArgs args) {
return dispatch(searchCommandBuilder.ftSugget(key, prefix, args));
}

Expand All @@ -1804,7 +1804,7 @@ public RedisFuture<Long> ftSuglen(K key) {
}

@Override
public RedisFuture<String> ftAlter(String index, List<FieldArgs<K>> fieldArgs) {
public RedisFuture<String> ftAlter(String index, List<FieldArgs> fieldArgs) {
return dispatch(searchCommandBuilder.ftAlter(index, false, fieldArgs));
}

Expand All @@ -1819,32 +1819,32 @@ public RedisFuture<String> ftDropindex(String index) {
}

@Override
public RedisFuture<SearchReply<K, V>> ftSearch(String index, V query, SearchArgs<K, V> args) {
public RedisFuture<SearchReply<K>> ftSearch(String index, String query, SearchArgs<K> args) {
return dispatch(searchCommandBuilder.ftSearch(index, query, args));
}

@Override
public RedisFuture<SearchReply<K, V>> ftSearch(String index, V query) {
return dispatch(searchCommandBuilder.ftSearch(index, query, SearchArgs.<K, V> builder().build()));
public RedisFuture<SearchReply<K>> ftSearch(String index, String query) {
return dispatch(searchCommandBuilder.ftSearch(index, query, SearchArgs.<K> builder().build()));
}

@Override
public RedisFuture<HybridReply<K, V>> ftHybrid(String index, HybridArgs<K, V> args) {
public RedisFuture<HybridReply<K>> ftHybrid(String index, HybridArgs args) {
return dispatch(searchCommandBuilder.ftHybrid(index, args));
}

@Override
public RedisFuture<AggregationReply<K, V>> ftAggregate(String index, V query, AggregateArgs<K, V> args) {
public RedisFuture<AggregationReply<K>> ftAggregate(String index, String query, AggregateArgs args) {
return dispatch(searchCommandBuilder.ftAggregate(index, query, args));
}

@Override
public RedisFuture<AggregationReply<K, V>> ftAggregate(String index, V query) {
public RedisFuture<AggregationReply<K>> ftAggregate(String index, String query) {
return dispatch(searchCommandBuilder.ftAggregate(index, query, null));
}

@Override
public RedisFuture<AggregationReply<K, V>> ftCursorread(String index, Cursor cursor, int count) {
public RedisFuture<AggregationReply<K>> ftCursorread(String index, Cursor cursor, int count) {
if (cursor == null) {
throw new IllegalArgumentException("cursor must not be null");
}
Expand All @@ -1853,7 +1853,7 @@ public RedisFuture<AggregationReply<K, V>> ftCursorread(String index, Cursor cur
}

@Override
public RedisFuture<AggregationReply<K, V>> ftCursorread(String index, Cursor cursor) {
public RedisFuture<AggregationReply<K>> ftCursorread(String index, Cursor cursor) {
return ftCursorread(index, cursor, -1);
}

Expand Down
66 changes: 33 additions & 33 deletions src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public abstract class AbstractRedisReactiveCommands<K, V>
RedisSortedSetReactiveCommands<K, V>, RedisScriptingReactiveCommands<K, V>, RedisServerReactiveCommands<K, V>,
RedisHLLReactiveCommands<K, V>, BaseRedisReactiveCommands<K, V>, RedisTransactionalReactiveCommands<K, V>,
RedisGeoReactiveCommands<K, V>, RedisClusterReactiveCommands<K, V>, RedisJsonReactiveCommands<K, V>,
RedisVectorSetReactiveCommands<K, V>, RediSearchReactiveCommands<K, V>, RedisArrayReactiveCommands<K, V>,
RedisVectorSetReactiveCommands<K, V>, RediSearchReactiveCommands<K>, RedisArrayReactiveCommands<K, V>,
RedisBloomFilterReactiveCommands<K, V>, RedisCuckooFilterReactiveCommands<K, V>, RedisTopKReactiveCommands<K, V> {

private final StatefulConnection<K, V> connection;
Expand Down Expand Up @@ -1770,12 +1770,12 @@ public Mono<String> info(String section) {
}

@Override
public Mono<String> ftCreate(String index, CreateArgs<K, V> options, List<FieldArgs<K>> fieldArgs) {
public Mono<String> ftCreate(String index, CreateArgs options, List<FieldArgs> fieldArgs) {
return createMono(() -> searchCommandBuilder.ftCreate(index, options, fieldArgs));
}

@Override
public Mono<String> ftCreate(String index, List<FieldArgs<K>> fieldArgs) {
public Mono<String> ftCreate(String index, List<FieldArgs> fieldArgs) {
return createMono(() -> searchCommandBuilder.ftCreate(index, null, fieldArgs));
}

Expand All @@ -1795,92 +1795,92 @@ public Mono<String> ftAliasdel(String alias) {
}

@Override
public Mono<String> ftAlter(String index, boolean skipInitialScan, List<FieldArgs<K>> fieldArgs) {
public Mono<String> ftAlter(String index, boolean skipInitialScan, List<FieldArgs> fieldArgs) {
return createMono(() -> searchCommandBuilder.ftAlter(index, skipInitialScan, fieldArgs));
}

@Override
public Flux<V> ftTagvals(String index, String fieldName) {
public Flux<String> ftTagvals(String index, String fieldName) {
return createDissolvingFlux(() -> searchCommandBuilder.ftTagvals(index, fieldName));
}

@Override
public Mono<SpellCheckResult<V>> ftSpellcheck(String index, V query) {
public Mono<SpellCheckResult> ftSpellcheck(String index, String query) {
return createMono(() -> searchCommandBuilder.ftSpellcheck(index, query));
}

@Override
public Mono<SpellCheckResult<V>> ftSpellcheck(String index, V query, SpellCheckArgs<K, V> args) {
public Mono<SpellCheckResult> ftSpellcheck(String index, String query, SpellCheckArgs args) {
return createMono(() -> searchCommandBuilder.ftSpellcheck(index, query, args));
}

@Override
public Mono<Long> ftDictadd(String dict, V... terms) {
public Mono<Long> ftDictadd(String dict, String... terms) {
return createMono(() -> searchCommandBuilder.ftDictadd(dict, terms));
}

@Override
public Mono<Long> ftDictdel(String dict, V... terms) {
public Mono<Long> ftDictdel(String dict, String... terms) {
return createMono(() -> searchCommandBuilder.ftDictdel(dict, terms));
}

@Override
public Flux<V> ftDictdump(String dict) {
public Flux<String> ftDictdump(String dict) {
return createDissolvingFlux(() -> searchCommandBuilder.ftDictdump(dict));
}

@Override
public Mono<String> ftExplain(String index, V query) {
public Mono<String> ftExplain(String index, String query) {
return createMono(() -> searchCommandBuilder.ftExplain(index, query));
}

@Override
public Mono<String> ftExplain(String index, V query, ExplainArgs<K, V> args) {
public Mono<String> ftExplain(String index, String query, ExplainArgs args) {
return createMono(() -> searchCommandBuilder.ftExplain(index, query, args));
}

@Override
public Flux<V> ftList() {
public Flux<String> ftList() {
return createDissolvingFlux(() -> searchCommandBuilder.ftList());
}

@Override
public Mono<Map<V, List<V>>> ftSyndump(String index) {
public Mono<Map<String, List<String>>> ftSyndump(String index) {
return createMono(() -> searchCommandBuilder.ftSyndump(index));
}

@Override
public Mono<String> ftSynupdate(String index, V synonymGroupId, V... terms) {
public Mono<String> ftSynupdate(String index, String synonymGroupId, String... terms) {
return createMono(() -> searchCommandBuilder.ftSynupdate(index, synonymGroupId, terms));
}

@Override
public Mono<String> ftSynupdate(String index, V synonymGroupId, SynUpdateArgs<K, V> args, V... terms) {
public Mono<String> ftSynupdate(String index, String synonymGroupId, SynUpdateArgs args, String... terms) {
return createMono(() -> searchCommandBuilder.ftSynupdate(index, synonymGroupId, args, terms));
}

@Override
public Mono<Long> ftSugadd(K key, V string, double score) {
return createMono(() -> searchCommandBuilder.ftSugadd(key, string, score));
public Mono<Long> ftSugadd(K key, String suggestion, double score) {
return createMono(() -> searchCommandBuilder.ftSugadd(key, suggestion, score));
}

@Override
public Mono<Long> ftSugadd(K key, V string, double score, SugAddArgs<K, V> args) {
return createMono(() -> searchCommandBuilder.ftSugadd(key, string, score, args));
public Mono<Long> ftSugadd(K key, String suggestion, double score, SugAddArgs args) {
return createMono(() -> searchCommandBuilder.ftSugadd(key, suggestion, score, args));
}

@Override
public Mono<Boolean> ftSugdel(K key, V string) {
return createMono(() -> searchCommandBuilder.ftSugdel(key, string));
public Mono<Boolean> ftSugdel(K key, String suggestion) {
return createMono(() -> searchCommandBuilder.ftSugdel(key, suggestion));
}

@Override
public Flux<Suggestion<V>> ftSugget(K key, V prefix) {
public Flux<Suggestion> ftSugget(K key, String prefix) {
return createDissolvingFlux(() -> searchCommandBuilder.ftSugget(key, prefix));
}

@Override
public Flux<Suggestion<V>> ftSugget(K key, V prefix, SugGetArgs<K, V> args) {
public Flux<Suggestion> ftSugget(K key, String prefix, SugGetArgs args) {
return createDissolvingFlux(() -> searchCommandBuilder.ftSugget(key, prefix, args));
}

Expand All @@ -1890,7 +1890,7 @@ public Mono<Long> ftSuglen(K key) {
}

@Override
public Mono<String> ftAlter(String index, List<FieldArgs<K>> fieldArgs) {
public Mono<String> ftAlter(String index, List<FieldArgs> fieldArgs) {
return createMono(() -> searchCommandBuilder.ftAlter(index, false, fieldArgs));
}

Expand All @@ -1916,32 +1916,32 @@ public Mono<String> ftDropindex(String index) {
}

@Override
public Mono<SearchReply<K, V>> ftSearch(String index, V query, SearchArgs<K, V> args) {
public Mono<SearchReply<K>> ftSearch(String index, String query, SearchArgs<K> args) {
return createMono(() -> searchCommandBuilder.ftSearch(index, query, args));
}

@Override
public Mono<SearchReply<K, V>> ftSearch(String index, V query) {
return createMono(() -> searchCommandBuilder.ftSearch(index, query, SearchArgs.<K, V> builder().build()));
public Mono<SearchReply<K>> ftSearch(String index, String query) {
return createMono(() -> searchCommandBuilder.ftSearch(index, query, SearchArgs.<K> builder().build()));
}

@Override
public Mono<HybridReply<K, V>> ftHybrid(String index, HybridArgs<K, V> args) {
public Mono<HybridReply<K>> ftHybrid(String index, HybridArgs args) {
return createMono(() -> searchCommandBuilder.ftHybrid(index, args));
}

@Override
public Mono<AggregationReply<K, V>> ftAggregate(String index, V query, AggregateArgs<K, V> args) {
public Mono<AggregationReply<K>> ftAggregate(String index, String query, AggregateArgs args) {
return createMono(() -> searchCommandBuilder.ftAggregate(index, query, args));
}

@Override
public Mono<AggregationReply<K, V>> ftAggregate(String index, V query) {
public Mono<AggregationReply<K>> ftAggregate(String index, String query) {
return createMono(() -> searchCommandBuilder.ftAggregate(index, query, null));
}

@Override
public Mono<AggregationReply<K, V>> ftCursorread(String index, Cursor cursor, int count) {
public Mono<AggregationReply<K>> ftCursorread(String index, Cursor cursor, int count) {
return createMono(() -> {
if (cursor == null) {
throw new IllegalArgumentException("cursor must not be null");
Expand All @@ -1952,7 +1952,7 @@ public Mono<AggregationReply<K, V>> ftCursorread(String index, Cursor cursor, in
}

@Override
public Mono<AggregationReply<K, V>> ftCursorread(String index, Cursor cursor) {
public Mono<AggregationReply<K>> ftCursorread(String index, Cursor cursor) {
return ftCursorread(index, cursor, -1);
}

Expand Down
Loading