CommandObjectsSearchAndQueryCommandsTest.java
package redis.clients.jedis.commands.commandobjects;
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.RedisProtocol;
import redis.clients.jedis.args.SortingOrder;
import redis.clients.jedis.json.Path2;
import redis.clients.jedis.resps.Tuple;
import redis.clients.jedis.search.Document;
import redis.clients.jedis.search.FTCreateParams;
import redis.clients.jedis.search.FTSearchParams;
import redis.clients.jedis.search.FTSpellCheckParams;
import redis.clients.jedis.search.IndexDataType;
import redis.clients.jedis.search.IndexDefinition;
import redis.clients.jedis.search.IndexOptions;
import redis.clients.jedis.search.Query;
import redis.clients.jedis.search.Schema;
import redis.clients.jedis.search.SearchResult;
import redis.clients.jedis.search.aggr.AggregationBuilder;
import redis.clients.jedis.search.aggr.AggregationResult;
import redis.clients.jedis.search.aggr.Reducers;
import redis.clients.jedis.search.schemafields.NumericField;
import redis.clients.jedis.search.schemafields.SchemaField;
import redis.clients.jedis.search.schemafields.TagField;
import redis.clients.jedis.search.schemafields.TextField;
/**
* Tests related to <a href="https://redis.io/commands/?group=search">Search and query</a> commands.
*/
public class CommandObjectsSearchAndQueryCommandsTest extends CommandObjectsModulesTestBase {
public CommandObjectsSearchAndQueryCommandsTest(RedisProtocol protocol) {
super(protocol);
}
@Test
public void testFtSearchHash() {
String indexName = "booksIndex";
IndexDefinition indexDefinition =
new IndexDefinition(IndexDefinition.Type.HASH).setPrefixes("books:");
IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition(indexDefinition);
Schema schema = new Schema()
.addField(new Schema.Field("title", Schema.FieldType.TEXT))
.addField(new Schema.Field("price", Schema.FieldType.NUMERIC));
String create = exec(commandObjects.ftCreate(indexName, indexOptions, schema));
assertThat(create, equalTo("OK"));
// Set individual fields.
String book1000 = "books:1000";
Long hset = exec(commandObjects.hsetObject(book1000, "title", "Redis in Action"));
assertThat(hset, equalTo(1L));
hset = exec(commandObjects.hsetObject(book1000, "price", 17.99));
assertThat(hset, equalTo(1L));
hset = exec(commandObjects.hsetObject(book1000, "author", "John Doe"));
assertThat(hset, equalTo(1L));
// Set multiple fields.
Map<String, Object> hash = new HashMap<>();
hash.put("title", "Redis Essentials");
hash.put("price", 19.99);
hash.put("author", "Jane Doe");
String book1200 = "books:1200";
Long hsetMultiple = exec(commandObjects.hsetObject(book1200, hash));
assertThat(hsetMultiple, equalTo(3L));
// Text search.
SearchResult search = exec(commandObjects.ftSearch(indexName, "Action"));
assertThat(search.getTotalResults(), equalTo(1L));
assertThat(search.getDocuments(), hasSize(1));
Document document = search.getDocuments().get(0);
assertThat(document.getId(), equalTo(book1000));
assertThat(document.get("title"), equalTo("Redis in Action"));
assertThat(document.get("price"), equalTo("17.99"));
assertThat(document.get("author"), equalTo("John Doe"));
// Price range search.
SearchResult searchByPrice = exec(commandObjects.ftSearch(indexName, "@price:[19 +inf]"));
assertThat(searchByPrice.getTotalResults(), equalTo(1L));
assertThat(searchByPrice.getDocuments(), hasSize(1));
Document documentByPrice = searchByPrice.getDocuments().get(0);
assertThat(documentByPrice.getId(), equalTo(book1200));
assertThat(documentByPrice.get("title"), equalTo("Redis Essentials"));
assertThat(documentByPrice.get("price"), equalTo("19.99"));
assertThat(documentByPrice.get("author"), equalTo("Jane Doe"));
// Price range search with sorting.
FTSearchParams ftSearchParams = new FTSearchParams().sortBy("price", SortingOrder.DESC);
SearchResult searchByPriceWithParams = exec(commandObjects.ftSearch(indexName, "@price:[10 20]", ftSearchParams));
assertThat(searchByPriceWithParams.getTotalResults(), equalTo(2L));
assertThat(searchByPriceWithParams.getDocuments(), hasSize(2));
assertThat(searchByPriceWithParams.getDocuments().stream().map(Document::getId).collect(Collectors.toList()),
contains(book1200, book1000));
Query query = new Query()
.addFilter(new Query.NumericFilter("price", 19.0, 20.0))
.returnFields("price", "title");
SearchResult searchByPriceWithQuery = exec(commandObjects.ftSearch(indexName, query));
assertThat(searchByPriceWithQuery.getTotalResults(), equalTo(1L));
assertThat(searchByPriceWithQuery.getDocuments(), hasSize(1));
Document documentByPriceWithQuery = searchByPriceWithQuery.getDocuments().get(0);
assertThat(documentByPriceWithQuery.getId(), equalTo(book1200));
assertThat(documentByPriceWithQuery.get("title"), equalTo("Redis Essentials"));
assertThat(documentByPriceWithQuery.get("price"), equalTo("19.99"));
assertThat(documentByPriceWithQuery.get("author"), nullValue());
}
@Test
public void testFtSearchJson() {
String indexName = "testIndex";
IndexDefinition indexDefinition = new IndexDefinition(IndexDefinition.Type.JSON)
.setPrefixes("books:");
IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition(indexDefinition);
Schema schema = new Schema()
.addField(new Schema.Field("$.title", Schema.FieldType.TEXT))
.addField(new Schema.Field("$.price", Schema.FieldType.NUMERIC));
String create = exec(commandObjects.ftCreate(indexName, indexOptions, schema));
assertThat(create, equalTo("OK"));
Map<String, Object> hash = new HashMap<>();
hash.put("title", "Redis in Action");
hash.put("price", 17.99);
hash.put("author", "John Doe");
String jsonSet = exec(commandObjects.jsonSet("books:1000", Path2.ROOT_PATH, new JSONObject(hash)));
assertThat(jsonSet, equalTo("OK"));
Map<String, Object> hash2 = new HashMap<>();
hash2.put("title", "Redis Essentials");
hash2.put("price", 19.99);
hash2.put("author", "Jane Doe");
String jsonSet2 = exec(commandObjects.jsonSet("books:1200", Path2.ROOT_PATH, new JSONObject(hash2)));
assertThat(jsonSet2, equalTo("OK"));
SearchResult searchResult = exec(commandObjects.ftSearch(indexName, "Action"));
assertThat(searchResult.getTotalResults(), equalTo(1L));
assertThat(searchResult.getDocuments(), hasSize(1));
Document document = searchResult.getDocuments().get(0);
assertThat(document.getId(), equalTo("books:1000"));
assertThat(document.get("$"), equalTo("{\"title\":\"Redis in Action\",\"price\":17.99,\"author\":\"John Doe\"}"));
}
@Test
public void testFtCreateWithParams() {
String indexName = "booksIndex";
SchemaField[] schema = {
TextField.of("$.title").as("title"),
NumericField.of("$.price").as("price")
};
FTCreateParams createParams = FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("books:");
String createResult = exec(commandObjects.ftCreate(indexName, createParams, Arrays.asList(schema)));
assertThat(createResult, equalTo("OK"));
JSONObject bookRedisInAction = new JSONObject();
bookRedisInAction.put("title", "Redis in Action");
bookRedisInAction.put("price", 17.99);
bookRedisInAction.put("author", "John Doe");
String jsonSet = exec(commandObjects.jsonSet("books:1000", Path2.ROOT_PATH, bookRedisInAction));
assertThat(jsonSet, equalTo("OK"));
JSONObject bookRedisEssentials = new JSONObject();
bookRedisEssentials.put("title", "Redis Essentials");
bookRedisEssentials.put("price", 19.99);
bookRedisEssentials.put("author", "Jane Doe");
String jsonSet2 = exec(commandObjects.jsonSet("books:1200", Path2.ROOT_PATH, bookRedisEssentials));
assertThat(jsonSet2, equalTo("OK"));
SearchResult searchResult = exec(commandObjects.ftSearch(indexName, "Action"));
assertThat(searchResult.getTotalResults(), equalTo(1L));
assertThat(searchResult.getDocuments(), hasSize(1));
Document document = searchResult.getDocuments().get(0);
assertThat(document.getId(), equalTo("books:1000"));
Object documentRoot = document.get("$");
assertThat(documentRoot, instanceOf(String.class)); // Unparsed!
assertThat(documentRoot, jsonEquals(bookRedisInAction));
}
@Test
public void testFtAlterWithParams() throws InterruptedException {
String indexName = "booksIndex";
List<SchemaField> schema = new ArrayList<>();
schema.add(TextField.of("$.title").as("title"));
schema.add(NumericField.of("$.price").as("price"));
FTCreateParams createParams = FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("books:");
String createResult = exec(commandObjects.ftCreate(indexName, createParams, schema));
assertThat(createResult, equalTo("OK"));
JSONObject bookRedisInAction = new JSONObject();
bookRedisInAction.put("title", "Redis in Action");
bookRedisInAction.put("price", 17.99);
bookRedisInAction.put("author", "John Doe");
String jsonSet = exec(commandObjects.jsonSet("books:1000", Path2.ROOT_PATH, bookRedisInAction));
assertThat(jsonSet, equalTo("OK"));
JSONObject bookRedisEssentials = new JSONObject();
bookRedisEssentials.put("title", "Redis Essentials");
bookRedisEssentials.put("price", 19.99);
bookRedisEssentials.put("author", "Jane Doe");
String jsonSet2 = exec(commandObjects.jsonSet("books:1200", Path2.ROOT_PATH, bookRedisEssentials));
assertThat(jsonSet2, equalTo("OK"));
SearchResult searchNotInIndex = exec(commandObjects.ftSearch(indexName, "John"));
assertThat(searchNotInIndex.getTotalResults(), equalTo(0L));
assertThat(searchNotInIndex.getDocuments(), empty());
List<SchemaField> schemaExtension = new ArrayList<>();
schemaExtension.add(TextField.of("$.author").as("author"));
String alter = exec(commandObjects.ftAlter(indexName, schemaExtension));
assertThat(alter, equalTo("OK"));
Thread.sleep(300); // wait for index to be updated
SearchResult searchInIndex = exec(commandObjects.ftSearch(indexName, "John"));
assertThat(searchInIndex.getTotalResults(), equalTo(1L));
assertThat(searchInIndex.getDocuments(), hasSize(1));
Document document = searchInIndex.getDocuments().get(0);
assertThat(document.getId(), equalTo("books:1000"));
Object documentRoot = document.get("$");
assertThat(documentRoot, instanceOf(String.class)); // Unparsed!
assertThat(documentRoot, jsonEquals(bookRedisInAction));
}
@Test
public void testFtExplain() {
String indexName = "booksIndex";
IndexDefinition indexDefinition = new IndexDefinition(IndexDefinition.Type.HASH).setPrefixes("books:");
IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition(indexDefinition);
Schema schema = new Schema()
.addField(new Schema.Field("title", Schema.FieldType.TEXT))
.addField(new Schema.Field("price", Schema.FieldType.NUMERIC));
String createResult = exec(commandObjects.ftCreate(indexName, indexOptions, schema));
assertThat(createResult, equalTo("OK"));
// Add a book to the index
String bookId = "books:123";
Map<String, Object> bookFields = new HashMap<>();
bookFields.put("title", "Redis for Dummies");
bookFields.put("price", 29.99);
Long hsetResult = exec(commandObjects.hsetObject(bookId, bookFields));
assertThat(hsetResult, equalTo(2L));
Query query = new Query("Redis").returnFields("title", "price");
String explanation = exec(commandObjects.ftExplain(indexName, query));
assertThat(explanation, not(emptyOrNullString()));
List<String> explanationCli = exec(commandObjects.ftExplainCLI(indexName, query));
assertThat(explanationCli, not(empty()));
}
@Test
public void testFtAggregate() {
String indexName = "booksIndex";
IndexDefinition indexDefinition = new IndexDefinition(IndexDefinition.Type.HASH).setPrefixes("books:");
IndexOptions indexOptions = IndexOptions.defaultOptions().setDefinition(indexDefinition);
Schema schema = new Schema()
.addField(new Schema.Field("title", Schema.FieldType.TEXT))
.addField(new Schema.Field("price", Schema.FieldType.NUMERIC))
.addField(new Schema.Field("genre", Schema.FieldType.TAG));
String createResult = exec(commandObjects.ftCreate(indexName, indexOptions, schema));
assertThat(createResult, equalTo("OK"));
// Add books to the index
Map<String, Object> book1Fields = new HashMap<>();
book1Fields.put("title", "Redis for Dummies");
book1Fields.put("price", 20.99);
book1Fields.put("genre", "Technology");
String book1Id = "books:101";
exec(commandObjects.hsetObject(book1Id, book1Fields));
Map<String, Object> book2Fields = new HashMap<>();
book2Fields.put("title", "Advanced Redis");
book2Fields.put("price", 25.99);
book2Fields.put("genre", "Technology");
String book2Id = "books:102";
exec(commandObjects.hsetObject(book2Id, book2Fields));
// Aggregation: average price of books in the 'Technology' genre
AggregationBuilder aggr = new AggregationBuilder()
.groupBy("@genre", Reducers.avg("@price").as("avgPrice"))
.filter("@genre=='Technology'");
AggregationResult aggregationResult = exec(commandObjects.ftAggregate(indexName, aggr));
assertThat(aggregationResult, notNullValue());
assertThat(aggregationResult.getResults(), hasSize(1));
Map<String, Object> result = aggregationResult.getResults().get(0);
assertThat(result, hasEntry("genre", "Technology"));
assertThat(result, hasEntry("avgPrice", "23.49"));
}
@Test
public void testSpellCheck() {
// Add some terms to an index
String indexName = "techArticles";
List<SchemaField> schemaFields = Collections.singletonList(TextField.of("$.technology"));
exec(commandObjects.ftCreate(indexName, FTCreateParams.createParams().on(IndexDataType.JSON), schemaFields));
exec(commandObjects.jsonSet("articles:02", Path2.ROOT_PATH, new JSONObject().put("technology", "Flutter")));
exec(commandObjects.jsonSet("articles:03", Path2.ROOT_PATH, new JSONObject().put("technology", "Rust")));
exec(commandObjects.jsonSet("articles:04", Path2.ROOT_PATH, new JSONObject().put("technology", "Angular")));
SearchResult searchInIndex = exec(commandObjects.ftSearch(indexName, "Flutter"));
assertThat(searchInIndex.getTotalResults(), equalTo(1L));
String query = "Fluter JavaScrit Pyhton Rust";
// Spellcheck based on index only
Map<String, Map<String, Double>> indexOnly = exec(commandObjects.ftSpellCheck(indexName, query));
assertThat(indexOnly.get("fluter"), hasKey(equalToIgnoringCase("Flutter")));
assertThat(indexOnly.get("javascrit"), anEmptyMap());
assertThat(indexOnly.get("pyhton"), anEmptyMap());
// Add more terms to a dictionary
String dictionary = "techDict";
Long addResult = exec(commandObjects.ftDictAdd(dictionary, "JavaScript", "Python"));
assertThat(addResult, equalTo(2L));
// Spellcheck based on index and dictionary
FTSpellCheckParams paramsWithDict = new FTSpellCheckParams().includeTerm(dictionary);
Map<String, Map<String, Double>> indexAndDictionary = exec(commandObjects.ftSpellCheck(indexName, query, paramsWithDict));
assertThat(indexAndDictionary.get("fluter"), hasKey(equalToIgnoringCase("Flutter")));
assertThat(indexAndDictionary.get("javascrit"), hasKey("JavaScript"));
assertThat(indexAndDictionary.get("pyhton"), anEmptyMap());
// Increase Levenshtein distance, to allow for misspelled letter
FTSpellCheckParams paramsWithDictAndDist = new FTSpellCheckParams().includeTerm(dictionary).distance(2);
Map<String, Map<String, Double>> indexAndDictionaryWithDist = exec(commandObjects.ftSpellCheck(indexName, query, paramsWithDictAndDist));
assertThat(indexAndDictionaryWithDist.get("fluter"), hasKey(equalToIgnoringCase("Flutter")));
assertThat(indexAndDictionaryWithDist.get("javascrit"), hasKey("JavaScript"));
assertThat(indexAndDictionaryWithDist.get("pyhton"), hasKey("Python"));
}
@Test
public void testFtDictAddDelAndDump() {
String dictionary = "programmingLanguages";
Long addResult = exec(commandObjects.ftDictAdd(dictionary, "Java", "Python", "JavaScript", "Rust"));
assertThat(addResult, equalTo(4L));
Set<String> dumpResultAfterAdd = exec(commandObjects.ftDictDump(dictionary));
assertThat(dumpResultAfterAdd, containsInAnyOrder("Java", "Python", "JavaScript", "Rust"));
Long delResult = exec(commandObjects.ftDictDel(dictionary, "Rust"));
assertThat(delResult, equalTo(1L));
Set<String> dumpResultAfterDel = exec(commandObjects.ftDictDump(dictionary));
assertThat(dumpResultAfterDel, containsInAnyOrder("Java", "Python", "JavaScript"));
}
@Test
public void testFtDictAddDelAndDumpWithSampleKeys() {
String index = "index"; // not used actually, but needed for the command
String dictionary = "programmingLanguages";
Long addResult = exec(commandObjects.ftDictAddBySampleKey(index, dictionary, "Java", "Python", "JavaScript", "Rust"));
assertThat(addResult, equalTo(4L));
Set<String> dumpResultAfterAdd = exec(commandObjects.ftDictDumpBySampleKey(index, dictionary));
assertThat(dumpResultAfterAdd, containsInAnyOrder("Java", "Python", "JavaScript", "Rust"));
Long delResult = exec(commandObjects.ftDictDelBySampleKey(index, dictionary, "Rust"));
assertThat(delResult, equalTo(1L));
Set<String> dumpResultAfterDel = exec(commandObjects.ftDictDumpBySampleKey(index, dictionary));
assertThat(dumpResultAfterDel, containsInAnyOrder("Java", "Python", "JavaScript"));
}
@Test
public void testFtTags() {
String indexName = "booksIndex";
SchemaField[] schema = {
TextField.of("$.title"),
TagField.of("$.genre").as("genre").separator(',')
};
FTCreateParams createParams = FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("books:");
String createResult = exec(commandObjects.ftCreate(indexName, createParams, Arrays.asList(schema)));
assertThat(createResult, equalTo("OK"));
JSONObject bookDune = new JSONObject();
bookDune.put("title", "Dune");
bookDune.put("genre", "Science Fiction, Fantasy, Adventure");
String jsonSet = exec(commandObjects.jsonSet("books:1000", Path2.ROOT_PATH, bookDune));
assertThat(jsonSet, equalTo("OK"));
JSONObject bookTheFoundation = new JSONObject();
bookTheFoundation.put("title", "The Foundation");
bookTheFoundation.put("genre", "Technical, Novel, Essential");
String jsonSet2 = exec(commandObjects.jsonSet("books:1200", Path2.ROOT_PATH, bookTheFoundation));
assertThat(jsonSet2, equalTo("OK"));
Set<String> tagVals = exec(commandObjects.ftTagVals(indexName, "genre"));
assertThat(tagVals, containsInAnyOrder(
"science fiction", "fantasy", "adventure", "technical", "novel", "essential"));
SearchResult searchSimple = exec(commandObjects.ftSearch(indexName, "Fantasy"));
assertThat(searchSimple.getTotalResults(), equalTo(0L));
assertThat(searchSimple.getDocuments(), empty());
SearchResult searchSpecialSyntax = exec(commandObjects.ftSearch(indexName, "@genre:{ fantasy }"));
assertThat(searchSpecialSyntax.getTotalResults(), equalTo(1L));
assertThat(searchSpecialSyntax.getDocuments(), hasSize(1));
Document document = searchSpecialSyntax.getDocuments().get(0);
assertThat(document.getId(), equalTo("books:1000"));
Object documentRoot = document.get("$");
assertThat(documentRoot, instanceOf(String.class)); // Unparsed!
assertThat(documentRoot, jsonEquals(bookDune));
}
@Test
public void testFtInfo() {
String indexName = "booksIndex";
SchemaField[] schema = {
TextField.of("$.title"),
TagField.of("$.genre").as("genre").separator(',')
};
FTCreateParams createParams = FTCreateParams.createParams()
.on(IndexDataType.JSON)
.addPrefix("books:");
String createResult = exec(commandObjects.ftCreate(indexName, createParams, Arrays.asList(schema)));
assertThat(createResult, equalTo("OK"));
JSONObject bookDune = new JSONObject();
bookDune.put("title", "Dune");
bookDune.put("genre", "Science Fiction, Fantasy, Adventure");
String jsonSet = exec(commandObjects.jsonSet("books:1000", Path2.ROOT_PATH, bookDune));
assertThat(jsonSet, equalTo("OK"));
JSONObject bookTheFoundation = new JSONObject();
bookTheFoundation.put("title", "The Foundation");
bookTheFoundation.put("genre", "Technical, Novel, Essential");
String jsonSet2 = exec(commandObjects.jsonSet("books:1200", Path2.ROOT_PATH, bookTheFoundation));
assertThat(jsonSet2, equalTo("OK"));
Map<String, Object> infoResult = exec(commandObjects.ftInfo(indexName));
assertThat(infoResult, hasEntry("index_name", indexName));
}
@Test
public void testFtSugAddAndGet() {
String key = "autocomplete";
// Round 1: single suggestion with weight 2.0
Long sugAdd1 = exec(commandObjects.ftSugAdd(key, "Redis", 2.0));
assertThat(sugAdd1, equalTo(1L));
List<String> suggestionsOneOption = exec(commandObjects.ftSugGet(key, "Re"));
assertThat(suggestionsOneOption, contains("Redis"));
List<Tuple> suggestionsWithScoresOneOption = exec(commandObjects.ftSugGetWithScores(key, "Re"));
assertThat(suggestionsWithScoresOneOption, contains(
new Tuple("Redis", 1.0)));
// Round 2: two suggestions with weights 2.0 and 1.0
Long sugAdd2 = exec(commandObjects.ftSugAdd(key, "Redux", 1.0));
assertThat(sugAdd2, equalTo(2L));
List<String> suggestionsTwoOptions = exec(commandObjects.ftSugGet(key, "Re"));
assertThat(suggestionsTwoOptions, contains("Redis", "Redux"));
List<Tuple> suggestionsWithScoresTwoOptions = exec(commandObjects.ftSugGetWithScores(key, "Re"));
assertThat(suggestionsWithScoresTwoOptions, contains(
new Tuple("Redis", 1.0),
new Tuple("Redux", 0.5)));
// Round 2: same two suggestions with weights 2.0 and 3.0
Long sugAddIncr = exec(commandObjects.ftSugAddIncr(key, "Redux", 2.0));
assertThat(sugAddIncr, equalTo(2L));
List<String> suggestionsAfterScoreChange = exec(commandObjects.ftSugGet(key, "Re"));
assertThat(suggestionsAfterScoreChange, contains("Redux", "Redis"));
List<Tuple> suggestionsWithScoresAfterChange = exec(commandObjects.ftSugGetWithScores(key, "Re"));
assertThat(suggestionsWithScoresAfterChange, contains(
new Tuple("Redux", 1.5),
new Tuple("Redis", 1.0)));
}
}