Skip to content

Add support for STRALGO #1282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,11 @@ public RedisFuture<Long> strlen(K key) {
return dispatch(commandBuilder.strlen(key));
}

@Override
public RedisFuture<StringMatchResult> stralgoLcs(StrAlgoArgs args) {
return dispatch(commandBuilder.stralgoLcs(args));
}

@Override
public RedisFuture<Set<V>> sunion(K... keys) {
return dispatch(commandBuilder.sunion(keys));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,11 @@ public Mono<Long> strlen(K key) {
return createMono(() -> commandBuilder.strlen(key));
}

@Override
public Mono<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs) {
return createMono(() -> commandBuilder.stralgoLcs(strAlgoArgs));
}

@Override
public Flux<V> sunion(K... keys) {
return createDissolvingFlux(() -> commandBuilder.sunion(keys));
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/io/lettuce/core/RedisCommandBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -2013,6 +2013,14 @@ Command<K, V, Long> strlen(K key) {
return createCommand(STRLEN, new IntegerOutput<>(codec), key);
}

Command<K, V, StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs) {
LettuceAssert.notNull(strAlgoArgs, "StrAlgoArgs " + MUST_NOT_BE_NULL);

CommandArgs<K, V> args = new CommandArgs<>(codec);
strAlgoArgs.build(args);
return createCommand(STRALGO, new StringMatchResultOutput<>(codec, strAlgoArgs.isWithIdx()), args);
}

Command<K, V, Set<V>> sunion(K... keys) {
notEmpty(keys);

Expand Down
168 changes: 168 additions & 0 deletions src/main/java/io/lettuce/core/StrAlgoArgs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright 2011-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.lettuce.core;

import io.lettuce.core.internal.LettuceAssert;
import io.lettuce.core.protocol.CommandArgs;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
* Argument list builder for the Redis <a href="http://redis.io/commands/stralgo">STRALGO</a> command.
* Static import the methods from {@link StrAlgoArgs.Builder} and call the methods: {@code block(…)} .
* <p>
* {@link StrAlgoArgs} is a mutable object and instances should be used only once to avoid shared mutable state.
*
* @author dengliming
* @since 6.0
*/
public class StrAlgoArgs implements CompositeArgument {

private boolean justLen;
private int minMatchLen;
private boolean withMatchLen;
private boolean withIdx;
private By by = By.STRINGS;
private String[] keys;
private Charset charset = StandardCharsets.UTF_8;

/**
* Builder entry points for {@link StrAlgoArgs}.
*/
public static class Builder {

/**
* Utility constructor.
*/
private Builder() {
}

/**
* Creates new {@link StrAlgoArgs} by keys.
*
* @return new {@link StrAlgoArgs} with {@literal By KEYS} set.
*/
public static StrAlgoArgs keys(String... keys) {
return new StrAlgoArgs().by(By.KEYS, keys);
}

/**
* Creates new {@link StrAlgoArgs} by strings.
*
* @return new {@link StrAlgoArgs} with {@literal By STRINGS} set.
*/
public static StrAlgoArgs strings(String... strings) {
return new StrAlgoArgs().by(By.STRINGS, strings);
}

/**
* Creates new {@link StrAlgoArgs} by strings and charset.
*
* @return new {@link StrAlgoArgs} with {@literal By STRINGS} set.
*/
public static StrAlgoArgs strings(Charset charset, String... strings) {
return new StrAlgoArgs().by(By.STRINGS, strings).charset(charset);
}
}
/**
* restrict the list of matches to the ones of a given minimal length.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs minMatchLen(int minMatchLen) {
this.minMatchLen = minMatchLen;
return this;
}

/**
* Request just the length of the match for results.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs justLen() {
justLen = true;
return this;
}

/**
* Request match len for results.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs withMatchLen() {
withMatchLen = true;
return this;
}

/**
* Request match position in each strings for results.
*
* @return {@code this} {@link StrAlgoArgs}.
*/
public StrAlgoArgs withIdx() {
withIdx = true;
return this;
}

public StrAlgoArgs by(By by, String... keys) {
this.by = by;
this.keys = keys;
return this;
}

public boolean isWithIdx() {
return withIdx;
}

public StrAlgoArgs charset(Charset charset) {
this.charset = charset;
return this;
}

public enum By {
STRINGS, KEYS
}

public <K, V> void build(CommandArgs<K, V> args) {
LettuceAssert.notEmpty(keys, "strings or keys must be not empty");

args.add("LCS");
args.add(by.name());
for (String key : keys) {
if (by == By.STRINGS) {
args.add(key.getBytes(charset));
} else {
args.add(key);
}
}
if (justLen) {
args.add("LEN");
}
if (withIdx) {
args.add("IDX");
}

if (minMatchLen > 0) {
args.add("MINMATCHLEN");
args.add(minMatchLen);
}

if (withMatchLen) {
args.add("WITHMATCHLEN");
}
}
}
118 changes: 118 additions & 0 deletions src/main/java/io/lettuce/core/StringMatchResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2011-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.lettuce.core;

import java.util.ArrayList;
import java.util.List;

/**
* Result for STRALGO command
*
* @author dengliming
*/
public class StringMatchResult {

private String matchString;
private List<MatchedPosition> matches = new ArrayList<>();
private long len;

public StringMatchResult matchString(String matchString) {
this.matchString = matchString;
return this;
}

public StringMatchResult addMatch(MatchedPosition match) {
this.matches.add(match);
return this;
}

public StringMatchResult len(long len) {
this.len = len;
return this;
}

public String getMatchString() {
return matchString;
}

public List<MatchedPosition> getMatches() {
return matches;
}

public long getLen() {
return len;
}

/**
* match position in each strings
*/
public static class MatchedPosition {
private Position a;
private Position b;
private long matchLen;

public MatchedPosition(Position a, Position b, long matchLen) {
this.a = a;
this.b = b;
this.matchLen = matchLen;
}

public Position getA() {
return a;
}

public void setA(Position a) {
this.a = a;
}

public Position getB() {
return b;
}

public void setB(Position b) {
this.b = b;
}

public long getMatchLen() {
return matchLen;
}

public void setMatchLen(long matchLen) {
this.matchLen = matchLen;
}
}

/**
* position range
*/
public static class Position {
private final long start;
private final long end;

public Position(long start, long end) {
this.start = start;
this.end = end;
}

public long getStart() {
return start;
}

public long getEnd() {
return end;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import io.lettuce.core.RedisFuture;
import io.lettuce.core.SetArgs;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.StrAlgoArgs;
import io.lettuce.core.StringMatchResult;

/**
* Asynchronous executed commands for Strings.
Expand Down Expand Up @@ -374,4 +376,13 @@ public interface RedisStringAsyncCommands<K, V> {
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
*/
RedisFuture<Long> strlen(K key);

/**
* The STRALGO implements complex algorithms that operate on strings.
*
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
* @param strAlgoArgs
* @return StringMatchResult
*/
RedisFuture<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import io.lettuce.core.SetArgs;
import io.lettuce.core.Value;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.StrAlgoArgs;
import io.lettuce.core.StringMatchResult;

/**
* Reactive executed commands for Strings.
Expand Down Expand Up @@ -375,4 +377,13 @@ public interface RedisStringReactiveCommands<K, V> {
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
*/
Mono<Long> strlen(K key);

/**
* The STRALGO implements complex algorithms that operate on strings.
*
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
* @param strAlgoArgs
* @return StringMatchResult
*/
Mono<StringMatchResult> stralgoLcs(StrAlgoArgs strAlgoArgs);
}
11 changes: 11 additions & 0 deletions src/main/java/io/lettuce/core/api/sync/RedisStringCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import io.lettuce.core.KeyValue;
import io.lettuce.core.SetArgs;
import io.lettuce.core.output.KeyValueStreamingChannel;
import io.lettuce.core.StrAlgoArgs;
import io.lettuce.core.StringMatchResult;

/**
* Synchronous executed commands for Strings.
Expand Down Expand Up @@ -373,4 +375,13 @@ public interface RedisStringCommands<K, V> {
* @return Long integer-reply the length of the string at {@code key}, or {@code 0} when {@code key} does not exist.
*/
Long strlen(K key);

/**
* The STRALGO implements complex algorithms that operate on strings.
*
* Right now the only algorithm implemented is the LCS algorithm (longest common substring).
* @param strAlgoArgs
* @return StringMatchResult
*/
StringMatchResult stralgoLcs(StrAlgoArgs strAlgoArgs);
}
Loading