From c97f2e9983de79b5cfee163d21132a7addc8ff4b Mon Sep 17 00:00:00 2001 From: Tihomir Mateev Date: Tue, 4 Feb 2025 13:03:40 +0100 Subject: [PATCH] Revert "Add support for FT.CREATE #2717 (#3150)" This reverts commit 636a503baa5afea716944030561e2f2fe5875da8. --- .../core/AbstractRedisAsyncCommands.java | 13 +- .../core/AbstractRedisReactiveCommands.java | 22 +- .../core/RediSearchCommandBuilder.java | 63 -- .../api/async/RediSearchAsyncCommands.java | 38 -- .../core/api/async/RedisAsyncCommands.java | 2 +- .../reactive/RediSearchReactiveCommands.java | 38 -- .../api/reactive/RedisReactiveCommands.java | 13 +- .../core/api/sync/RediSearchCommands.java | 37 -- .../lettuce/core/api/sync/RedisCommands.java | 2 +- .../api/async/RediSearchAsyncCommands.java | 37 -- .../cluster/api/sync/RediSearchCommands.java | 37 -- .../api/sync/RedisClusterCommands.java | 1 - .../lettuce/core/protocol/CommandKeyword.java | 6 +- .../io/lettuce/core/protocol/CommandType.java | 3 - .../lettuce/core/search/DocumentLanguage.java | 144 ----- .../java/io/lettuce/core/search/Field.java | 522 ----------------- .../core/search/arguments/CreateArgs.java | 537 ------------------ .../io/lettuce/core/search/package-info.java | 10 - .../RediSearchCoroutinesCommands.kt | 41 -- .../lettuce/core/api/RediSearchCommands.java | 37 -- .../io/lettuce/apigenerator/Constants.java | 2 +- .../RediSearchCommandBuilderUnitTests.java | 92 --- .../core/json/RediSearchIntegrationTests.java | 84 --- 23 files changed, 17 insertions(+), 1764 deletions(-) delete mode 100644 src/main/java/io/lettuce/core/RediSearchCommandBuilder.java delete mode 100644 src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java delete mode 100644 src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java delete mode 100644 src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java delete mode 100644 src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java delete mode 100644 src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java delete mode 100644 src/main/java/io/lettuce/core/search/DocumentLanguage.java delete mode 100644 src/main/java/io/lettuce/core/search/Field.java delete mode 100644 src/main/java/io/lettuce/core/search/arguments/CreateArgs.java delete mode 100644 src/main/java/io/lettuce/core/search/package-info.java delete mode 100644 src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt delete mode 100644 src/main/templates/io/lettuce/core/api/RediSearchCommands.java delete mode 100644 src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java delete mode 100644 src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java diff --git a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java index 1a8994d28d..de095893fa 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java @@ -48,8 +48,6 @@ import io.lettuce.core.protocol.CommandType; import io.lettuce.core.protocol.ProtocolKeyword; import io.lettuce.core.protocol.RedisCommand; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; import reactor.core.publisher.Mono; import java.time.Duration; @@ -81,8 +79,7 @@ public abstract class AbstractRedisAsyncCommands implements RedisAclAsyncC RedisKeyAsyncCommands, RedisStringAsyncCommands, RedisListAsyncCommands, RedisSetAsyncCommands, RedisSortedSetAsyncCommands, RedisScriptingAsyncCommands, RedisServerAsyncCommands, RedisHLLAsyncCommands, BaseRedisAsyncCommands, RedisTransactionalAsyncCommands, - RedisGeoAsyncCommands, RedisClusterAsyncCommands, RedisJsonAsyncCommands, - RediSearchAsyncCommands { + RedisGeoAsyncCommands, RedisClusterAsyncCommands, RedisJsonAsyncCommands { private final StatefulConnection connection; @@ -90,8 +87,6 @@ public abstract class AbstractRedisAsyncCommands implements RedisAclAsyncC private final RedisJsonCommandBuilder jsonCommandBuilder; - private final RediSearchCommandBuilder searchCommandBuilder; - private final Mono parser; /** @@ -106,7 +101,6 @@ public AbstractRedisAsyncCommands(StatefulConnection connection, RedisCode this.connection = connection; this.commandBuilder = new RedisCommandBuilder<>(codec); this.jsonCommandBuilder = new RedisJsonCommandBuilder<>(codec, parser); - this.searchCommandBuilder = new RediSearchCommandBuilder<>(codec); } /** @@ -1484,11 +1478,6 @@ public boolean isOpen() { return connection.isOpen(); } - @Override - public RedisFuture ftCreate(K index, CreateArgs options, List> fields) { - return dispatch(searchCommandBuilder.ftCreate(index, options, fields)); - } - @Override public RedisFuture> jsonArrappend(K key, JsonPath jsonPath, JsonValue... values) { return dispatch(jsonCommandBuilder.jsonArrappend(key, jsonPath, values)); diff --git a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java index 02f37afd4d..1e9365821f 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java @@ -49,8 +49,6 @@ import io.lettuce.core.protocol.RedisCommand; import io.lettuce.core.protocol.TracedCommand; import io.lettuce.core.resource.ClientResources; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; import io.lettuce.core.tracing.TraceContext; import io.lettuce.core.tracing.TraceContextProvider; import io.lettuce.core.tracing.Tracing; @@ -86,12 +84,12 @@ * @author Tihomir Mateev * @since 4.0 */ -public abstract class AbstractRedisReactiveCommands implements RedisAclReactiveCommands, - RedisHashReactiveCommands, RedisKeyReactiveCommands, RedisStringReactiveCommands, - RedisListReactiveCommands, RedisSetReactiveCommands, RedisSortedSetReactiveCommands, - RedisScriptingReactiveCommands, RedisServerReactiveCommands, RedisHLLReactiveCommands, - BaseRedisReactiveCommands, RedisTransactionalReactiveCommands, RedisGeoReactiveCommands, - RedisClusterReactiveCommands, RedisJsonReactiveCommands, RediSearchReactiveCommands { +public abstract class AbstractRedisReactiveCommands + implements RedisAclReactiveCommands, RedisHashReactiveCommands, RedisKeyReactiveCommands, + RedisStringReactiveCommands, RedisListReactiveCommands, RedisSetReactiveCommands, + RedisSortedSetReactiveCommands, RedisScriptingReactiveCommands, RedisServerReactiveCommands, + RedisHLLReactiveCommands, BaseRedisReactiveCommands, RedisTransactionalReactiveCommands, + RedisGeoReactiveCommands, RedisClusterReactiveCommands, RedisJsonReactiveCommands { private final StatefulConnection connection; @@ -99,8 +97,6 @@ public abstract class AbstractRedisReactiveCommands implements RedisAclRea private final RedisJsonCommandBuilder jsonCommandBuilder; - private final RediSearchCommandBuilder searchCommandBuilder; - private final Mono parser; private final ClientResources clientResources; @@ -121,7 +117,6 @@ public AbstractRedisReactiveCommands(StatefulConnection connection, RedisC this.parser = parser; this.commandBuilder = new RedisCommandBuilder<>(codec); this.jsonCommandBuilder = new RedisJsonCommandBuilder<>(codec, parser); - this.searchCommandBuilder = new RediSearchCommandBuilder<>(codec); this.clientResources = connection.getResources(); this.tracingEnabled = clientResources.tracing().isEnabled(); } @@ -1548,11 +1543,6 @@ public boolean isOpen() { return connection.isOpen(); } - @Override - public Mono ftCreate(K index, CreateArgs options, List> fields) { - return createMono(() -> searchCommandBuilder.ftCreate(index, options, fields)); - } - @Override public Flux jsonArrappend(K key, JsonPath jsonPath, JsonValue... values) { return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, jsonPath, values)); diff --git a/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java b/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java deleted file mode 100644 index 1f8f25d303..0000000000 --- a/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core; - -import io.lettuce.core.codec.RedisCodec; -import io.lettuce.core.output.StatusOutput; -import io.lettuce.core.protocol.BaseRedisCommandBuilder; -import io.lettuce.core.protocol.Command; -import io.lettuce.core.protocol.CommandArgs; -import io.lettuce.core.protocol.CommandKeyword; -import io.lettuce.core.search.arguments.CreateArgs; -import io.lettuce.core.search.Field; - -import java.util.List; - -import static io.lettuce.core.protocol.CommandType.*; - -/** - * Command builder for RediSearch commands. - * - * @param Key type. - * @param Value type. - * @since 6.6 - */ -class RediSearchCommandBuilder extends BaseRedisCommandBuilder { - - RediSearchCommandBuilder(RedisCodec codec) { - super(codec); - } - - /** - * Create a new index with the given name, index options and fields. - * - * @param index the index name - * @param createArgs the index options - * @param fields the fields - * @return the result of the create command - */ - public Command ftCreate(K index, CreateArgs createArgs, List> fields) { - notNullKey(index); - notEmpty(fields.toArray()); - - CommandArgs args = new CommandArgs<>(codec).addKey(index); - - if (createArgs != null) { - createArgs.build(args); - } - - args.add(CommandKeyword.SCHEMA); - - for (Field field : fields) { - field.build(args); - } - - return createCommand(FT_CREATE, new StatusOutput<>(codec), args); - - } - -} diff --git a/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java b/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java deleted file mode 100644 index 7b549160cb..0000000000 --- a/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.api.async; - -import java.util.List; -import io.lettuce.core.RedisFuture; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; - -/** - * Asynchronous executed commands for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - * @generated by io.lettuce.apigenerator.CreateAsyncApi - */ -public interface RediSearchAsyncCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index {@link CreateArgs} - * @param fields the {@link Field}s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - RedisFuture ftCreate(K index, CreateArgs options, List> fields); - -} diff --git a/src/main/java/io/lettuce/core/api/async/RedisAsyncCommands.java b/src/main/java/io/lettuce/core/api/async/RedisAsyncCommands.java index 5689de96f5..6ff3ef9ad1 100644 --- a/src/main/java/io/lettuce/core/api/async/RedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/api/async/RedisAsyncCommands.java @@ -37,7 +37,7 @@ public interface RedisAsyncCommands extends BaseRedisAsyncCommands, RedisHashAsyncCommands, RedisHLLAsyncCommands, RedisKeyAsyncCommands, RedisListAsyncCommands, RedisScriptingAsyncCommands, RedisServerAsyncCommands, RedisSetAsyncCommands, RedisSortedSetAsyncCommands, RedisStreamAsyncCommands, RedisStringAsyncCommands, - RedisTransactionalAsyncCommands, RedisJsonAsyncCommands, RediSearchAsyncCommands { + RedisTransactionalAsyncCommands, RedisJsonAsyncCommands { /** * Authenticate to the server. diff --git a/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java b/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java deleted file mode 100644 index ba2268cca3..0000000000 --- a/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.api.reactive; - -import java.util.List; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; -import reactor.core.publisher.Mono; - -/** - * Reactive executed commands for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - * @generated by io.lettuce.apigenerator.CreateReactiveApi - */ -public interface RediSearchReactiveCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index {@link CreateArgs} - * @param fields the {@link Field}s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - Mono ftCreate(K index, CreateArgs options, List> fields); - -} diff --git a/src/main/java/io/lettuce/core/api/reactive/RedisReactiveCommands.java b/src/main/java/io/lettuce/core/api/reactive/RedisReactiveCommands.java index 76d24ddf10..2f75efcc92 100644 --- a/src/main/java/io/lettuce/core/api/reactive/RedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/api/reactive/RedisReactiveCommands.java @@ -31,13 +31,12 @@ * @author Mark Paluch * @since 5.0 */ -public interface RedisReactiveCommands - extends BaseRedisReactiveCommands, RedisAclReactiveCommands, RedisClusterReactiveCommands, - RedisFunctionReactiveCommands, RedisGeoReactiveCommands, RedisHashReactiveCommands, - RedisHLLReactiveCommands, RedisKeyReactiveCommands, RedisListReactiveCommands, - RedisScriptingReactiveCommands, RedisServerReactiveCommands, RedisSetReactiveCommands, - RedisSortedSetReactiveCommands, RedisStreamReactiveCommands, RedisStringReactiveCommands, - RedisTransactionalReactiveCommands, RedisJsonReactiveCommands, RediSearchReactiveCommands { +public interface RedisReactiveCommands extends BaseRedisReactiveCommands, RedisAclReactiveCommands, + RedisClusterReactiveCommands, RedisFunctionReactiveCommands, RedisGeoReactiveCommands, + RedisHashReactiveCommands, RedisHLLReactiveCommands, RedisKeyReactiveCommands, + RedisListReactiveCommands, RedisScriptingReactiveCommands, RedisServerReactiveCommands, + RedisSetReactiveCommands, RedisSortedSetReactiveCommands, RedisStreamReactiveCommands, + RedisStringReactiveCommands, RedisTransactionalReactiveCommands, RedisJsonReactiveCommands { /** * Authenticate to the server. diff --git a/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java b/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java deleted file mode 100644 index c76f9867e6..0000000000 --- a/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.api.sync; - -import java.util.List; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; - -/** - * Synchronous executed commands for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - * @generated by io.lettuce.apigenerator.CreateSyncApi - */ -public interface RediSearchCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index {@link CreateArgs} - * @param fields the {@link Field}s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - String ftCreate(K index, CreateArgs options, List> fields); - -} diff --git a/src/main/java/io/lettuce/core/api/sync/RedisCommands.java b/src/main/java/io/lettuce/core/api/sync/RedisCommands.java index e7f74d5378..98f21b4cb2 100644 --- a/src/main/java/io/lettuce/core/api/sync/RedisCommands.java +++ b/src/main/java/io/lettuce/core/api/sync/RedisCommands.java @@ -36,7 +36,7 @@ public interface RedisCommands extends BaseRedisCommands, RedisAclCo RedisFunctionCommands, RedisGeoCommands, RedisHashCommands, RedisHLLCommands, RedisKeyCommands, RedisListCommands, RedisScriptingCommands, RedisServerCommands, RedisSetCommands, RedisSortedSetCommands, RedisStreamCommands, RedisStringCommands, - RedisTransactionalCommands, RedisJsonCommands, RediSearchCommands { + RedisTransactionalCommands, RedisJsonCommands { /** * Authenticate to the server. diff --git a/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java b/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java deleted file mode 100644 index d9fb189253..0000000000 --- a/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.cluster.api.async; - -import java.util.List; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; - -/** - * Asynchronous executed commands on a node selection for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - * @generated by io.lettuce.apigenerator.CreateAsyncNodeSelectionClusterApi - */ -public interface RediSearchAsyncCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index {@link CreateArgs} - * @param fields the {@link Field}s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - AsyncExecutions ftCreate(K index, CreateArgs options, List> fields); - -} diff --git a/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java b/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java deleted file mode 100644 index 00cbc7b8bc..0000000000 --- a/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.cluster.api.sync; - -import java.util.List; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; - -/** - * Synchronous executed commands on a node selection for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - * @generated by io.lettuce.apigenerator.CreateSyncNodeSelectionClusterApi - */ -public interface RediSearchCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index {@link CreateArgs} - * @param fields the {@link Field}s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - Executions ftCreate(K index, CreateArgs options, List> fields); - -} diff --git a/src/main/java/io/lettuce/core/cluster/api/sync/RedisClusterCommands.java b/src/main/java/io/lettuce/core/cluster/api/sync/RedisClusterCommands.java index d66093759f..988975740c 100644 --- a/src/main/java/io/lettuce/core/cluster/api/sync/RedisClusterCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/sync/RedisClusterCommands.java @@ -34,7 +34,6 @@ * @param Value type. * @author Mark Paluch * @author dengliming - * @author Tihomir Mateev * @since 4.0 */ public interface RedisClusterCommands diff --git a/src/main/java/io/lettuce/core/protocol/CommandKeyword.java b/src/main/java/io/lettuce/core/protocol/CommandKeyword.java index 62c6e84cd0..c9d782afd8 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandKeyword.java +++ b/src/main/java/io/lettuce/core/protocol/CommandKeyword.java @@ -49,11 +49,7 @@ public enum CommandKeyword implements ProtocolKeyword { MIGRATING, IMPORTING, SAVE, SKIPME, SLAVES, STREAM, STORE, SUM, SEGFAULT, SETUSER, TAKEOVER, TRACKING, TRACKINGINFO, TYPE, UNBLOCK, USERS, USAGE, WEIGHTS, WHOAMI, - WITHMATCHLEN, WITHSCORE, WITHSCORES, WITHVALUES, XOR, XX, YES, INDENT, NEWLINE, SPACE, GT, LT, - - MAXTEXTFIELDS, PREFIX, FILTER, LANGUAGE, LANGUAGE_FIELD, SCORE, SCORE_FIELD, PAYLOAD_FIELD, TEMPORARY, NOOFFSETS, NOHL, NOFIELDS, NOFREQS, SKIPINITIALSCAN, STOPWORDS, AS, SORTABLE, SCHEMA, UNF, NOINDEX, - - NOSTEM, PHONETIC, WEIGHT, SEPARATOR, CASESENSITIVE, WITHSUFFIXTRIE, INDEXEMPTY, INDEXMISSING; + WITHMATCHLEN, WITHSCORE, WITHSCORES, WITHVALUES, XOR, XX, YES, INDENT, NEWLINE, SPACE, GT, LT; public final byte[] bytes; diff --git a/src/main/java/io/lettuce/core/protocol/CommandType.java b/src/main/java/io/lettuce/core/protocol/CommandType.java index 3d5b9f4e9d..9a2fcf83f6 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandType.java +++ b/src/main/java/io/lettuce/core/protocol/CommandType.java @@ -112,9 +112,6 @@ public enum CommandType implements ProtocolKeyword { "JSON.OBJLEN"), JSON_SET("JSON.SET"), JSON_STRAPPEND("JSON.STRAPPEND"), JSON_STRLEN( "JSON.STRLEN"), JSON_TOGGLE("JSON.TOGGLE"), JSON_TYPE("JSON.TYPE"), - // RediSearch - FT_CREATE("FT.CREATE"), - // Others TIME, WAIT, diff --git a/src/main/java/io/lettuce/core/search/DocumentLanguage.java b/src/main/java/io/lettuce/core/search/DocumentLanguage.java deleted file mode 100644 index ba3dd1d161..0000000000 --- a/src/main/java/io/lettuce/core/search/DocumentLanguage.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.search; - -import java.util.Locale; - -/** - * Supported document languages. - * - * @since 6.6 - * @author Tihomir Mateev - * @see Stemming - */ -public enum DocumentLanguage { - - /** - * Arabic - */ - ARABIC("arabic", new Locale("ar")), - /** - * Armenian - */ - ARMENIAN("armenian", new Locale("hy")), - /** - * Danish - */ - DANISH("danish", new Locale("da")), - /** - * Dutch - */ - DUTCH("dutch", new Locale("nl")), - /** - * English - */ - ENGLISH("english", Locale.ENGLISH), - /** - * Finnish - */ - FINNISH("finnish", new Locale("fi")), - /** - * French - */ - FRENCH("french", Locale.FRENCH), - /** - * German - */ - GERMAN("german", Locale.GERMAN), - /** - * Hungarian - */ - HUNGARIAN("hungarian", new Locale("hu")), - /** - * Italian - */ - ITALIAN("italian", Locale.ITALIAN), - /** - * Norwegian - */ - NORWEGIAN("norwegian", new Locale("no")), - /** - * Portuguese - */ - PORTUGUESE("portuguese", new Locale("pt")), - /** - * Romanian - */ - ROMANIAN("romanian", new Locale("ro")), - /** - * Russian - */ - RUSSIAN("russian", new Locale("ru")), - /** - * Serbian - */ - SERBIAN("serbian", new Locale("sr")), - /** - * Spanish - */ - SPANISH("spanish", new Locale("es")), - /** - * Swedish - */ - SWEDISH("swedish", new Locale("sv")), - /** - * Tamil - */ - TAMIL("tamil", new Locale("ta")), - /** - * Turkish - */ - TURKISH("turkish", new Locale("tr")), - /** - * Yiddish - */ - YIDDISH("yiddish", new Locale("yi")), - /** - * Chinese - * - * @see Chinese - * support - */ - CHINESE("chinese", Locale.CHINESE); - - private final String language; - - private final Locale locale; - - DocumentLanguage(String language, Locale locale) { - this.language = language; - this.locale = locale; - } - - @Override - public String toString() { - return language; - } - - /** - * @return the {@link DocumentLanguage} as a {@link Locale} - */ - public Locale getLocale() { - return locale; - } - - /** - * Retrieve the {@link DocumentLanguage} for a given {@link Locale}. - * - * @param locale the locale - * @return the {@link DocumentLanguage} - */ - public static DocumentLanguage getLanguage(Locale locale) { - for (DocumentLanguage language : DocumentLanguage.values()) { - if (language.getLocale().getLanguage().equals(locale.getLanguage())) { - return language; - } - } - throw new UnsupportedOperationException("No language found for locale: " + locale); - } - -} diff --git a/src/main/java/io/lettuce/core/search/Field.java b/src/main/java/io/lettuce/core/search/Field.java deleted file mode 100644 index 51049936d0..0000000000 --- a/src/main/java/io/lettuce/core/search/Field.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.search; - -import io.lettuce.core.protocol.CommandArgs; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import static io.lettuce.core.protocol.CommandKeyword.*; - -/** - * Representation of a field in a RediSearch index. - * - * @param Key type - * @see Field - * and type options - * @since 6.6 - * @author Tihomir Mateev - */ -@SuppressWarnings("OptionalUsedAsFieldOrParameterType") -public class Field { - - /** - * Field types - * - * @see Field and - * type options - */ - public enum Type { - /** - * Allows full-text search queries against the value in this attribute. - */ - TEXT, - /** - * Allows exact-match queries, 1 as categories or primary keys, against the value in this attribute. - * - * @see Tag Fields - */ - TAG, - /** - * Allows numeric range queries against the value in this attribute. See query syntax docs for details on how to use - * numeric ranges. - */ - NUMERIC, - /** - * Allows radius range queries against the value (point) in this attribute. The value of the attribute must be a string - * containing a longitude (first) and latitude separated by a comma. - */ - GEO, - /** - * Allows vector queries against the value in this attribute. Requires query dialect 2 or above (introduced in - * RediSearch v2.4). - * - * @see Vector - * Fields - * @see Query - * Dialect v2 - */ - VECTOR, - /** - * Allows polygon queries against the value in this attribute. The value of the attribute must follow a - * WKT notation list of 2D points - * representing the polygon edges POLYGON((x1 y1, x2 y2, ...) separated by a comma. - *

- * A GEOSHAPE field type can be followed by one of the following coordinate systems: - *

    - *
  • SPHERICAL for Geographic longitude and latitude coordinates
  • - *
  • FLAT for Cartesian X Y coordinates
  • - *
  • The default coordinate system is SPHERICAL.
  • - *
- * - * Currently GEOSHAPE doesn't support JSON multi-value and SORTABLE option. - */ - GEOSHAPE - } - - /** - * Phonetic matchers - * - * @see Phonetic - * Matching - */ - public enum PhoneticMatcher { - - ENGLISH("dm:en"), FRENCH("dm:fr"), PORTUGUESE("dm:pt"), SPANISH("dm:es"); - - PhoneticMatcher(String matcher) { - this.matcher = matcher; - } - - private final String matcher; - - /** - * @return the {@link String} representation of the matcher - */ - public String getMatcher() { - return matcher; - } - - } - - private K name; - - private Optional as = Optional.empty(); - - private Type type; - - private boolean sortable; - - private boolean unNormalizedForm; - - private boolean noStemming; - - private boolean noIndex; - - private Optional phonetic = Optional.empty();; - - private boolean caseSensitive; - - private boolean withSuffixTrie; - - private boolean indexEmpty; - - private boolean indexMissing; - - private Optional weight = Optional.empty();; - - private Optional separator = Optional.empty();; - - private Field() { - } - - /** - * Create a new {@link Field} using the builder pattern. - *

- * One needs to call {@link Builder#build()} to build a single {@link Field} or {@link Builder#buildFields()} to build a - * {@link java.util.List} of {@link Field}s. - * - * @param Key type - * @return a new {@link Builder} - */ - public static Builder builder() { - return new Builder<>(); - } - - /** - * Builder for {@link Field}. - * - * @param Key type - */ - public static class Builder { - - private final Field instance = new Field<>(); - - /** - * The name of the field in a hash the index is going to be based on. - * - * @param name the name of the field - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder name(K name) { - instance.name = name; - return this; - } - - // TODO handling JsonPath - // public Builder name(JsonPath path) { - // instance.name = path.toString(); - // return this; - // } - - /** - * The type of the field. - * - * @param type the type of the field - * @return the instance of the {@link Builder} for the purpose of method chaining - * @see Type - */ - public Builder type(Type type) { - instance.type = type; - return this; - } - - /** - * Defines the attribute associated to the identifier. For example, you can use this feature to alias a complex JSONPath - * expression with more memorable (and easier to type) name. - * - * @param as the field name to be used in queries - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder as(K as) { - instance.as = Optional.of(as); - return this; - } - - /** - * {@link Type#NUMERIC}, {@link Type#TAG}, {@link Type#TEXT}, or {@link Type#GEO} attributes can have an optional - * SORTABLE argument. As the user sorts the results by the value of this attribute, the results are available with very - * low latency. Default is false (not sortable). - *

- * Note that this adds memory overhead, so consider not declaring it on large text attributes. You can sort an attribute - * without the SORTABLE option, but the latency is not as good as with SORTABLE. - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder sortable() { - instance.sortable = true; - return this; - } - - /** - * By default, for hashes (not with JSON) SORTABLE applies normalization to the indexed value (characters set to - * lowercase, removal of diacritics). When using the unnormalized form (UNF), you can disable the normalization and keep - * the original form of the value. With JSON, UNF is implicit with SORTABLE (normalization is disabled). - *

- * Default is false (normalized form). - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder unNormalizedForm() { - instance.sortable = true; - instance.unNormalizedForm = true; - return this; - } - - /** - * By default, the index applies stemming to {@link Type#TEXT} fields. If you don't want to apply stemming to the field, - * you can use the NOSTEM argument. This may be ideal for things like proper names. - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder noStemming() { - instance.noStemming = true; - return this; - } - - /** - * Attributes can have the NOINDEX option, which means they will not be indexed. This is useful in conjunction with - * {@link Builder#sortable()}, to create attributes whose update using PARTIAL will not cause full reindexing of the - * document. If an attribute has NOINDEX and doesn't have SORTABLE, it will just be ignored by the index. - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder noIndex() { - instance.noIndex = true; - return this; - } - - /** - * Phonetic matching is a feature that allows you to search for similar-sounding words. For example, a search for - * "Smith" will also return results for "Smyth". Phonetic matching is language-specific, and you can specify the - * language using the PHONETIC argument. - *

- * The following languages are supported: - *

    - *
  • ENGLISH
  • - *
  • FRENCH
  • - *
  • PORTUGUESE
  • x - *
  • SPANISH
  • - *
- * - * @see Phonetic - * Matching - * @param matcher the phonetic matcher - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder phonetic(PhoneticMatcher matcher) { - instance.phonetic = Optional.of(matcher); - return this; - } - - /** - * The weight of the field. Works with {@link Type#TEXT} attributes, declares the importance of this attribute when - * calculating result accuracy. This is a multiplication factor. The default weight is 1. - * - * @param weight the weight of the field - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder weight(long weight) { - instance.weight = Optional.of(weight); - return this; - } - - /** - * The separator for {@link Type#TAG} attributes. The default separator is a comma. - * - * @param separator the separator for tag fields - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder separator(String separator) { - instance.separator = Optional.of(separator); - return this; - } - - /** - * Keeps the original letter cases of the tags. If not specified, the characters are converted to lowercase. Works with - * {@link Type#TAG} attributes. - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder caseSensitive() { - instance.caseSensitive = true; - return this; - } - - /** - * For {@link Type#TEXT} and {@link Type#TAG} attributes, keeps a suffix trie with all terms which match the suffix. It - * is used to optimize contains (foo) and suffix (*foo) queries. Otherwise, a brute-force search on the trie is - * performed. If the suffix trie exists for some fields, these queries will be disabled for other fields. - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder withSuffixTrie() { - instance.withSuffixTrie = true; - return this; - } - - /** - * For {@link Type#TEXT} and {@link Type#TAG} attributes, introduced in v2.10, allows you to index and search for empty - * strings. By default, empty strings are not indexed. - * - * @return the instance of the {@link Builder} for the purpose of method chaining - */ - public Builder indexEmpty() { - instance.indexEmpty = true; - return this; - } - - /** - * For all field types, introduced in v2.10, allows you to search for missing values, that is, documents that do not - * contain a specific field. Note the difference between a field with an empty value and a document with a missing - * value. By default, missing values are not indexed. - */ - public Builder indexMissing() { - instance.indexMissing = true; - return this; - } - - /** - * Build a single {@link Field}. - * - * @return the instance of the {@link Field} - */ - public Field build() { - return instance; - } - - /** - * Build a {@link java.util.List} of {@link Field}s, containing the current {@link Field} as the only element of the - * list. - * - * @return the instance of the {@link Field} - */ - public List> buildFields() { - List> fields = new ArrayList<>(); - fields.add(instance); - return fields; - } - - } - - /** - * @return the type of the field - * @see Builder#type(Type) - */ - public Type getType() { - return type; - } - - /** - * @return the name of the field - * @see Builder#name(Object) - */ - public K getName() { - return name; - } - - /** - * @return the alias of the field - * @see Builder#as(Object) - */ - public Optional getAs() { - return as; - } - - /** - * @return if the field should be sortable - * @see Builder#sortable() - */ - public boolean isSortable() { - return sortable; - } - - /** - * @return if the field should be in unnormalized form - * @see Builder#unNormalizedForm() - */ - public boolean isUnNormalizedForm() { - return unNormalizedForm; - } - - /** - * @return if the field should not be indexed - * @see Builder#noIndex() - */ - public boolean isNoIndex() { - return noIndex; - } - - /** - * @return if the field should not be stemmed - * @see Builder#noStemming() - */ - public boolean isNoStemming() { - return noStemming; - } - - /** - * @return the setting for phonetic matching - * @see Builder#phonetic(PhoneticMatcher) - */ - public Optional isPhonetic() { - return phonetic; - } - - /** - * @return if the field should be case sensitive - * @see Builder#caseSensitive() - */ - public boolean isCaseSensitive() { - return caseSensitive; - } - - /** - * @return if the field should have a suffix trie - * @see Builder#withSuffixTrie() - */ - public boolean isWithSuffixTrie() { - return withSuffixTrie; - } - - /** - * @return if the field should index empty values - * @see Builder#indexEmpty() - */ - public boolean isIndexEmpty() { - return indexEmpty; - } - - /** - * @return if the field should index missing values - * @see Builder#indexMissing() - */ - public boolean isIndexMissing() { - return indexMissing; - } - - /** - * @return the weight of the field - * @see Builder#weight(long) - */ - public Optional getWeight() { - return weight; - } - - /** - * @return the separator for tag fields - * @see Builder#separator(String) - */ - public Optional getSeparator() { - return separator; - } - - /** - * Add all configured arguments to the final command - * - * @param args the command arguments to modify - */ - public void build(CommandArgs args) { - args.addKey(name); - as.ifPresent(a -> args.add(AS).addKey(a)); - args.add(type.toString()); - if (sortable) { - args.add(SORTABLE); - if (unNormalizedForm) { - args.add(UNF); - } - } - if (noStemming) { - args.add(NOSTEM); - } - if (noIndex) { - args.add(NOINDEX); - } - phonetic.ifPresent(p -> args.add(PHONETIC).add(p.getMatcher())); - weight.ifPresent(w -> args.add(WEIGHT).add(w)); - separator.ifPresent(s -> args.add(SEPARATOR).add(s)); - if (caseSensitive) { - args.add(CASESENSITIVE); - } - if (withSuffixTrie) { - args.add(WITHSUFFIXTRIE); - } - if (indexEmpty) { - args.add(INDEXEMPTY); - } - if (indexMissing) { - args.add(INDEXMISSING); - } - } - -} diff --git a/src/main/java/io/lettuce/core/search/arguments/CreateArgs.java b/src/main/java/io/lettuce/core/search/arguments/CreateArgs.java deleted file mode 100644 index 2e61affba3..0000000000 --- a/src/main/java/io/lettuce/core/search/arguments/CreateArgs.java +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.search.arguments; - -import io.lettuce.core.protocol.CommandArgs; -import io.lettuce.core.search.DocumentLanguage; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.OptionalDouble; -import java.util.OptionalLong; - -import static io.lettuce.core.protocol.CommandKeyword.*; - -/** - * Argument list builder for {@code FT.CREATE}. - * - * @param Key type. - * @param Value type. - * @see FT.CREATE - * @since 6.6 - * @author Tihomir Mateev - */ -@SuppressWarnings("OptionalUsedAsFieldOrParameterType") -public class CreateArgs { - - /** - * Possible target types for the index. - */ - public enum TargetType { - HASH, JSON - } - - private Optional on = Optional.of(TargetType.HASH); - - private final List prefixes = new ArrayList<>(); - - private Optional filter = Optional.empty(); - - private Optional defaultLanguage = Optional.empty(); - - private Optional languageField = Optional.empty(); - - private OptionalDouble defaultScore = OptionalDouble.empty(); - - private Optional scoreField = Optional.empty(); - - private Optional payloadField = Optional.empty(); - - private boolean maxTextFields; - - private OptionalLong temporary = OptionalLong.empty(); - - private boolean noOffsets; - - private boolean noHighlight; - - private boolean noFields; - - private boolean noFrequency; - - private boolean skipInitialScan; - - private Optional> stopWords = Optional.empty(); - - /** - * Used to build a new instance of the {@link CreateArgs}. - * - * @return a {@link Builder} that provides the option to build up a new instance of the {@link CreateArgs} - * @param the key type - * @param the value type - */ - public static Builder builder() { - return new Builder<>(); - } - - /** - * Builder for {@link CreateArgs}. - *

- * As a final step the {@link Builder#build()} method needs to be executed to create the final {@link CreateArgs} instance. - * - * @param the key type - * @param the value type - * @see FT.CREATE - */ - public static class Builder { - - private final CreateArgs instance = new CreateArgs<>(); - - /** - * Set the {@link TargetType} type for the index. Defaults to {@link TargetType#HASH}. - * - * @param targetType the target type - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder on(TargetType targetType) { - instance.on = Optional.of(targetType); - return this; - } - - /** - * Add a prefix to the index. You can add several prefixes to index. Default setting is * (all keys). - * - * @param prefix the prefix - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see {@link Builder#addPrefixes(List)} - */ - public Builder addPrefix(K prefix) { - instance.prefixes.add(prefix); - return this; - } - - /** - * Add a list of prefixes to the index. You can add several prefixes to index. Default setting is * (all keys). - * - * @param prefixes a {@link List} of prefixes - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder addPrefixes(List prefixes) { - instance.prefixes.addAll(prefixes); - return this; - } - - /** - * Set a filter for the index. Default setting is to have no filter. - *

- * It is possible to use @__key to access the key that was just added/changed. A field can be used to set field name by - * passing 'FILTER @indexName=="myindexname"'. - * - * @param filter a filter expression with the full RediSearch aggregation expression language - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see RediSearch Query - */ - public Builder filter(V filter) { - instance.filter = Optional.of(filter); - return this; - } - - /** - * Set the default language for the documents in the index. The default setting is English. - * - * @param language the default language - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder defaultLanguage(DocumentLanguage language) { - instance.defaultLanguage = Optional.of(language); - return this; - } - - /** - * Set the field that contains the language setting for the documents in the index. The default setting is to have no - * language field. - * - * @param field the language field - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see Stemming - */ - public Builder languageField(K field) { - instance.languageField = Optional.of(field); - return this; - } - - /** - * Set the default score for the documents in the index. The default setting is 1.0. - * - * @param score the default score - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see Scoring - */ - public Builder defaultScore(double score) { - instance.defaultScore = OptionalDouble.of(score); - return this; - } - - /** - * Set the field that contains the score setting for the documents in the index. The default setting is a score of 1.0. - * - * @param field the score field - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see Scoring - */ - public Builder scoreField(K field) { - instance.scoreField = Optional.of(field); - return this; - } - - /** - * Set the field that contains the payload setting for the documents in the index. The default setting is to have no - * payload field. - *

- * This should be a document attribute that you use as a binary safe payload string to the document that can be - * evaluated at query time by a custom scoring function or retrieved to the client - * - * @param field the payload field - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see Scoring - */ - public Builder payloadField(K field) { - instance.payloadField = Optional.of(field); - return this; - } - - /** - * Set the maximum number of text fields in the index. The default setting is to have no limit. - *

- * Forces RediSearch to encode indexes as if there were more than 32 text attributes, which allows you to add additional - * attributes (beyond 32) using FT.ALTER. For efficiency, RediSearch encodes indexes differently if they are created - * with less than 32 text attributes. - * - * @param maxTextFields the maximum number of text fields - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder maxTextFields(boolean maxTextFields) { - instance.maxTextFields = maxTextFields; - return this; - } - - /** - * Set the temporary index expiration time in seconds. The default setting is to have no expiration time. - *

- * Creates a lightweight temporary index that expires after a specified period of inactivity, in seconds. The internal - * idle timer is reset whenever the index is searched or added to. Because such indexes are lightweight, you can create - * thousands of such indexes without negative performance implications and, therefore, you should consider using - * {@link Builder#skipInitialScan(boolean)} to avoid costly scanning. - *

- * Warning: When temporary indexes expire, they drop all the records associated with them. FT.DROPINDEX was introduced - * with a default of not deleting docs and a DD flag that enforced deletion. However, for temporary indexes, documents - * are deleted along with the index. Historically, RediSearch used an FT.ADD command, which made a connection between - * the document and the index. Then, FT.DROP, also a hystoric command, deleted documents by default. In version 2.x, - * RediSearch indexes hashes and JSONs, and the dependency between the index and documents no longer exists. - * - * @param seconds the temporary index expiration time in seconds - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder temporary(long seconds) { - instance.temporary = OptionalLong.of(seconds); - return this; - } - - /** - * Set the no offsets flag. The default setting is to have offsets. - *

- * It saves memory, but does not allow exact searches or highlighting. It implies - * {@link Builder#noHighlighting(boolean)} is set to true. - * - * @param noOffsets the no offsets flag - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder noOffsets(boolean noOffsets) { - instance.noOffsets = noOffsets; - return this; - } - - /** - * Set the no highlighting flag. The default setting is to have highlighting. - *

- * Conserves storage space and memory by disabling highlighting support. If set, the corresponding byte offsets for term - * positions are not stored. NOHL is also implied by NOOFFSETS. - * - * @param noHL the no highlighting flag - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder noHighlighting(boolean noHL) { - instance.noHighlight = noHL; - return this; - } - - /** - * Set the no fields flag. The default setting is to have fields. - *

- * Does not store attribute bits for each term. It saves memory, but it does not allow filtering by specific attributes. - * - * @param noFields the no fields flag - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder noFields(boolean noFields) { - instance.noFields = noFields; - return this; - } - - /** - * Set the no frequency flag. The default setting is to have frequencies. - *

- * Does not store the frequency of each term. It saves memory, but it does not allow sorting by frequency of a given - * term. - * - * @param noFreqs the no frequency flag - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder noFrequency(boolean noFreqs) { - instance.noFrequency = noFreqs; - return this; - } - - /** - * Set the skip initial scan flag. The default setting is to scan initially. - * - * @param skipInitialScan the skip initial scan flag - * @return the instance of the current {@link Builder} for the purpose of method chaining - */ - public Builder skipInitialScan(boolean skipInitialScan) { - instance.skipInitialScan = skipInitialScan; - return this; - } - - /** - * Set the index with a custom stopword list, to be ignored during indexing and search time. - *

- * If not set, FT.CREATE takes the default list of stopwords. If {count} is set to 0, the index does not have stopwords. - * - * @param stopWords a list of stop words - * @return the instance of the current {@link Builder} for the purpose of method chaining - * @see Stop - * words - */ - public Builder stopWords(List stopWords) { - instance.stopWords = Optional.of(stopWords); - return this; - } - - public CreateArgs build() { - return instance; - } - - } - - /** - * Get the target type for the index. - * - * @return the target type - * @see TargetType - * @see Builder#on(TargetType) - */ - public Optional getOn() { - return on; - } - - /** - * Get the prefixes for the index. - * - * @return the prefixes - * @see Builder#addPrefix(Object) - * @see Builder#addPrefixes(List) - */ - public List getPrefixes() { - return prefixes; - } - - /** - * Get the filter for the index. - * - * @return the filter - * @see Builder#filter(Object) - */ - public Optional getFilter() { - return filter; - } - - /** - * Get the default language for the documents in the index. - * - * @return the default language - * @see Builder#defaultLanguage(DocumentLanguage) - */ - public Optional getDefaultLanguage() { - return defaultLanguage; - } - - /** - * Get the field that contains the language setting for the documents in the index. - * - * @return the language field - * @see Builder#languageField(Object) - */ - public Optional getLanguageField() { - return languageField; - } - - /** - * Get the default score for the documents in the index. - * - * @return the default score - * @see Builder#defaultScore(double) - */ - public OptionalDouble getDefaultScore() { - return defaultScore; - } - - /** - * Get the field that contains the score setting for the documents in the index. - * - * @return the score field - * @see Builder#scoreField(Object) - */ - public Optional getScoreField() { - return scoreField; - } - - /** - * Get the field that contains the payload setting for the documents in the index. - * - * @return the payload field - * @see Builder#payloadField(Object) - */ - public Optional getPayloadField() { - return payloadField; - } - - /** - * Get the maximum number of text fields in the index. - * - * @return the maximum number of text fields - * @see Builder#maxTextFields(boolean) - */ - public boolean isMaxTextFields() { - return maxTextFields; - } - - /** - * Get the temporary index expiration time in seconds. - * - * @return the temporary index expiration time in seconds - * @see Builder#temporary(long) - */ - public OptionalLong getTemporary() { - return temporary; - } - - /** - * Get the no offsets flag. - * - * @return the no offsets flag - * @see Builder#noOffsets(boolean) - */ - public boolean isNoOffsets() { - return noOffsets; - } - - /** - * Get the no highlighting flag. - * - * @return the no highlighting flag - * @see Builder#noHighlighting(boolean) - */ - public boolean isNoHighlight() { - return noHighlight; - } - - /** - * Get the no fields flag. - * - * @return the no fields flag - * @see Builder#noFields(boolean) - */ - public boolean isNoFields() { - return noFields; - } - - /** - * Get the no frequency flag. - * - * @return the no frequency flag - * @see Builder#noFrequency(boolean) - */ - public boolean isNoFrequency() { - return noFrequency; - } - - /** - * Get the skip initial scan flag. - * - * @return the skip initial scan flag - * @see Builder#skipInitialScan(boolean) - */ - public boolean isSkipInitialScan() { - return skipInitialScan; - } - - /** - * Get the stop words for the index. - * - * @return the stop words - * @see Builder#stopWords(List) - */ - public Optional> getStopWords() { - return stopWords; - } - - /** - * Build a {@link CommandArgs} object that contains all the arguments. - * - * @param args the {@link CommandArgs} object - */ - public void build(CommandArgs args) { - on.ifPresent(targetType -> args.add(ON).add(targetType.name())); - if (!prefixes.isEmpty()) { - args.add(PREFIX).add(prefixes.size()); - prefixes.forEach(args::addKey); - } - filter.ifPresent(filter -> args.add(FILTER).addValue(filter)); - defaultLanguage.ifPresent(language -> args.add(LANGUAGE).add(language.toString())); - languageField.ifPresent(field -> args.add(LANGUAGE_FIELD).addKey(field)); - defaultScore.ifPresent(score -> args.add(SCORE).add(score)); - scoreField.ifPresent(field -> args.add(SCORE_FIELD).addKey(field)); - payloadField.ifPresent(field -> args.add(PAYLOAD_FIELD).addKey(field)); - if (maxTextFields) { - args.add(MAXTEXTFIELDS); - } - temporary.ifPresent(seconds -> args.add(TEMPORARY).add(seconds)); - if (noOffsets) { - args.add(NOOFFSETS); - } - if (noHighlight) { - args.add(NOHL); - } - if (noFields) { - args.add(NOFIELDS); - } - if (noFrequency) { - args.add(NOFREQS); - } - if (skipInitialScan) { - args.add(SKIPINITIALSCAN); - } - stopWords.ifPresent(words -> { - args.add(STOPWORDS).add(words.size()); - words.forEach(args::addValue); - }); - } - -} diff --git a/src/main/java/io/lettuce/core/search/package-info.java b/src/main/java/io/lettuce/core/search/package-info.java deleted file mode 100644 index 0d4f7f5cdd..0000000000 --- a/src/main/java/io/lettuce/core/search/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -/** - * Support for the RediSearch features. - */ -package io.lettuce.core.search; diff --git a/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt deleted file mode 100644 index f6a24da5a0..0000000000 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ - -package io.lettuce.core.api.coroutines - -import io.lettuce.core.ExperimentalLettuceCoroutinesApi -import kotlinx.coroutines.flow.Flow -import io.lettuce.core.search.Field -import io.lettuce.core.search.arguments.CreateArgs - -/** - * Coroutine executed commands for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - * @generated by io.lettuce.apigenerator.CreateKotlinCoroutinesApi - */ -@ExperimentalLettuceCoroutinesApi -interface RediSearchCoroutinesCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index [CreateArgs] - * @param fields the [Field]s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - suspend fun ftCreate(index: K, options: CreateArgs, fields: List>): String? - -} - diff --git a/src/main/templates/io/lettuce/core/api/RediSearchCommands.java b/src/main/templates/io/lettuce/core/api/RediSearchCommands.java deleted file mode 100644 index 9c348db9c9..0000000000 --- a/src/main/templates/io/lettuce/core/api/RediSearchCommands.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -package io.lettuce.core.api; - -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; - -import java.util.List; - -/** - * ${intent} for RediSearch functionality - * - * @param Key type. - * @param Value type. - * @author Tihomir Mateev - * @see RediSearch - * @since 6.6 - */ -public interface RediSearchCommands { - - /** - * Create a new index with the given name, index options, and fields. - * - * @param index the index name, as a key - * @param options the index {@link CreateArgs} - * @param fields the {@link Field}s of the index - * @return the result of the create command - * @since 6.6 - * @see FT.CREATE - */ - String ftCreate(K index, CreateArgs options, List> fields); - -} diff --git a/src/test/java/io/lettuce/apigenerator/Constants.java b/src/test/java/io/lettuce/apigenerator/Constants.java index 4f28a33d95..896b939951 100644 --- a/src/test/java/io/lettuce/apigenerator/Constants.java +++ b/src/test/java/io/lettuce/apigenerator/Constants.java @@ -30,7 +30,7 @@ class Constants { "RedisGeoCommands", "RedisHashCommands", "RedisHLLCommands", "RedisKeyCommands", "RedisListCommands", "RedisScriptingCommands", "RedisSentinelCommands", "RedisServerCommands", "RedisSetCommands", "RedisSortedSetCommands", "RedisStreamCommands", "RedisStringCommands", "RedisTransactionalCommands", - "RedisJsonCommands", "RediSearchCommands" }; + "RedisJsonCommands" }; public static final File TEMPLATES = new File("src/main/templates"); diff --git a/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java b/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java deleted file mode 100644 index c84e232ebf..0000000000 --- a/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java +++ /dev/null @@ -1,92 +0,0 @@ -package io.lettuce.core; - -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ -import io.lettuce.core.codec.StringCodec; -import io.lettuce.core.protocol.Command; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import static io.lettuce.TestTags.UNIT_TEST; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Unit tests for {@link RediSearchCommandBuilder}. - * - * @author Tihomir Mateev - */ -@Tag(UNIT_TEST) -class RediSearchCommandBuilderUnitTests { - - private static final String MY_KEY = "idx"; - - private static final String FIELD1_NAME = "title"; - - private static final String FIELD2_NAME = "published_at"; - - private static final String FIELD3_NAME = "category"; - - private static final String FIELD4_NAME = "sku"; - - private static final String FIELD4_ALIAS1 = "sku_text"; - - private static final String FIELD4_ALIAS2 = "sku_tag"; - - private static final String PREFIX = "blog:post:"; - - RediSearchCommandBuilder builder = new RediSearchCommandBuilder<>(StringCodec.UTF8); - - // FT.CREATE idx ON HASH PREFIX 1 blog:post: SCHEMA title TEXT SORTABLE published_at NUMERIC SORTABLE category TAG SORTABLE - @Test - void shouldCorrectlyConstructFtCreateCommandScenario1() { - Field field1 = Field. builder().name(FIELD1_NAME).type(Field.Type.TEXT).sortable().build(); - Field field2 = Field. builder().name(FIELD2_NAME).type(Field.Type.NUMERIC).sortable().build(); - Field field3 = Field. builder().name(FIELD3_NAME).type(Field.Type.TAG).sortable().build(); - CreateArgs createArgs = CreateArgs. builder().addPrefix(PREFIX) - .on(CreateArgs.TargetType.HASH).build(); - Command command = builder.ftCreate(MY_KEY, createArgs, Arrays.asList(field1, field2, field3)); - ByteBuf buf = Unpooled.directBuffer(); - command.encode(buf); - - String result = "*17\r\n" + "$9\r\n" + "FT.CREATE\r\n" + "$3\r\n" + MY_KEY + "\r\n" + "$2\r\n" + "ON\r\n" + "$4\r\n" - + "HASH\r\n" + "$6\r\n" + "PREFIX\r\n" + "$1\r\n" + "1\r\n" + "$10\r\n" + PREFIX + "\r\n" + "$6\r\n" - + "SCHEMA\r\n" + "$5\r\n" + FIELD1_NAME + "\r\n" + "$4\r\n" + "TEXT\r\n" + "$8\r\n" + "SORTABLE\r\n" + "$12\r\n" - + FIELD2_NAME + "\r\n" + "$7\r\n" + "NUMERIC\r\n" + "$8\r\n" + "SORTABLE\r\n" + "$8\r\n" + FIELD3_NAME + "\r\n" - + "$3\r\n" + "TAG\r\n" + "$8\r\n" + "SORTABLE\r\n"; - - assertThat(buf.toString(StandardCharsets.UTF_8)).isEqualTo(result); - } - - // FT.CREATE idx ON HASH PREFIX 1 blog:post: SCHEMA sku AS sku_text TEXT sku AS sku_tag TAG SORTABLE - @Test - void shouldCorrectlyConstructFtCreateCommandScenario2() { - Field field1 = Field. builder().name(FIELD4_NAME).as(FIELD4_ALIAS1).type(Field.Type.TEXT).build(); - Field field2 = Field. builder().name(FIELD4_NAME).as(FIELD4_ALIAS2).type(Field.Type.TAG).sortable() - .build(); - CreateArgs createArgs = CreateArgs. builder().addPrefix(PREFIX) - .on(CreateArgs.TargetType.HASH).build(); - Command command = builder.ftCreate(MY_KEY, createArgs, Arrays.asList(field1, field2)); - ByteBuf buf = Unpooled.directBuffer(); - command.encode(buf); - - String result = "*17\r\n" + "$9\r\n" + "FT.CREATE\r\n" + "$3\r\n" + MY_KEY + "\r\n" + "$2\r\n" + "ON\r\n" + "$4\r\n" - + "HASH\r\n" + "$6\r\n" + "PREFIX\r\n" + "$1\r\n" + "1\r\n" + "$10\r\n" + PREFIX + "\r\n" + "$6\r\n" - + "SCHEMA\r\n" + "$3\r\n" + FIELD4_NAME + "\r\n" + "$2\r\n" + "AS\r\n" + "$8\r\n" + FIELD4_ALIAS1 + "\r\n" - + "$4\r\n" + "TEXT\r\n" + "$3\r\n" + FIELD4_NAME + "\r\n" + "$2\r\n" + "AS\r\n" + "$7\r\n" + FIELD4_ALIAS2 - + "\r\n" + "$3\r\n" + "TAG\r\n" + "$8\r\n" + "SORTABLE\r\n"; - - assertThat(buf.toString(StandardCharsets.UTF_8)).isEqualTo(result); - } - -} diff --git a/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java b/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java deleted file mode 100644 index c87472bc64..0000000000 --- a/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2025, Redis Ltd. and Contributors - * All rights reserved. - * - * Licensed under the MIT License. - */ - -package io.lettuce.core.json; - -import io.lettuce.core.RedisClient; -import io.lettuce.core.RedisContainerIntegrationTests; -import io.lettuce.core.RedisURI; -import io.lettuce.core.api.sync.RedisCommands; -import io.lettuce.core.search.Field; -import io.lettuce.core.search.arguments.CreateArgs; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; - -import static io.lettuce.TestTags.INTEGRATION_TEST; -import static org.assertj.core.api.Assertions.assertThat; - -@Tag(INTEGRATION_TEST) -public class RediSearchIntegrationTests extends RedisContainerIntegrationTests { - - private static final String GENERIC_INDEX = "idx"; - - private static final String FIELD1_NAME = "title"; - - private static final String FIELD2_NAME = "published_at"; - - private static final String FIELD3_NAME = "category"; - - private static final String PREFIX = "blog:post:"; - - protected static RedisClient client; - - protected static RedisCommands redis; - - public RediSearchIntegrationTests() { - RedisURI redisURI = RedisURI.Builder.redis("127.0.0.1").withPort(16379).build(); - - client = RedisClient.create(redisURI); - redis = client.connect().sync(); - } - - @BeforeEach - public void prepare() throws IOException { - redis.flushall(); - - Path path = Paths.get("src/test/resources/bike-inventory.json"); - String read = String.join("", Files.readAllLines(path)); - JsonValue value = redis.getJsonParser().createJsonValue(read); - - redis.jsonSet("bikes:inventory", JsonPath.ROOT_PATH, value); - } - - @AfterAll - static void teardown() { - if (client != null) { - client.shutdown(); - } - } - - @Test - void ftCreateScenario1() { - Field field1 = Field. builder().name(FIELD1_NAME).type(Field.Type.TEXT).sortable().build(); - Field field2 = Field. builder().name(FIELD2_NAME).type(Field.Type.NUMERIC).sortable().build(); - Field field3 = Field. builder().name(FIELD3_NAME).type(Field.Type.TAG).sortable().build(); - CreateArgs createArgs = CreateArgs. builder().addPrefix(PREFIX) - .on(CreateArgs.TargetType.HASH).build(); - - String result = redis.ftCreate(GENERIC_INDEX, createArgs, Arrays.asList(field1, field2, field3)); - assertThat(result).isEqualTo("OK"); - } - -}