diff --git a/docs/jedis5-breaking.md b/docs/jedis5-breaking.md index 752105e3ba..1e4c12b6fa 100644 --- a/docs/jedis5-breaking.md +++ b/docs/jedis5-breaking.md @@ -45,6 +45,7 @@ - `KeyedListElement` - `TSKeyValue` - `TSKeyedElements` + - `Limit` - `STREAM_AUTO_CLAIM_ID_RESPONSE` in BuilderFactory has been renamed to `STREAM_AUTO_CLAIM_JUSTID_RESPONSE`. @@ -67,6 +68,20 @@ - `getParams()` method is removed from `SortingParams` class. +- `addCommandEncodedArguments` and `addCommandBinaryArguments` methods have been removed from `FieldName` class. + +- `limit` and `getArgs` methods have been removed from `Group` class. + +- `Reducer` abstract class is refactored: + - `Reducer(String field)` constructored is removed; `Reducer(String name, String field)` constructor is added. + - `Reducer(String name)` constructored is added; it will cause runtime error with older `Reducer(String field)` constructor. + - `getName` method is removed. + - `getAlias` method is removed. + - `setAlias` method is removed; use `as` method. + - `setAliasAsField` method is removed. + - `getOwnArgs` method is now abstract. + - `getArgs` method is removed. + - All variants of `blmpop` and `bzmpop` methods now take `double timeout` parameter instead of `long timeout` parameter. This is breaking ONLY IF you are using `Long` for timeout. diff --git a/src/main/java/redis/clients/jedis/search/FTSearchParams.java b/src/main/java/redis/clients/jedis/search/FTSearchParams.java index e88926e1da..2f3d6394de 100644 --- a/src/main/java/redis/clients/jedis/search/FTSearchParams.java +++ b/src/main/java/redis/clients/jedis/search/FTSearchParams.java @@ -9,6 +9,7 @@ import redis.clients.jedis.args.GeoUnit; import redis.clients.jedis.args.SortingOrder; import redis.clients.jedis.params.IParams; +import redis.clients.jedis.util.LazyRawable; /** * Query represents query parameters and filters to load results from the engine diff --git a/src/main/java/redis/clients/jedis/search/FieldName.java b/src/main/java/redis/clients/jedis/search/FieldName.java index f4b8b3ffb2..452b0b8d61 100644 --- a/src/main/java/redis/clients/jedis/search/FieldName.java +++ b/src/main/java/redis/clients/jedis/search/FieldName.java @@ -3,15 +3,10 @@ import java.util.List; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.params.IParams; - -import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.search.SearchProtocol.SearchKeyword; public class FieldName implements IParams { - private static final String AS_ENCODED = "AS"; - private static final byte[] AS_BINARY = SafeEncoder.encode(AS_ENCODED); - private static final byte[] AS = SafeEncoder.encode("AS"); - private final String name; private String attribute; @@ -35,36 +30,25 @@ public FieldName as(String attribute) { return this; } - public int addCommandEncodedArguments(List args) { + public int addCommandArguments(List args) { args.add(name); if (attribute == null) { return 1; } - args.add(AS_ENCODED); + args.add(SearchKeyword.AS); args.add(attribute); return 3; } - public int addCommandBinaryArguments(List args) { - args.add(SafeEncoder.encode(name)); - if (attribute == null) { - return 1; - } - - args.add(AS_BINARY); - args.add(SafeEncoder.encode(attribute)); - return 3; - } - public int addCommandArguments(CommandArguments args) { - args.add(SafeEncoder.encode(name)); + args.add(name); if (attribute == null) { return 1; } - args.add(AS); - args.add(SafeEncoder.encode(attribute)); + args.add(SearchKeyword.AS); + args.add(attribute); return 3; } diff --git a/src/main/java/redis/clients/jedis/search/Query.java b/src/main/java/redis/clients/jedis/search/Query.java index d251697a76..f4de2f78a2 100644 --- a/src/main/java/redis/clients/jedis/search/Query.java +++ b/src/main/java/redis/clients/jedis/search/Query.java @@ -9,6 +9,7 @@ import redis.clients.jedis.Protocol; import redis.clients.jedis.params.IParams; import redis.clients.jedis.search.SearchProtocol.SearchKeyword; +import redis.clients.jedis.util.LazyRawable; import redis.clients.jedis.util.SafeEncoder; /** diff --git a/src/main/java/redis/clients/jedis/search/SearchProtocol.java b/src/main/java/redis/clients/jedis/search/SearchProtocol.java index 8b8d0875d6..36780b569b 100644 --- a/src/main/java/redis/clients/jedis/search/SearchProtocol.java +++ b/src/main/java/redis/clients/jedis/search/SearchProtocol.java @@ -56,7 +56,7 @@ public enum SearchKeyword implements Rawable { SCORE_FIELD, SCORER, PARAMS, AS, DIALECT, SLOP, TIMEOUT, INORDER, EXPANDER, MAXTEXTFIELDS, SKIPINITIALSCAN, WITHSUFFIXTRIE, NOSTEM, NOINDEX, PHONETIC, WEIGHT, CASESENSITIVE, LOAD, APPLY, GROUPBY, MAXIDLE, WITHCURSOR, DISTANCE, TERMS, INCLUDE, EXCLUDE, - SEARCH, AGGREGATE, QUERY, LIMITED, COUNT; + SEARCH, AGGREGATE, QUERY, LIMITED, COUNT, REDUCE; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java b/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java index d7b40d47fd..13d6f9a270 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java +++ b/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java @@ -6,17 +6,19 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.StringJoiner; +import redis.clients.jedis.Protocol; import redis.clients.jedis.search.FieldName; -import redis.clients.jedis.util.SafeEncoder; +import redis.clients.jedis.search.SearchProtocol.SearchKeyword; +import redis.clients.jedis.util.LazyRawable; /** * @author Guy Korland */ public class AggregationBuilder { - private final List args = new ArrayList<>(); + private final List args = new ArrayList<>(); + private Integer dialect; private boolean isWithCursor = false; public AggregationBuilder(String query) { @@ -32,26 +34,27 @@ public AggregationBuilder load(String... fields) { } public AggregationBuilder load(FieldName... fields) { - args.add("LOAD"); - final int loadCountIndex = args.size(); - args.add(null); + args.add(SearchKeyword.LOAD); + LazyRawable rawLoadCount = new LazyRawable(); + args.add(rawLoadCount); int loadCount = 0; for (FieldName fn : fields) { - loadCount += fn.addCommandEncodedArguments(args); + loadCount += fn.addCommandArguments(args); } - args.set(loadCountIndex, Integer.toString(loadCount)); + rawLoadCount.setRaw(Protocol.toByteArray(loadCount)); return this; } public AggregationBuilder loadAll() { - args.add("LOAD"); - args.add("*"); + args.add(SearchKeyword.LOAD); + args.add(Protocol.BYTES_ASTERISK); return this; } public AggregationBuilder limit(int offset, int count) { - Limit limit = new Limit(offset, count); - limit.addArgs(args); + args.add(SearchKeyword.LIMIT); + args.add(offset); + args.add(count); return this; } @@ -60,22 +63,12 @@ public AggregationBuilder limit(int count) { } public AggregationBuilder sortBy(SortedField... fields) { - args.add("SORTBY"); + args.add(SearchKeyword.SORTBY); args.add(Integer.toString(fields.length * 2)); for (SortedField field : fields) { args.add(field.getField()); args.add(field.getOrder()); } - - return this; - } - - public AggregationBuilder sortBy(int max, SortedField... fields) { - sortBy(fields); - if (max > 0) { - args.add("MAX"); - args.add(Integer.toString(max)); - } return this; } @@ -87,20 +80,51 @@ public AggregationBuilder sortByDesc(String field) { return sortBy(SortedField.desc(field)); } + /** + * {@link AggregationBuilder#sortBy(redis.clients.jedis.search.aggr.SortedField...)} + * (or {@link AggregationBuilder#sortByAsc(java.lang.String)} + * or {@link AggregationBuilder#sortByDesc(java.lang.String)}) + * MUST BE called JUST BEFORE this. + * @param max limit + * @return this + */ + public AggregationBuilder sortByMax(int max) { + args.add(SearchKeyword.MAX); + args.add(max); + return this; + } + + /** + * Shortcut to {@link AggregationBuilder#sortBy(redis.clients.jedis.search.aggr.SortedField...)} + * and {@link AggregationBuilder#sortByMax(int)}. + * @param max limit + * @param fields sorted fields + * @return this + */ + public AggregationBuilder sortBy(int max, SortedField... fields) { + sortBy(fields); + sortByMax(max); + return this; + } + public AggregationBuilder apply(String projection, String alias) { - args.add("APPLY"); + args.add(SearchKeyword.APPLY); args.add(projection); - args.add("AS"); + args.add(SearchKeyword.AS); args.add(alias); return this; } + public AggregationBuilder groupBy(Group group) { + args.add(SearchKeyword.GROUPBY); + group.addArgs(args); + return this; + } + public AggregationBuilder groupBy(Collection fields, Collection reducers) { String[] fieldsArr = new String[fields.size()]; Group g = new Group(fields.toArray(fieldsArr)); - for (Reducer r : reducers) { - g.reduce(r); - } + reducers.forEach((r) -> g.reduce(r)); groupBy(g); return this; } @@ -109,65 +133,61 @@ public AggregationBuilder groupBy(String field, Reducer... reducers) { return groupBy(Collections.singletonList(field), Arrays.asList(reducers)); } - public AggregationBuilder groupBy(Group group) { - args.add("GROUPBY"); - group.addArgs(args); + public AggregationBuilder filter(String expression) { + args.add(SearchKeyword.FILTER); + args.add(expression); return this; } - public AggregationBuilder filter(String expression) { - args.add("FILTER"); - args.add(expression); + public AggregationBuilder cursor(int count) { + isWithCursor = true; + args.add(SearchKeyword.WITHCURSOR); + args.add(SearchKeyword.COUNT); + args.add(count); return this; } public AggregationBuilder cursor(int count, long maxIdle) { isWithCursor = true; - if (count > 0) { - args.add("WITHCURSOR"); - args.add("COUNT"); - args.add(Integer.toString(count)); - if (maxIdle < Long.MAX_VALUE && maxIdle >= 0) { - args.add("MAXIDLE"); - args.add(Long.toString(maxIdle)); - } - } + args.add(SearchKeyword.WITHCURSOR); + args.add(SearchKeyword.COUNT); + args.add(count); + args.add(SearchKeyword.MAXIDLE); + args.add(maxIdle); return this; } public AggregationBuilder verbatim() { - args.add("VERBATIM"); + args.add(SearchKeyword.VERBATIM); return this; } public AggregationBuilder timeout(long timeout) { - if (timeout >= 0) { - args.add("TIMEOUT"); - args.add(Long.toString(timeout)); - } + args.add(SearchKeyword.TIMEOUT); + args.add(timeout); return this; } public AggregationBuilder params(Map params) { - if (params.size() >= 1) { - args.add("PARAMS"); - args.add(Integer.toString(params.size() * 2)); - for (Map.Entry entry : params.entrySet()) { - args.add(entry.getKey()); - args.add(String.valueOf(entry.getValue())); - } - } - + args.add(SearchKeyword.PARAMS); + args.add(params.size() * 2); + params.forEach((k, v) -> { + args.add(k); + args.add(v); + }); return this; } public AggregationBuilder dialect(int dialect) { - args.add("DIALECT"); - args.add(Integer.toString(dialect)); + this.dialect = dialect; return this; } - public List getArgs() { + public List getArgs() { + if (dialect != null) { + args.add(SearchKeyword.DIALECT); + args.add(dialect); + } return Collections.unmodifiableList(args); } diff --git a/src/main/java/redis/clients/jedis/search/aggr/Group.java b/src/main/java/redis/clients/jedis/search/aggr/Group.java index a60cb5ac0c..6ef9220845 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Group.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Group.java @@ -9,9 +9,8 @@ */ public class Group { - private final List reducers = new ArrayList<>(); private final List fields = new ArrayList<>(); - private Limit limit = new Limit(0, 0); + private final List reducers = new ArrayList<>(); public Group(String... fields) { this.fields.addAll(Arrays.asList(fields)); @@ -22,30 +21,11 @@ public Group reduce(Reducer r) { return this; } - public Group limit(Limit limit) { - this.limit = limit; - return this; - } + public void addArgs(List args) { - public void addArgs(List args) { - args.add(Integer.toString(fields.size())); + args.add(fields.size()); args.addAll(fields); - for (Reducer r : reducers) { - args.add("REDUCE"); - args.add(r.getName()); - r.addArgs(args); - String alias = r.getAlias(); - if (alias != null && !alias.isEmpty()) { - args.add("AS"); - args.add(alias); - } - } - args.addAll(limit.getArgs()); - } - public List getArgs() { - List args = new ArrayList<>(); - addArgs(args); - return args; + reducers.forEach((r) -> r.addArgs(args)); } } diff --git a/src/main/java/redis/clients/jedis/search/aggr/Limit.java b/src/main/java/redis/clients/jedis/search/aggr/Limit.java deleted file mode 100644 index 9f512c9713..0000000000 --- a/src/main/java/redis/clients/jedis/search/aggr/Limit.java +++ /dev/null @@ -1,39 +0,0 @@ -package redis.clients.jedis.search.aggr; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Created by mnunberg on 2/22/18. - */ -public class Limit { - - public static final Limit NO_LIMIT = new Limit(0, 0); - - private final int offset; - private final int count; - - public Limit(int offset, int count) { - this.offset = offset; - this.count = count; - } - - public void addArgs(List args) { - if (count == 0) { - return; - } - args.add("LIMIT"); - args.add(Integer.toString(offset)); - args.add(Integer.toString(count)); - } - - public List getArgs() { - if (count == 0) { - return Collections.emptyList(); - } - List ll = new ArrayList<>(3); - addArgs(ll); - return ll; - } -} diff --git a/src/main/java/redis/clients/jedis/search/aggr/Reducer.java b/src/main/java/redis/clients/jedis/search/aggr/Reducer.java index 858fc0f7c2..21f7060ee7 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Reducer.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Reducer.java @@ -1,8 +1,7 @@ package redis.clients.jedis.search.aggr; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import redis.clients.jedis.search.SearchProtocol.SearchKeyword; /** * Created by mnunberg on 2/22/18. @@ -11,61 +10,44 @@ */ public abstract class Reducer { - private String alias; + private final String name; private final String field; + private String alias; - protected Reducer(String field) { - this.field = field; - this.alias = null; - } - - protected Reducer() { - this(null); - } - - protected List getOwnArgs() { - if (field == null) { - return Collections.emptyList(); - } - List ret = new ArrayList<>(); - ret.add(field); - return ret; + protected Reducer(String name) { + this.name = name; + this.field = null; } - /** - * @return The name of the reducer - */ - public abstract String getName(); - - public final String getAlias() { - return alias; + protected Reducer(String name, String field) { + this.name = name; + this.field = field; } - public final Reducer setAlias(String alias) { + public final Reducer as(String alias) { this.alias = alias; return this; } - public final Reducer as(String alias) { - return setAlias(alias); - } + protected abstract List getOwnArgs(); - public final Reducer setAliasAsField() { - if (field == null || field.isEmpty()) { - throw new IllegalArgumentException("Cannot set to field name since no field exists"); - } - return setAlias(field); - } + public final void addArgs(List args) { - public void addArgs(List args) { - List ownArgs = getOwnArgs(); - args.add(Integer.toString(ownArgs.size())); + args.add(SearchKeyword.REDUCE); + args.add(name); + + List ownArgs = getOwnArgs(); + if (field != null) { + args.add(1 + ownArgs.size()); + args.add(field); + } else { + args.add(ownArgs.size()); + } args.addAll(ownArgs); - } - public final List getArgs() { - List args = new ArrayList<>(); - addArgs(args); - return args; + if (alias != null) { + args.add(SearchKeyword.AS); + args.add(alias); + } } } diff --git a/src/main/java/redis/clients/jedis/search/aggr/Reducers.java b/src/main/java/redis/clients/jedis/search/aggr/Reducers.java index 4ac4d4ccfc..e24dadc871 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/Reducers.java +++ b/src/main/java/redis/clients/jedis/search/aggr/Reducers.java @@ -1,5 +1,7 @@ package redis.clients.jedis.search.aggr; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -8,19 +10,17 @@ public class Reducers { public static Reducer count() { - return new Reducer() { - @Override - public String getName() { - return "COUNT"; + return new Reducer("COUNT") { + @Override protected List getOwnArgs() { + return Collections.emptyList(); } }; } private static Reducer singleFieldReducer(String name, String field) { - return new Reducer(field) { - @Override - public String getName() { - return name; + return new Reducer(name, field) { + @Override protected List getOwnArgs() { + return Collections.emptyList(); } }; } @@ -54,21 +54,17 @@ public static Reducer stddev(String field) { } public static Reducer quantile(String field, double percentile) { - return new Reducer(field) { - @Override - public String getName() { - return "QUANTILE"; - } - - @Override - protected List getOwnArgs() { - List args = super.getOwnArgs(); - args.add(Double.toString(percentile)); - return args; + return new Reducer("QUANTILE", field) { + @Override protected List getOwnArgs() { + return Arrays.asList(percentile); } }; } + public static Reducer first_value(String field) { + return singleFieldReducer("FIRST_VALUE", field); + } + /** * REDUCE FIRST_VALUE {nargs} {property} [BY {property} [ASC|DESC]] * @@ -77,45 +73,21 @@ protected List getOwnArgs() { * @return Reducer */ public static Reducer first_value(String field, SortedField sortBy) { - return new Reducer(field) { - @Override - public String getName() { - return "FIRST_VALUE"; - } - - @Override - protected List getOwnArgs() { - List args = super.getOwnArgs(); - if (sortBy != null) { - args.add("BY"); - args.add(sortBy.getField()); - args.add(sortBy.getOrder()); - } - return args; + return new Reducer("FIRST_VALUE", field) { + @Override protected List getOwnArgs() { + return Arrays.asList("BY", sortBy.getField(), sortBy.getOrder()); } }; } - public static Reducer first_value(String field) { - return first_value(field, null); - } - public static Reducer to_list(String field) { return singleFieldReducer("TOLIST", field); } public static Reducer random_sample(String field, int size) { - return new Reducer(field) { - @Override - public String getName() { - return "RANDOM_SAMPLE"; - } - - @Override - protected List getOwnArgs() { - List args = super.getOwnArgs(); - args.add(Integer.toString(size)); - return args; + return new Reducer("RANDOM_SAMPLE", field) { + @Override protected List getOwnArgs() { + return Arrays.asList(size); } }; } diff --git a/src/main/java/redis/clients/jedis/search/LazyRawable.java b/src/main/java/redis/clients/jedis/util/LazyRawable.java similarity index 70% rename from src/main/java/redis/clients/jedis/search/LazyRawable.java rename to src/main/java/redis/clients/jedis/util/LazyRawable.java index bc1a346800..74a5820e87 100644 --- a/src/main/java/redis/clients/jedis/search/LazyRawable.java +++ b/src/main/java/redis/clients/jedis/util/LazyRawable.java @@ -1,8 +1,8 @@ -package redis.clients.jedis.search; +package redis.clients.jedis.util; import redis.clients.jedis.args.Rawable; -class LazyRawable implements Rawable { +public class LazyRawable implements Rawable { private byte[] raw = null;