From f1e346e6d5dbb660162b5307cf19a7e4eb52587f Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Thu, 17 Oct 2024 16:17:54 -0700 Subject: [PATCH 1/4] `FT.PROFILE`. Signed-off-by: Yury-Fridlyand --- CHANGELOG.md | 1 + glide-core/src/client/value_conversion.rs | 51 +++++- .../glide/api/commands/servermodules/FT.java | 32 ++++ .../models/commands/FT/FTProfileOptions.java | 168 ++++++++++++++++++ .../java/glide/modules/VectorSearchTests.java | 104 ++++++----- 5 files changed, 300 insertions(+), 56 deletions(-) create mode 100644 java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 429e2d2316..a15853d8b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Java: Added `FT.DROPINDEX` ([#2440](https://github.com/valkey-io/valkey-glide/pull/2440)) * Java: Added `FT.SEARCH` ([#2439](https://github.com/valkey-io/valkey-glide/pull/2439)) * Java: Added `FT.AGGREGATE` ([#2466](https://github.com/valkey-io/valkey-glide/pull/2466)) +* Java: Added `FT.PROFILE` ([#2473](https://github.com/valkey-io/valkey-glide/pull/2473)) * Java: Added `JSON.SET` and `JSON.GET` ([#2462](https://github.com/valkey-io/valkey-glide/pull/2462)) * Core: Update routing for commands from server modules ([#2461](https://github.com/valkey-io/valkey-glide/pull/2461)) diff --git a/glide-core/src/client/value_conversion.rs b/glide-core/src/client/value_conversion.rs index 64b853af9f..661bcd8776 100644 --- a/glide-core/src/client/value_conversion.rs +++ b/glide-core/src/client/value_conversion.rs @@ -24,6 +24,7 @@ pub(crate) enum ExpectedReturnType<'a> { ArrayOfDoubleOrNull, FTAggregateReturnType, FTSearchReturnType, + FTProfileReturnType(&'a Option>), Lolwut, ArrayOfStringAndArrays, ArrayOfArraysOfDoubleOrNull, @@ -938,7 +939,7 @@ pub(crate) fn convert_to_expected_type( let Value::Array(fields) = aggregation else { return Err(( ErrorKind::TypeError, - "Response couldn't be converted for FT.AGGREGATION", + "Response couldn't be converted for FT.AGGREGATE", format!("(`fields` was {:?})", get_value_type(&aggregation)), ) .into()); @@ -953,7 +954,7 @@ pub(crate) fn convert_to_expected_type( } _ => Err(( ErrorKind::TypeError, - "Response couldn't be converted to FT.AGGREGATION", + "Response couldn't be converted for FT.AGGREGATE", format!("(response was {:?})", get_value_type(&value)), ) .into()), @@ -999,11 +1000,47 @@ pub(crate) fn convert_to_expected_type( }, _ => Err(( ErrorKind::TypeError, - "Response couldn't be converted to Pair", + "Response couldn't be converted for FT.SEARCH", format!("(response was {:?})", get_value_type(&value)), ) .into()) }, + ExpectedReturnType::FTProfileReturnType(type_of_query) => match value { + /* + Example of the response + 1) + 2) 1) 1) "parse.time" + 2) 119 + 2) 1) "all.count" + 2) 4 + 3) 1) "sync.time" + 2) 0 + + Converting response to + 1) + 2) 1# "parse.time" => 119 + 2# "all.count" => 4 + 3# "sync.time" => 0 + + Converting first array element as it is needed for the inner query and second element to a map. + */ + Value::Array(mut array) if array.len() == 2 => { + let res = vec![ + convert_to_expected_type(array.remove(0), *type_of_query)?, + convert_to_expected_type(array.remove(0), Some(ExpectedReturnType::Map { + key_type: &None, + value_type: &None, + }))?]; + + Ok(Value::Array(res)) + }, + _ => Err(( + ErrorKind::TypeError, + "Response couldn't be converted for FT.PROFILE", + format!("(response was {:?})", get_value_type(&value)), + ) + .into()) + } } } @@ -1370,6 +1407,14 @@ pub(crate) fn expected_type_for_cmd(cmd: &Cmd) -> Option { }), b"FT.AGGREGATE" => Some(ExpectedReturnType::FTAggregateReturnType), b"FT.SEARCH" => Some(ExpectedReturnType::FTSearchReturnType), + // TODO replace with tuple + b"FT.PROFILE" => Some(ExpectedReturnType::FTProfileReturnType( + if cmd.arg_idx(2).is_some_and(|a| a == b"SEARCH") { + &Some(ExpectedReturnType::FTSearchReturnType) + } else { + &Some(ExpectedReturnType::FTAggregateReturnType) + }, + )), _ => None, } } diff --git a/java/client/src/main/java/glide/api/commands/servermodules/FT.java b/java/client/src/main/java/glide/api/commands/servermodules/FT.java index 106d540f8c..20e13f0965 100644 --- a/java/client/src/main/java/glide/api/commands/servermodules/FT.java +++ b/java/client/src/main/java/glide/api/commands/servermodules/FT.java @@ -13,6 +13,7 @@ import glide.api.models.commands.FT.FTAggregateOptions; import glide.api.models.commands.FT.FTCreateOptions; import glide.api.models.commands.FT.FTCreateOptions.FieldInfo; +import glide.api.models.commands.FT.FTProfileOptions; import glide.api.models.commands.FT.FTSearchOptions; import java.util.Arrays; import java.util.Map; @@ -474,6 +475,37 @@ public static CompletableFuture[]> aggregate( .thenApply(res -> castArray(res, Map.class)); } + /** + * Runs a search or aggregation query and collects performance profiling information. + * + * @param client The client to execute the command. + * @param indexName The index name. + * @param options Querying and profiling parameters - see {@link FTProfileOptions}. + * @return A two-element array. The first element contains results of query being profiled, the + * second element stores profiling information. + */ + public static CompletableFuture profile( + @NonNull BaseClient client, @NonNull String indexName, @NonNull FTProfileOptions options) { + return profile(client, gs(indexName), options); + } + + /** + * Runs a search or aggregation query and collects performance profiling information. + * + * @param client The client to execute the command. + * @param indexName The index name. + * @param options Querying and profiling parameters - see {@link FTProfileOptions}. + * @return A two-element array. The first element contains results of query being profiled, the + * second element stores profiling information. + */ + public static CompletableFuture profile( + @NonNull BaseClient client, + @NonNull GlideString indexName, + @NonNull FTProfileOptions options) { + var args = concatenateArrays(new GlideString[] {gs("FT.PROFILE"), indexName}, options.toArgs()); + return executeCommand(client, args, false); + } + /** * A wrapper for custom command API. * diff --git a/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java b/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java new file mode 100644 index 0000000000..c1fb528785 --- /dev/null +++ b/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java @@ -0,0 +1,168 @@ +/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */ +package glide.api.models.commands.FT; + +import static glide.api.models.GlideString.gs; +import static glide.utils.ArrayTransformUtils.concatenateArrays; + +import glide.api.commands.servermodules.FT; +import glide.api.models.GlideString; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +/** Mandatory parameters for {@link FT#profile} command. */ +public class FTProfileOptions { + private final QueryType queryType; + private final boolean limited; + private final GlideString[] query; + + /** Query type being profiled. */ + public enum QueryType { + SEARCH, + AGGREGATE + } + + /** + * Profile a query given as an array of module command line arguments. + * + * @param queryType The query type. + * @param commandLine Command arguments (not including index name). + */ + public FTProfileOptions(QueryType queryType, GlideString[] commandLine) { + this(queryType, commandLine, false); + } + + /** + * Profile a query given as an array of module command line arguments. + * + * @param queryType The query type. + * @param commandLine Command arguments (not including index name). + */ + public FTProfileOptions(QueryType queryType, String[] commandLine) { + this(queryType, commandLine, false); + } + + /** + * Profile a query given as an array of module command line arguments. + * + * @param queryType The query type. + * @param commandLine Command arguments (not including index name). + * @param limited Either provide a full verbose output or some brief version (limited). + */ + public FTProfileOptions(QueryType queryType, GlideString[] commandLine, boolean limited) { + this.queryType = queryType; + this.query = commandLine; + this.limited = limited; + } + + /** + * Profile a query given as an array of module command line arguments. + * + * @param queryType The query type. + * @param commandLine Command arguments (not including index name). + * @param limited Either provide a full verbose output or some brief version (limited). + */ + public FTProfileOptions(QueryType queryType, String[] commandLine, boolean limited) { + this( + queryType, + Stream.of(commandLine).map(GlideString::gs).toArray(GlideString[]::new), + limited); + } + + /** + * Profile an aggregation query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#aggregate} options. + */ + public FTProfileOptions(String query, FTAggregateOptions options) { + this(gs(query), options); + } + + /** + * Profile an aggregation query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#aggregate} options. + */ + public FTProfileOptions(GlideString query, FTAggregateOptions options) { + this(QueryType.AGGREGATE, concatenateArrays(new GlideString[] {query}, options.toArgs())); + } + + /** + * Profile a search query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#search} options. + */ + public FTProfileOptions(String query, FTSearchOptions options) { + this(gs(query), options); + } + + /** + * Profile a search query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#search} options. + */ + public FTProfileOptions(GlideString query, FTSearchOptions options) { + this(QueryType.SEARCH, concatenateArrays(new GlideString[] {query}, options.toArgs())); + } + + /** + * Profile an aggregation query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#aggregate} options. + * @param limited Either provide a full verbose output or some brief version (limited). + */ + public FTProfileOptions(String query, FTAggregateOptions options, boolean limited) { + this(gs(query), options, limited); + } + + /** + * Profile a search query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#search} options. + * @param limited Either provide a full verbose output or some brief version (limited). + */ + public FTProfileOptions(GlideString query, FTAggregateOptions options, boolean limited) { + this( + QueryType.AGGREGATE, + concatenateArrays(new GlideString[] {query}, options.toArgs()), + limited); + } + + /** + * Profile an aggregation query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#aggregate} options. + * @param limited Either provide a full verbose output or some brief version (limited). + */ + public FTProfileOptions(String query, FTSearchOptions options, boolean limited) { + this(gs(query), options, limited); + } + + /** + * Profile a search query with given parameters. + * + * @param query The query itself. + * @param options {@link FT#search} options. + * @param limited Either provide a full verbose output or some brief version (limited). + */ + public FTProfileOptions(GlideString query, FTSearchOptions options, boolean limited) { + this(QueryType.SEARCH, concatenateArrays(new GlideString[] {query}, options.toArgs()), limited); + } + + /** Convert to module API. */ + public GlideString[] toArgs() { + var args = new ArrayList(); + args.add(gs(queryType.toString())); + if (limited) args.add(gs("LIMITED")); + args.add(gs("QUERY")); + args.addAll(List.of(query)); + return args.toArray(GlideString[]::new); + } +} diff --git a/java/integTest/src/test/java/glide/modules/VectorSearchTests.java b/java/integTest/src/test/java/glide/modules/VectorSearchTests.java index fbc3eab196..5c6383b54b 100644 --- a/java/integTest/src/test/java/glide/modules/VectorSearchTests.java +++ b/java/integTest/src/test/java/glide/modules/VectorSearchTests.java @@ -32,6 +32,7 @@ import glide.api.models.commands.FT.FTCreateOptions.TextField; import glide.api.models.commands.FT.FTCreateOptions.VectorFieldFlat; import glide.api.models.commands.FT.FTCreateOptions.VectorFieldHnsw; +import glide.api.models.commands.FT.FTProfileOptions; import glide.api.models.commands.FT.FTSearchOptions; import glide.api.models.commands.FlushMode; import glide.api.models.commands.InfoOptions.Section; @@ -254,22 +255,21 @@ public void ft_search() { }))) .get()); - var ftsearch = - FT.search( - client, - index, - "*=>[KNN 2 @VEC $query_vec]", - FTSearchOptions.builder() - .params( - Map.of( - gs("query_vec"), - gs( - new byte[] { - (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, - (byte) 0, (byte) 0 - }))) - .build()) - .get(); + // FT.SEARCH hash_idx1 "*=>[KNN 2 @VEC $query_vec]" PARAMS 2 query_vec + // "\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2 + var options = + FTSearchOptions.builder() + .params( + Map.of( + gs("query_vec"), + gs( + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0 + }))) + .build(); + var query = "*=>[KNN 2 @VEC $query_vec]"; + var ftsearch = FT.search(client, index, query, options).get(); assertArrayEquals( new Object[] { @@ -298,6 +298,9 @@ public void ft_search() { // TODO more tests with json index + var ftprofile = FT.profile(client, index, new FTProfileOptions(query, options)).get(); + assertArrayEquals(ftsearch, (Object[]) ftprofile[0]); + // querying non-existing index var exception = assertThrows( @@ -530,19 +533,15 @@ public void ft_aggregate() { Thread.sleep(DATA_PROCESSING_TIMEOUT); // let server digest the data and update index // FT.AGGREGATE idx:bicycle "*" LOAD 1 "__key" GROUPBY 1 "@condition" REDUCE COUNT 0 AS bicylces - var aggreg = - FT.aggregate( - client, - indexBicycles, - "*", - FTAggregateOptions.builder() - .loadFields(new String[] {"__key"}) - .addExpression( - new GroupBy( - new String[] {"@condition"}, - new Reducer[] {new Reducer("COUNT", new String[0], "bicycles")})) - .build()) - .get(); + var options = + FTAggregateOptions.builder() + .loadFields(new String[] {"__key"}) + .addExpression( + new GroupBy( + new String[] {"@condition"}, + new Reducer[] {new Reducer("COUNT", new String[0], "bicycles")})) + .build(); + var aggreg = FT.aggregate(client, indexBicycles, "*", options).get(); // elements (maps in array) could be reordered, comparing as sets assertDeepEquals( Set.of( @@ -657,30 +656,26 @@ public void ft_aggregate() { // FT.AGGREGATE idx:movie * LOAD * APPLY ceil(@rating) as r_rating GROUPBY 1 @genre REDUCE // COUNT 0 AS nb_of_movies REDUCE SUM 1 votes AS nb_of_votes REDUCE AVG 1 r_rating AS avg_rating // SORTBY 4 @avg_rating DESC @nb_of_votes DESC - aggreg = - FT.aggregate( - client, - indexMovies, - "*", - FTAggregateOptions.builder() - .loadAll() - .addExpression(new Apply("ceil(@rating)", "r_rating")) - .addExpression( - new GroupBy( - new String[] {"@genre"}, - new Reducer[] { - new Reducer("COUNT", new String[0], "nb_of_movies"), - new Reducer("SUM", new String[] {"votes"}, "nb_of_votes"), - new Reducer("AVG", new String[] {"r_rating"}, "avg_rating") - })) - .addExpression( - new SortBy( - new SortProperty[] { - new SortProperty("@avg_rating", SortOrder.DESC), - new SortProperty("@nb_of_votes", SortOrder.DESC) - })) - .build()) - .get(); + options = + FTAggregateOptions.builder() + .loadAll() + .addExpression(new Apply("ceil(@rating)", "r_rating")) + .addExpression( + new GroupBy( + new String[] {"@genre"}, + new Reducer[] { + new Reducer("COUNT", new String[0], "nb_of_movies"), + new Reducer("SUM", new String[] {"votes"}, "nb_of_votes"), + new Reducer("AVG", new String[] {"r_rating"}, "avg_rating") + })) + .addExpression( + new SortBy( + new SortProperty[] { + new SortProperty("@avg_rating", SortOrder.DESC), + new SortProperty("@nb_of_votes", SortOrder.DESC) + })) + .build(); + aggreg = FT.aggregate(client, indexMovies, "*", options).get(); // elements (maps in array) could be reordered, comparing as sets assertDeepEquals( Set.of( @@ -712,5 +707,8 @@ public void ft_aggregate() { gs("avg_rating"), 9.)), Set.of(aggreg)); + + var ftprofile = FT.profile(client, indexMovies, new FTProfileOptions("*", options)).get(); + assertDeepEquals(aggreg, ftprofile[0]); } } From 74a1500fbca9bec88855eb3cca70b756047848e4 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Fri, 18 Oct 2024 17:59:22 -0700 Subject: [PATCH 2/4] nonnulll Signed-off-by: Yury-Fridlyand --- .../commands/FT/FTAggregateOptions.java | 39 ++++++++++--------- .../models/commands/FT/FTCreateOptions.java | 2 +- .../models/commands/FT/FTProfileOptions.java | 31 +++++++++------ .../models/commands/FT/FTSearchOptions.java | 10 +++-- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/java/client/src/main/java/glide/api/models/commands/FT/FTAggregateOptions.java b/java/client/src/main/java/glide/api/models/commands/FT/FTAggregateOptions.java index 73ffdbf412..700695b7ae 100644 --- a/java/client/src/main/java/glide/api/models/commands/FT/FTAggregateOptions.java +++ b/java/client/src/main/java/glide/api/models/commands/FT/FTAggregateOptions.java @@ -14,6 +14,7 @@ import java.util.Map; import java.util.stream.Stream; import lombok.Builder; +import lombok.NonNull; /** * Additional arguments for {@link FT#aggregate(BaseClient, String, String, FTAggregateOptions)} @@ -79,19 +80,19 @@ public FTAggregateOptionsBuilder loadAll() { return this; } - public FTAggregateOptionsBuilder loadFields(String[] fields) { + public FTAggregateOptionsBuilder loadFields(@NonNull String[] fields) { loadFields = toGlideStringArray(fields); loadAll = false; return this; } - public FTAggregateOptionsBuilder loadFields(GlideString[] fields) { + public FTAggregateOptionsBuilder loadFields(@NonNull GlideString[] fields) { loadFields = fields; loadAll = false; return this; } - public FTAggregateOptionsBuilder addExpression(FTAggregateExpression expression) { + public FTAggregateOptionsBuilder addExpression(@NonNull FTAggregateExpression expression) { if (expressions == null) expressions = new ArrayList<>(); expressions.add(expression); return this; @@ -138,11 +139,11 @@ GlideString[] toArgs() { public static class Filter extends FTAggregateExpression { private final GlideString expression; - public Filter(GlideString expression) { + public Filter(@NonNull GlideString expression) { this.expression = expression; } - public Filter(String expression) { + public Filter(@NonNull String expression) { this.expression = gs(expression); } @@ -160,22 +161,22 @@ public static class GroupBy extends FTAggregateExpression { private final GlideString[] properties; private final Reducer[] reducers; - public GroupBy(GlideString[] properties, Reducer[] reducers) { + public GroupBy(@NonNull GlideString[] properties, @NonNull Reducer[] reducers) { this.properties = properties; this.reducers = reducers; } - public GroupBy(String[] properties, Reducer[] reducers) { + public GroupBy(@NonNull String[] properties, @NonNull Reducer[] reducers) { this.properties = toGlideStringArray(properties); this.reducers = reducers; } - public GroupBy(GlideString[] properties) { + public GroupBy(@NonNull GlideString[] properties) { this.properties = properties; this.reducers = new Reducer[0]; } - public GroupBy(String[] properties) { + public GroupBy(@NonNull String[] properties) { this.properties = toGlideStringArray(properties); this.reducers = new Reducer[0]; } @@ -199,25 +200,25 @@ public static class Reducer { private final GlideString[] args; private final String alias; - public Reducer(String function, GlideString[] args, String alias) { + public Reducer(@NonNull String function, @NonNull GlideString[] args, @NonNull String alias) { this.function = function; this.args = args; this.alias = alias; } - public Reducer(String function, GlideString[] args) { + public Reducer(@NonNull String function, @NonNull GlideString[] args) { this.function = function; this.args = args; this.alias = null; } - public Reducer(String function, String[] args, String alias) { + public Reducer(@NonNull String function, @NonNull String[] args, @NonNull String alias) { this.function = function; this.args = toGlideStringArray(args); this.alias = alias; } - public Reducer(String function, String[] args) { + public Reducer(@NonNull String function, @NonNull String[] args) { this.function = function; this.args = toGlideStringArray(args); this.alias = null; @@ -240,12 +241,12 @@ public static class SortBy extends FTAggregateExpression { private final SortProperty[] properties; private final Integer max; - public SortBy(SortProperty[] properties) { + public SortBy(@NonNull SortProperty[] properties) { this.properties = properties; this.max = null; } - public SortBy(SortProperty[] properties, int max) { + public SortBy(@NonNull SortProperty[] properties, int max) { this.properties = properties; this.max = max; } @@ -273,12 +274,12 @@ public static class SortProperty { private final GlideString property; private final SortOrder order; - public SortProperty(GlideString property, SortOrder order) { + public SortProperty(@NonNull GlideString property, @NonNull SortOrder order) { this.property = property; this.order = order; } - public SortProperty(String property, SortOrder order) { + public SortProperty(@NonNull String property, @NonNull SortOrder order) { this.property = gs(property); this.order = order; } @@ -297,12 +298,12 @@ public static class Apply extends FTAggregateExpression { private final GlideString expression; private final GlideString alias; - public Apply(GlideString expression, GlideString alias) { + public Apply(@NonNull GlideString expression, @NonNull GlideString alias) { this.expression = expression; this.alias = alias; } - public Apply(String expression, String alias) { + public Apply(@NonNull String expression, @NonNull String alias) { this.expression = gs(expression); this.alias = gs(alias); } diff --git a/java/client/src/main/java/glide/api/models/commands/FT/FTCreateOptions.java b/java/client/src/main/java/glide/api/models/commands/FT/FTCreateOptions.java index 1cdb6c77d0..c407894cf8 100644 --- a/java/client/src/main/java/glide/api/models/commands/FT/FTCreateOptions.java +++ b/java/client/src/main/java/glide/api/models/commands/FT/FTCreateOptions.java @@ -54,7 +54,7 @@ public GlideString[] toArgs() { } public static class FTCreateOptionsBuilder { - public FTCreateOptionsBuilder prefixes(String[] prefixes) { + public FTCreateOptionsBuilder prefixes(@NonNull String[] prefixes) { this.prefixes = Stream.of(prefixes).map(GlideString::gs).toArray(GlideString[]::new); return this; } diff --git a/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java b/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java index c1fb528785..840a501da7 100644 --- a/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java +++ b/java/client/src/main/java/glide/api/models/commands/FT/FTProfileOptions.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; +import lombok.NonNull; /** Mandatory parameters for {@link FT#profile} command. */ public class FTProfileOptions { @@ -28,7 +29,7 @@ public enum QueryType { * @param queryType The query type. * @param commandLine Command arguments (not including index name). */ - public FTProfileOptions(QueryType queryType, GlideString[] commandLine) { + public FTProfileOptions(@NonNull QueryType queryType, @NonNull GlideString[] commandLine) { this(queryType, commandLine, false); } @@ -38,7 +39,7 @@ public FTProfileOptions(QueryType queryType, GlideString[] commandLine) { * @param queryType The query type. * @param commandLine Command arguments (not including index name). */ - public FTProfileOptions(QueryType queryType, String[] commandLine) { + public FTProfileOptions(@NonNull QueryType queryType, @NonNull String[] commandLine) { this(queryType, commandLine, false); } @@ -49,7 +50,8 @@ public FTProfileOptions(QueryType queryType, String[] commandLine) { * @param commandLine Command arguments (not including index name). * @param limited Either provide a full verbose output or some brief version (limited). */ - public FTProfileOptions(QueryType queryType, GlideString[] commandLine, boolean limited) { + public FTProfileOptions( + @NonNull QueryType queryType, @NonNull GlideString[] commandLine, boolean limited) { this.queryType = queryType; this.query = commandLine; this.limited = limited; @@ -62,7 +64,8 @@ public FTProfileOptions(QueryType queryType, GlideString[] commandLine, boolean * @param commandLine Command arguments (not including index name). * @param limited Either provide a full verbose output or some brief version (limited). */ - public FTProfileOptions(QueryType queryType, String[] commandLine, boolean limited) { + public FTProfileOptions( + @NonNull QueryType queryType, @NonNull String[] commandLine, boolean limited) { this( queryType, Stream.of(commandLine).map(GlideString::gs).toArray(GlideString[]::new), @@ -75,7 +78,7 @@ public FTProfileOptions(QueryType queryType, String[] commandLine, boolean limit * @param query The query itself. * @param options {@link FT#aggregate} options. */ - public FTProfileOptions(String query, FTAggregateOptions options) { + public FTProfileOptions(@NonNull String query, @NonNull FTAggregateOptions options) { this(gs(query), options); } @@ -85,7 +88,7 @@ public FTProfileOptions(String query, FTAggregateOptions options) { * @param query The query itself. * @param options {@link FT#aggregate} options. */ - public FTProfileOptions(GlideString query, FTAggregateOptions options) { + public FTProfileOptions(@NonNull GlideString query, @NonNull FTAggregateOptions options) { this(QueryType.AGGREGATE, concatenateArrays(new GlideString[] {query}, options.toArgs())); } @@ -95,7 +98,7 @@ public FTProfileOptions(GlideString query, FTAggregateOptions options) { * @param query The query itself. * @param options {@link FT#search} options. */ - public FTProfileOptions(String query, FTSearchOptions options) { + public FTProfileOptions(@NonNull String query, @NonNull FTSearchOptions options) { this(gs(query), options); } @@ -105,7 +108,7 @@ public FTProfileOptions(String query, FTSearchOptions options) { * @param query The query itself. * @param options {@link FT#search} options. */ - public FTProfileOptions(GlideString query, FTSearchOptions options) { + public FTProfileOptions(@NonNull GlideString query, @NonNull FTSearchOptions options) { this(QueryType.SEARCH, concatenateArrays(new GlideString[] {query}, options.toArgs())); } @@ -116,7 +119,8 @@ public FTProfileOptions(GlideString query, FTSearchOptions options) { * @param options {@link FT#aggregate} options. * @param limited Either provide a full verbose output or some brief version (limited). */ - public FTProfileOptions(String query, FTAggregateOptions options, boolean limited) { + public FTProfileOptions( + @NonNull String query, @NonNull FTAggregateOptions options, boolean limited) { this(gs(query), options, limited); } @@ -127,7 +131,8 @@ public FTProfileOptions(String query, FTAggregateOptions options, boolean limite * @param options {@link FT#search} options. * @param limited Either provide a full verbose output or some brief version (limited). */ - public FTProfileOptions(GlideString query, FTAggregateOptions options, boolean limited) { + public FTProfileOptions( + @NonNull GlideString query, @NonNull FTAggregateOptions options, boolean limited) { this( QueryType.AGGREGATE, concatenateArrays(new GlideString[] {query}, options.toArgs()), @@ -141,7 +146,8 @@ public FTProfileOptions(GlideString query, FTAggregateOptions options, boolean l * @param options {@link FT#aggregate} options. * @param limited Either provide a full verbose output or some brief version (limited). */ - public FTProfileOptions(String query, FTSearchOptions options, boolean limited) { + public FTProfileOptions( + @NonNull String query, @NonNull FTSearchOptions options, boolean limited) { this(gs(query), options, limited); } @@ -152,7 +158,8 @@ public FTProfileOptions(String query, FTSearchOptions options, boolean limited) * @param options {@link FT#search} options. * @param limited Either provide a full verbose output or some brief version (limited). */ - public FTProfileOptions(GlideString query, FTSearchOptions options, boolean limited) { + public FTProfileOptions( + @NonNull GlideString query, @NonNull FTSearchOptions options, boolean limited) { this(QueryType.SEARCH, concatenateArrays(new GlideString[] {query}, options.toArgs()), limited); } diff --git a/java/client/src/main/java/glide/api/models/commands/FT/FTSearchOptions.java b/java/client/src/main/java/glide/api/models/commands/FT/FTSearchOptions.java index 990eab2cb3..74407c64c0 100644 --- a/java/client/src/main/java/glide/api/models/commands/FT/FTSearchOptions.java +++ b/java/client/src/main/java/glide/api/models/commands/FT/FTSearchOptions.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.Map; import lombok.Builder; +import lombok.NonNull; import org.apache.commons.lang3.tuple.Pair; /** Mandatory parameters for {@link FT#search}. */ @@ -84,25 +85,26 @@ void count(boolean count) {} void identifiers(Map identifiers) {} /** Add a field to be returned. */ - public FTSearchOptionsBuilder addReturnField(String field) { + public FTSearchOptionsBuilder addReturnField(@NonNull String field) { this.identifiers$value.put(gs(field), null); return this; } /** Add a field with an alias to be returned. */ - public FTSearchOptionsBuilder addReturnField(String field, String alias) { + public FTSearchOptionsBuilder addReturnField(@NonNull String field, @NonNull String alias) { this.identifiers$value.put(gs(field), gs(alias)); return this; } /** Add a field to be returned. */ - public FTSearchOptionsBuilder addReturnField(GlideString field) { + public FTSearchOptionsBuilder addReturnField(@NonNull GlideString field) { this.identifiers$value.put(field, null); return this; } /** Add a field with an alias to be returned. */ - public FTSearchOptionsBuilder addReturnField(GlideString field, GlideString alias) { + public FTSearchOptionsBuilder addReturnField( + @NonNull GlideString field, @NonNull GlideString alias) { this.identifiers$value.put(field, alias); return this; } From 127f7f04a901f069dfeb130fdccbe0cb66f14d52 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 21 Oct 2024 16:14:48 -0700 Subject: [PATCH 3/4] cleanup Signed-off-by: Yury-Fridlyand --- .../integTest/src/test/java/glide/modules/VectorSearchTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/integTest/src/test/java/glide/modules/VectorSearchTests.java b/java/integTest/src/test/java/glide/modules/VectorSearchTests.java index 8888009c88..de76985f8e 100644 --- a/java/integTest/src/test/java/glide/modules/VectorSearchTests.java +++ b/java/integTest/src/test/java/glide/modules/VectorSearchTests.java @@ -67,6 +67,7 @@ public static void init() { @AfterAll @SneakyThrows public static void teardown() { + client.flushall(FlushMode.SYNC, ALL_PRIMARIES).get(); client.close(); } From 14ee140b26cb62c27f3b1545a47f6246107ed3dc Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Thu, 24 Oct 2024 09:41:38 -0700 Subject: [PATCH 4/4] docs Signed-off-by: Yury-Fridlyand --- .../glide/api/commands/servermodules/FT.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/java/client/src/main/java/glide/api/commands/servermodules/FT.java b/java/client/src/main/java/glide/api/commands/servermodules/FT.java index adf70d5549..aa48da11d1 100644 --- a/java/client/src/main/java/glide/api/commands/servermodules/FT.java +++ b/java/client/src/main/java/glide/api/commands/servermodules/FT.java @@ -483,6 +483,16 @@ public static CompletableFuture[]> aggregate( * @param options Querying and profiling parameters - see {@link FTProfileOptions}. * @return A two-element array. The first element contains results of query being profiled, the * second element stores profiling information. + * @example + *
{@code
+     * var options = FTSearchOptions.builder().params(Map.of(
+     *         gs("query_vec"),
+     *         gs(new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0 })))
+     *     .build();
+     * var result = FT.profile(client, "myIndex", new FTProfileOptions("*=>[KNN 2 @VEC $query_vec]", options)).get();
+     * // result[0] contains `FT.SEARCH` response with the given options and query
+     * // result[1] contains profiling data as a `Map`
+     * }
*/ public static CompletableFuture profile( @NonNull BaseClient client, @NonNull String indexName, @NonNull FTProfileOptions options) { @@ -497,6 +507,13 @@ public static CompletableFuture profile( * @param options Querying and profiling parameters - see {@link FTProfileOptions}. * @return A two-element array. The first element contains results of query being profiled, the * second element stores profiling information. + * @example + *
{@code
+     * var commandLine = new String[] { "*", "LOAD", "1", "__key", "GROUPBY", "1", "@condition", "REDUCE", "COUNT", "0", "AS", "bicylces" };
+     * var result = FT.profile(client, gs("myIndex"), new FTProfileOptions(QueryType.AGGREGATE, commandLine)).get();
+     * // result[0] contains `FT.AGGREGATE` response with the given command line
+     * // result[1] contains profiling data as a `Map`
+     * }
*/ public static CompletableFuture profile( @NonNull BaseClient client,