diff --git a/src/main/java/redis/clients/jedis/CommandObjects.java b/src/main/java/redis/clients/jedis/CommandObjects.java index f98c49d0de..bc37045dc5 100644 --- a/src/main/java/redis/clients/jedis/CommandObjects.java +++ b/src/main/java/redis/clients/jedis/CommandObjects.java @@ -3433,7 +3433,7 @@ public final CommandObject ftCursorDel(String indexName, long cursorId) .key(indexName).add(cursorId), BuilderFactory.STRING); } - public final CommandObject>> ftProfileAggregate( + public final CommandObject> ftProfileAggregate( String indexName, FTProfileParams profileParams, AggregationBuilder aggr) { return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) .add(SearchKeyword.AGGREGATE).addParams(profileParams).add(SearchKeyword.QUERY) @@ -3442,7 +3442,7 @@ public final CommandObject>> ft : AggregationResult.SEARCH_AGGREGATION_RESULT_WITH_CURSOR)); } - public final CommandObject>> ftProfileSearch( + public final CommandObject> ftProfileSearch( String indexName, FTProfileParams profileParams, Query query) { return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) .add(SearchKeyword.SEARCH).addParams(profileParams).add(SearchKeyword.QUERY) @@ -3451,7 +3451,7 @@ public final CommandObject>> ftProfi () -> new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), true)))); } - public final CommandObject>> ftProfileSearch( + public final CommandObject> ftProfileSearch( String indexName, FTProfileParams profileParams, String query, FTSearchParams searchParams) { return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.PROFILE, indexName) .add(SearchKeyword.SEARCH).addParams(profileParams).add(SearchKeyword.QUERY).add(query) @@ -4428,32 +4428,51 @@ public void setDefaultSearchDialect(int dialect) { this.searchDialect.set(dialect); } - private class SearchProfileResponseBuilder extends Builder>> { + private class SearchProfileResponseBuilder extends Builder> { - private static final String PROFILE_STR = "profile"; + private static final String PROFILE_STR_REDIS7 = "profile"; + private static final String PROFILE_STR_REDIS8 = "Profile"; + private static final String RESULTS_STR_REDIS7 = "results"; + private static final String RESULTS_STR_REDIS8 = "Results"; - private final Builder replyBuilder; + private final Builder resultsBuilder; - public SearchProfileResponseBuilder(Builder replyBuilder) { - this.replyBuilder = replyBuilder; + public SearchProfileResponseBuilder(Builder resultsBuilder) { + this.resultsBuilder = resultsBuilder; } @Override - public Map.Entry> build(Object data) { + public Map.Entry build(Object data) { List list = (List) data; if (list == null || list.isEmpty()) return null; - if (list.get(0) instanceof KeyValue) { + if (list.get(0) instanceof KeyValue) { // RESP3 + Object resultsData = null, profileData = null; + for (KeyValue keyValue : (List) data) { - if (PROFILE_STR.equals(BuilderFactory.STRING.build(keyValue.getKey()))) { - return KeyValue.of(replyBuilder.build(data), - BuilderFactory.AGGRESSIVE_ENCODED_OBJECT_MAP.build(keyValue.getValue())); + String keyStr = BuilderFactory.STRING.build(keyValue.getKey()); + switch (keyStr) { + case PROFILE_STR_REDIS7: + case PROFILE_STR_REDIS8: + profileData = keyValue.getValue(); + break; + case RESULTS_STR_REDIS7: + resultsData = data; + break; + case RESULTS_STR_REDIS8: + resultsData = keyValue.getValue(); + break; } } + + assert resultsData != null : "Could not detect Results data."; + assert profileData != null : "Could not detect Profile data."; + return KeyValue.of(resultsBuilder.build(resultsData), + ProfilingInfo.PROFILING_INFO_BUILDER.build(profileData)); } - return KeyValue.of(replyBuilder.build(list.get(0)), - SearchBuilderFactory.SEARCH_PROFILE_PROFILE.build(list.get(1))); + return KeyValue.of(resultsBuilder.build(list.get(0)), + ProfilingInfo.PROFILING_INFO_BUILDER.build(list.get(1))); } } diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 8c8dc760fe..4f2c97eac7 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -3979,19 +3979,19 @@ public FtAggregateIteration ftAggregateIteration(String indexName, AggregationBu } @Override - public Map.Entry> ftProfileAggregate(String indexName, + public Map.Entry ftProfileAggregate(String indexName, FTProfileParams profileParams, AggregationBuilder aggr) { return executeCommand(commandObjects.ftProfileAggregate(indexName, profileParams, aggr)); } @Override - public Map.Entry> ftProfileSearch(String indexName, + public Map.Entry ftProfileSearch(String indexName, FTProfileParams profileParams, Query query) { return executeCommand(commandObjects.ftProfileSearch(indexName, profileParams, query)); } @Override - public Map.Entry> ftProfileSearch(String indexName, + public Map.Entry ftProfileSearch(String indexName, FTProfileParams profileParams, String query, FTSearchParams searchParams) { return executeCommand(commandObjects.ftProfileSearch(indexName, profileParams, query, searchParams)); } diff --git a/src/main/java/redis/clients/jedis/search/ProfilingInfo.java b/src/main/java/redis/clients/jedis/search/ProfilingInfo.java new file mode 100644 index 0000000000..98dcf095ba --- /dev/null +++ b/src/main/java/redis/clients/jedis/search/ProfilingInfo.java @@ -0,0 +1,31 @@ +package redis.clients.jedis.search; + +import static redis.clients.jedis.BuilderFactory.AGGRESSIVE_ENCODED_OBJECT; + +import redis.clients.jedis.Builder; + +public class ProfilingInfo { + + private final Object profilingInfo; + + private ProfilingInfo(Object profilingInfo) { + this.profilingInfo = profilingInfo; + } + + public Object getProfilingInfo() { + return profilingInfo; + } + + @Override + public String toString() { + return String.valueOf(profilingInfo); + } + + public static final Builder PROFILING_INFO_BUILDER + = new Builder() { + @Override + public ProfilingInfo build(Object data) { + return new ProfilingInfo(AGGRESSIVE_ENCODED_OBJECT.build(data)); + } + }; +} diff --git a/src/main/java/redis/clients/jedis/search/RediSearchCommands.java b/src/main/java/redis/clients/jedis/search/RediSearchCommands.java index 588a47b768..451f2e58bb 100644 --- a/src/main/java/redis/clients/jedis/search/RediSearchCommands.java +++ b/src/main/java/redis/clients/jedis/search/RediSearchCommands.java @@ -74,13 +74,13 @@ default SearchResult ftSearch(String indexName) { String ftCursorDel(String indexName, long cursorId); - Map.Entry> ftProfileAggregate(String indexName, + Map.Entry ftProfileAggregate(String indexName, FTProfileParams profileParams, AggregationBuilder aggr); - Map.Entry> ftProfileSearch(String indexName, + Map.Entry ftProfileSearch(String indexName, FTProfileParams profileParams, Query query); - Map.Entry> ftProfileSearch(String indexName, + Map.Entry ftProfileSearch(String indexName, FTProfileParams profileParams, String query, FTSearchParams searchParams); String ftSynUpdate(String indexName, String synonymGroupId, String... terms); diff --git a/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java b/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java index 8702b4a307..ad5fc83ada 100644 --- a/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java +++ b/src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java @@ -2,7 +2,6 @@ import static redis.clients.jedis.BuilderFactory.STRING; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -12,109 +11,10 @@ import redis.clients.jedis.Builder; import redis.clients.jedis.BuilderFactory; -import redis.clients.jedis.util.DoublePrecision; import redis.clients.jedis.util.KeyValue; -import redis.clients.jedis.util.SafeEncoder; public final class SearchBuilderFactory { - public static final Builder> SEARCH_PROFILE_PROFILE = new Builder>() { - - private final String ITERATORS_PROFILE_STR = "Iterators profile"; - private final String CHILD_ITERATORS_STR = "Child iterators"; - private final String RESULT_PROCESSORS_PROFILE_STR = "Result processors profile"; - - @Override - public Map build(Object data) { - List list = (List) SafeEncoder.encodeObject(data); - Map profileMap = new HashMap<>(list.size(), 1f); - - for (Object listObject : list) { - List attributeList = (List) listObject; - String attributeName = (String) attributeList.get(0); - Object attributeValue; - - if (attributeList.size() == 2) { - - Object value = attributeList.get(1); - if (attributeName.equals(ITERATORS_PROFILE_STR)) { - attributeValue = parseIterators(value); - } else if (attributeName.endsWith(" time")) { - attributeValue = DoublePrecision.parseEncodedFloatingPointNumber(value); - } else { - attributeValue = value; - } - - } else if (attributeList.size() > 2) { - - if (attributeName.equals(RESULT_PROCESSORS_PROFILE_STR)) { - List> resultProcessorsProfileList = new ArrayList<>(attributeList.size() - 1); - for (int i = 1; i < attributeList.size(); i++) { - resultProcessorsProfileList.add(parseResultProcessors(attributeList.get(i))); - } - attributeValue = resultProcessorsProfileList; - } else { - attributeValue = attributeList.subList(1, attributeList.size()); - } - - } else { - attributeValue = null; - } - - profileMap.put(attributeName, attributeValue); - } - return profileMap; - } - - private Map parseResultProcessors(Object data) { - List list = (List) data; - Map map = new HashMap<>(list.size() / 2, 1f); - for (int i = 0; i < list.size(); i += 2) { - String key = (String) list.get(i); - Object value = list.get(i + 1); - if (key.equals("Time")) { - value = DoublePrecision.parseEncodedFloatingPointNumber(value); - } - map.put(key, value); - } - return map; - } - - private Object parseIterators(Object data) { - if (!(data instanceof List)) return data; - List iteratorsAttributeList = (List) data; - int childIteratorsIndex = iteratorsAttributeList.indexOf(CHILD_ITERATORS_STR); - // https://github.com/RediSearch/RediSearch/issues/3205 patch. TODO: Undo if resolved in RediSearch. - if (childIteratorsIndex < 0) childIteratorsIndex = iteratorsAttributeList.indexOf("Child iterator"); - - Map iteratorsProfile; - if (childIteratorsIndex < 0) { - childIteratorsIndex = iteratorsAttributeList.size(); - iteratorsProfile = new HashMap<>(childIteratorsIndex / 2, 1f); - } else { - iteratorsProfile = new HashMap<>(1 + childIteratorsIndex / 2, 1f); - } - - for (int i = 0; i < childIteratorsIndex; i += 2) { - String key = (String) iteratorsAttributeList.get(i); - Object value = iteratorsAttributeList.get(i + 1); - if (key.equals("Time")) { - value = DoublePrecision.parseEncodedFloatingPointNumber(value); - } - iteratorsProfile.put(key, value); - } - - if (childIteratorsIndex + 1 < iteratorsAttributeList.size()) { - List childIteratorsList = new ArrayList(iteratorsAttributeList.size() - childIteratorsIndex - 1); - for (int i = childIteratorsIndex + 1; i < iteratorsAttributeList.size(); i++) { - childIteratorsList.add(parseIterators(iteratorsAttributeList.get(i))); - } - iteratorsProfile.put(CHILD_ITERATORS_STR, childIteratorsList); - } - return iteratorsProfile; - } - }; - public static final Builder>> SEARCH_SYNONYM_GROUPS = new Builder>>() { @Override public Map> build(Object data) { diff --git a/src/test/java/io/redis/test/utils/RedisVersion.java b/src/test/java/io/redis/test/utils/RedisVersion.java index a87d60262e..fa9ed8b427 100644 --- a/src/test/java/io/redis/test/utils/RedisVersion.java +++ b/src/test/java/io/redis/test/utils/RedisVersion.java @@ -1,10 +1,11 @@ package io.redis.test.utils; -public class RedisVersion implements Comparable{ +public class RedisVersion implements Comparable { public static final RedisVersion V6_0_0 = RedisVersion.of("6.0.0"); public static final RedisVersion V7_0_0 = RedisVersion.of("7.0.0"); public static final RedisVersion V7_2_0 = RedisVersion.of("7.2.0"); public static final RedisVersion V7_4 = RedisVersion.of("7.4"); + public static final RedisVersion V8_0_0_PRE = RedisVersion.of("7.9.0"); public static final RedisVersion V8_0_0 = RedisVersion.of("8.0.0"); private final int major; diff --git a/src/test/java/redis/clients/jedis/mocked/MockedCommandObjectsTestBase.java b/src/test/java/redis/clients/jedis/mocked/MockedCommandObjectsTestBase.java index f97de5d9af..5576a207f8 100644 --- a/src/test/java/redis/clients/jedis/mocked/MockedCommandObjectsTestBase.java +++ b/src/test/java/redis/clients/jedis/mocked/MockedCommandObjectsTestBase.java @@ -12,12 +12,10 @@ import redis.clients.jedis.GeoCoordinate; import redis.clients.jedis.StreamEntryID; import redis.clients.jedis.resps.*; +import redis.clients.jedis.search.ProfilingInfo; import redis.clients.jedis.search.SearchResult; import redis.clients.jedis.search.aggr.AggregationResult; -import redis.clients.jedis.timeseries.TSElement; -import redis.clients.jedis.timeseries.TSInfo; -import redis.clients.jedis.timeseries.TSMGetElement; -import redis.clients.jedis.timeseries.TSMRangeElements; +import redis.clients.jedis.timeseries.*; import redis.clients.jedis.util.KeyValue; /** @@ -85,9 +83,9 @@ public final static class MyBean { @Mock protected CommandObject> listTupleCommandObject; @Mock protected CommandObject> listBytesCommandObject; @Mock protected CommandObject longCommandObject; - @Mock protected CommandObject>> entryAggregationResultMapStringObjectCommandObject; + @Mock protected CommandObject> entryAggregationResultMapStringObjectCommandObject; @Mock protected CommandObject> entryLongBytesCommandObject; - @Mock protected CommandObject>> entrySearchResultMapStringObjectCommandObject; + @Mock protected CommandObject> entrySearchResultMapStringObjectCommandObject; @Mock protected CommandObject>> entryStreamEntryIdListStreamEntryCommandObject; @Mock protected CommandObject>> entryStreamEntryIdListStreamEntryIdCommandObject; @Mock protected CommandObject>> mapStringListStringCommandObject; diff --git a/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisSearchAndQueryCommandsTest.java b/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisSearchAndQueryCommandsTest.java index 1f6d9d6363..c061c6f102 100644 --- a/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisSearchAndQueryCommandsTest.java +++ b/src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisSearchAndQueryCommandsTest.java @@ -17,14 +17,7 @@ import org.junit.Test; import redis.clients.jedis.resps.Tuple; -import redis.clients.jedis.search.FTCreateParams; -import redis.clients.jedis.search.FTProfileParams; -import redis.clients.jedis.search.FTSearchParams; -import redis.clients.jedis.search.FTSpellCheckParams; -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.*; import redis.clients.jedis.search.aggr.AggregationBuilder; import redis.clients.jedis.search.aggr.AggregationResult; import redis.clients.jedis.search.schemafields.SchemaField; @@ -773,13 +766,13 @@ public void testFtProfileAggregate() { String indexName = "myIndex"; FTProfileParams profileParams = new FTProfileParams(); AggregationBuilder aggr = new AggregationBuilder().groupBy("@field"); - Map.Entry> expectedResponse = new AbstractMap.SimpleEntry<>( - mock(AggregationResult.class), Collections.singletonMap("Profile", "Data")); + Map.Entry expectedResponse = new AbstractMap.SimpleEntry<>( + mock(AggregationResult.class), mock(ProfilingInfo.class)); when(commandObjects.ftProfileAggregate(indexName, profileParams, aggr)).thenReturn(entryAggregationResultMapStringObjectCommandObject); when(commandExecutor.executeCommand(entryAggregationResultMapStringObjectCommandObject)).thenReturn(expectedResponse); - Map.Entry> result = jedis.ftProfileAggregate(indexName, profileParams, aggr); + Map.Entry result = jedis.ftProfileAggregate(indexName, profileParams, aggr); assertThat(result, equalTo(expectedResponse)); @@ -792,13 +785,13 @@ public void testFtProfileSearchWithQueryObject() { String indexName = "myIndex"; FTProfileParams profileParams = new FTProfileParams(); Query query = new Query("hello world").limit(0, 10); - Map.Entry> expectedResponse = new AbstractMap.SimpleEntry<>( - mock(SearchResult.class), Collections.singletonMap("Profile", "Data")); + Map.Entry expectedResponse = new AbstractMap.SimpleEntry<>( + mock(SearchResult.class), mock(ProfilingInfo.class)); when(commandObjects.ftProfileSearch(indexName, profileParams, query)).thenReturn(entrySearchResultMapStringObjectCommandObject); when(commandExecutor.executeCommand(entrySearchResultMapStringObjectCommandObject)).thenReturn(expectedResponse); - Map.Entry> result = jedis.ftProfileSearch(indexName, profileParams, query); + Map.Entry result = jedis.ftProfileSearch(indexName, profileParams, query); assertThat(result, equalTo(expectedResponse)); @@ -812,13 +805,13 @@ public void testFtProfileSearchWithQueryAndSearchParams() { FTProfileParams profileParams = new FTProfileParams(); String query = "hello world"; FTSearchParams searchParams = new FTSearchParams().noContent().limit(0, 10); - Map.Entry> expectedResponse = new AbstractMap.SimpleEntry<>( - mock(SearchResult.class), Collections.singletonMap("Profile", "Data")); + Map.Entry expectedResponse = new AbstractMap.SimpleEntry<>( + mock(SearchResult.class), mock(ProfilingInfo.class)); when(commandObjects.ftProfileSearch(indexName, profileParams, query, searchParams)).thenReturn(entrySearchResultMapStringObjectCommandObject); when(commandExecutor.executeCommand(entrySearchResultMapStringObjectCommandObject)).thenReturn(expectedResponse); - Map.Entry> result = jedis.ftProfileSearch(indexName, profileParams, query, searchParams); + Map.Entry result = jedis.ftProfileSearch(indexName, profileParams, query, searchParams); assertThat(result, equalTo(expectedResponse)); diff --git a/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java b/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java index c7b7c9ecea..bac9d9d687 100644 --- a/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/AggregationTest.java @@ -7,6 +7,7 @@ import static org.junit.Assert.fail; import io.redis.test.annotations.SinceRedisVersion; +import io.redis.test.utils.RedisVersion; import org.hamcrest.Matchers; import org.junit.BeforeClass; import org.junit.Test; @@ -14,30 +15,20 @@ import org.junit.runners.Parameterized; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import redis.clients.jedis.RedisProtocol; import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.jedis.search.Document; -import redis.clients.jedis.search.FieldName; -import redis.clients.jedis.search.IndexOptions; -import redis.clients.jedis.search.Schema; -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.aggr.Row; -import redis.clients.jedis.search.aggr.SortedField; import redis.clients.jedis.modules.RedisModuleCommandsTestBase; -import redis.clients.jedis.search.FTProfileParams; -import redis.clients.jedis.search.aggr.FtAggregateIteration; +import redis.clients.jedis.search.*; +import redis.clients.jedis.search.aggr.*; import redis.clients.jedis.search.schemafields.NumericField; import redis.clients.jedis.search.schemafields.TextField; import redis.clients.jedis.util.RedisConditions; +import redis.clients.jedis.util.RedisVersionUtil; @RunWith(Parameterized.class) public class AggregationTest extends RedisModuleCommandsTestBase { @@ -136,7 +127,6 @@ public void testAggregations2() { assertEquals("10", rows.get(1).get("sum")); } - @org.junit.Ignore @Test public void testAggregations2Profile() { Schema sc = new Schema(); @@ -152,7 +142,7 @@ public void testAggregations2Profile() { .groupBy("@name", Reducers.sum("@count").as("sum")) .sortBy(10, SortedField.desc("@sum")); - Map.Entry> reply + Map.Entry reply = client.ftProfileAggregate(index, FTProfileParams.profileParams(), aggr); // actual search @@ -168,18 +158,17 @@ public void testAggregations2Profile() { assertEquals("10", rows.get(1).get("sum")); // profile - Map profile = reply.getValue(); - - assertEquals(Arrays.asList("Index", "Grouper", "Sorter"), - ((List>) profile.get("Result processors profile")).stream() - .map(map -> map.get("Type")).collect(Collectors.toList())); - + Object profileObject = reply.getValue().getProfilingInfo(); if (protocol != RedisProtocol.RESP3) { - assertEquals("WILDCARD", ((Map) profile.get("Iterators profile")).get("Type")); + assertThat(profileObject, Matchers.isA(List.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0_PRE)) { + assertThat((List) profileObject, Matchers.hasItems("Shards", "Coordinator")); + } } else { - assertEquals(Arrays.asList("WILDCARD"), - ((List>) profile.get("Iterators profile")).stream() - .map(map -> map.get("Type")).collect(Collectors.toList())); + assertThat(profileObject, Matchers.isA(Map.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0_PRE)) { + assertThat(((Map) profileObject).keySet(), Matchers.hasItems("Shards", "Coordinator")); + } } } diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchTest.java index 661c083631..7f41d8e2fa 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SearchTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SearchTest.java @@ -1123,7 +1123,6 @@ public void testDialectsWithFTExplain() throws Exception { assertThat(client.ftExplain(index, query), not(emptyOrNullString())); } - @org.junit.Ignore @Test public void searchProfile() { Schema sc = new Schema().addTextField("t1", 1.0).addTextField("t2", 1.0); @@ -1134,31 +1133,25 @@ public void searchProfile() { hash.put("t2", "bar"); client.hset("doc1", hash); - Map.Entry> reply = client.ftProfileSearch(index, + Map.Entry reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), new Query("foo")); SearchResult result = reply.getKey(); assertEquals(1, result.getTotalResults()); assertEquals(Collections.singletonList("doc1"), result.getDocuments().stream().map(Document::getId).collect(Collectors.toList())); - Map profile = reply.getValue(); - Map iteratorsProfile; + Object profileObject = reply.getValue().getProfilingInfo(); if (protocol != RedisProtocol.RESP3) { - iteratorsProfile = (Map) profile.get("Iterators profile"); + assertThat(profileObject, Matchers.isA(List.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat((List) profileObject, Matchers.hasItems("Shards", "Coordinator")); + } } else { - List iteratorsProfileList = (List) profile.get("Iterators profile"); - assertEquals(1, iteratorsProfileList.size()); - iteratorsProfile = (Map) iteratorsProfileList.get(0); + assertThat(profileObject, Matchers.isA(Map.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat(((Map) profileObject).keySet(), Matchers.hasItems("Shards", "Coordinator")); + } } - assertEquals("TEXT", iteratorsProfile.get("Type")); - assertEquals("foo", iteratorsProfile.get("Term")); - assertEquals(1L, iteratorsProfile.get("Counter")); - assertEquals(1L, iteratorsProfile.get("Size")); - assertSame(Double.class, iteratorsProfile.get("Time").getClass()); - - assertEquals(Arrays.asList("Index", "Scorer", "Sorter", "Loader"), - ((List>) profile.get("Result processors profile")).stream() - .map(map -> map.get("Type")).collect(Collectors.toList())); } @Test @@ -1183,21 +1176,6 @@ public void testHNSWVVectorSimilarity() { Document doc1 = client.ftSearch(index, query).getDocuments().get(0); assertEquals("a", doc1.getId()); assertEquals("0", doc1.get("__v_score")); - -// // @org.junit.Ignore -// // profile -// Map.Entry> reply -// = client.ftProfileSearch(index, FTProfileParams.profileParams(), query); -// doc1 = reply.getKey().getDocuments().get(0); -// assertEquals("a", doc1.getId()); -// assertEquals("0", doc1.get("__v_score")); -// if (protocol != RedisProtocol.RESP3) { -// assertEquals("VECTOR", ((Map) reply.getValue().get("Iterators profile")).get("Type")); -// } else { -// assertEquals(Arrays.asList("VECTOR"), -// ((List>) reply.getValue().get("Iterators profile")).stream() -// .map(map -> map.get("Type")).collect(Collectors.toList())); -// } } @Test @@ -1222,21 +1200,6 @@ public void testFlatVectorSimilarity() { Document doc1 = client.ftSearch(index, query).getDocuments().get(0); assertEquals("a", doc1.getId()); assertEquals("0", doc1.get("__v_score")); - -// // @org.junit.Ignore -// // profile -// Map.Entry> reply -// = client.ftProfileSearch(index, FTProfileParams.profileParams(), query); -// doc1 = reply.getKey().getDocuments().get(0); -// assertEquals("a", doc1.getId()); -// assertEquals("0", doc1.get("__v_score")); -// if (protocol != RedisProtocol.RESP3) { -// assertEquals("VECTOR", ((Map) reply.getValue().get("Iterators profile")).get("Type")); -// } else { -// assertEquals(Arrays.asList("VECTOR"), -// ((List>) reply.getValue().get("Iterators profile")).stream() -// .map(map -> map.get("Type")).collect(Collectors.toList())); -// } } @Test diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java index 8ab421809d..1ac4575ea0 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java @@ -5,14 +5,12 @@ import static redis.clients.jedis.util.AssertUtil.assertOK; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import io.redis.test.annotations.SinceRedisVersion; import io.redis.test.utils.RedisVersion; import org.hamcrest.Matchers; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -1291,7 +1289,6 @@ public void bfloat16StorageType() { .build())); } - @Ignore @Test public void searchProfile() { assertOK(client.ftCreate(index, TextField.of("t1"), TextField.of("t2"))); @@ -1301,34 +1298,28 @@ public void searchProfile() { hash.put("t2", "bar"); client.hset("doc1", hash); - Map.Entry> reply = client.ftProfileSearch(index, + Map.Entry reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), "foo", FTSearchParams.searchParams()); SearchResult result = reply.getKey(); assertEquals(1, result.getTotalResults()); assertEquals(Collections.singletonList("doc1"), result.getDocuments().stream().map(Document::getId).collect(Collectors.toList())); - Map profile = reply.getValue(); - Map iteratorsProfile; + // profile + Object profileObject = reply.getValue().getProfilingInfo(); if (protocol != RedisProtocol.RESP3) { - iteratorsProfile = (Map) profile.get("Iterators profile"); + assertThat(profileObject, Matchers.isA(List.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat((List) profileObject, Matchers.hasItems("Shards", "Coordinator")); + } } else { - List iteratorsProfileList = (List) profile.get("Iterators profile"); - assertEquals(1, iteratorsProfileList.size()); - iteratorsProfile = (Map) iteratorsProfileList.get(0); + assertThat(profileObject, Matchers.isA(Map.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat(((Map) profileObject).keySet(), Matchers.hasItems("Shards", "Coordinator")); + } } - assertEquals("TEXT", iteratorsProfile.get("Type")); - assertEquals("foo", iteratorsProfile.get("Term")); - assertEquals(1L, iteratorsProfile.get("Counter")); - assertEquals(1L, iteratorsProfile.get("Size")); - assertSame(Double.class, iteratorsProfile.get("Time").getClass()); - - assertEquals(Arrays.asList("Index", "Scorer", "Sorter", "Loader"), - ((List>) profile.get("Result processors profile")).stream() - .map(map -> map.get("Type")).collect(Collectors.toList())); } - @Ignore @Test public void vectorSearchProfile() { assertOK(client.ftCreate(index, VectorField.builder().fieldName("v") @@ -1344,129 +1335,28 @@ public void vectorSearchProfile() { FTSearchParams searchParams = FTSearchParams.searchParams().addParam("vec", "aaaaaaaa") .sortBy("__v_score", SortingOrder.ASC).noContent().dialect(2); - Map.Entry> reply = client.ftProfileSearch(index, + Map.Entry reply = client.ftProfileSearch(index, FTProfileParams.profileParams(), "*=>[KNN 3 @v $vec]", searchParams); assertEquals(3, reply.getKey().getTotalResults()); assertEquals(Arrays.asList(4, 2, 1).toString(), reply.getKey().getDocuments() .stream().map(Document::getId).collect(Collectors.toList()).toString()); - Map profile = reply.getValue(); - + // profile + Object profileObject = reply.getValue().getProfilingInfo(); if (protocol != RedisProtocol.RESP3) { - assertEquals("VECTOR", ((Map) profile.get("Iterators profile")).get("Type")); - } else { - assertEquals(Arrays.asList("VECTOR"), - ((List>) profile.get("Iterators profile")).stream() - .map(map -> map.get("Type")).collect(Collectors.toList())); - } - - List> resultProcessorsProfile - = (List>) reply.getValue().get("Result processors profile"); - assertEquals(3, resultProcessorsProfile.size()); - assertEquals("Index", resultProcessorsProfile.get(0).get("Type")); - assertEquals("Sorter", resultProcessorsProfile.get(2).get("Type")); - } - - @Ignore - @Test - public void maxPrefixExpansionSearchProfile() { - final String configParam = "MAXPREFIXEXPANSIONS"; - String configValue = (String) client.ftConfigGet(configParam).get(configParam); - try { - client.ftConfigSet(configParam, "2"); - - assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", "t", "foo1"); - client.hset("2", "t", "foo2"); - client.hset("3", "t", "foo3"); - - Map.Entry> reply = client.ftProfileSearch(index, - FTProfileParams.profileParams(), "foo*", FTSearchParams.searchParams().limit(0, 0)); - // Warning=Max prefix expansion reached - if (protocol != RedisProtocol.RESP3) { - assertEquals("Max prefix expansion reached", - ((Map) reply.getValue().get("Iterators profile")).get("Warning")); - } else { - assertEquals("Max prefix expansion reached", - ((Map) ((List) reply.getValue().get("Iterators profile")).get(0)).get("Warning")); + assertThat(profileObject, Matchers.isA(List.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat((List) profileObject, Matchers.hasItems("Shards", "Coordinator")); } - } finally { - client.ftConfigSet(configParam, configValue); - } - } - - @Ignore - @Test - public void noContentSearchProfile() { - assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", "t", "foo"); - client.hset("2", "t", "bar"); - - Map.Entry> profile = client.ftProfileSearch(index, - FTProfileParams.profileParams(), "foo -@t:baz", FTSearchParams.searchParams().noContent()); - - Map depth0 = protocol != RedisProtocol.RESP3 - ? (Map) profile.getValue().get("Iterators profile") - : ((List>) profile.getValue().get("Iterators profile")).get(0); - - assertEquals("INTERSECT", depth0.get("Type")); - List> depth0_children = (List>) depth0.get("Child iterators"); - assertEquals("TEXT", depth0_children.get(0).get("Type")); - Map depth1 = depth0_children.get(1); - assertEquals("NOT", depth1.get("Type")); - if (protocol != RedisProtocol.RESP3) { - List> depth1_children = (List>) depth1.get("Child iterators"); - assertEquals(1, depth1_children.size()); - assertEquals("EMPTY", depth1_children.get(0).get("Type")); } else { - assertEquals("EMPTY", ((Map) depth1.get("Child iterator")).get("Type")); - } - } - - @Ignore - @Test - public void deepReplySearchProfile() { - assertOK(client.ftCreate(index, TextField.of("t"))); - client.hset("1", "t", "hello"); - client.hset("2", "t", "world"); - - Map.Entry> profile - = client.ftProfileSearch(index, FTProfileParams.profileParams(), - "hello(hello(hello(hello(hello(hello)))))", FTSearchParams.searchParams().noContent()); - - Map depth0 = protocol != RedisProtocol.RESP3 - ? (Map) profile.getValue().get("Iterators profile") - : ((List>) profile.getValue().get("Iterators profile")).get(0); - - AtomicInteger intersectLevelCount = new AtomicInteger(); - AtomicInteger textLevelCount = new AtomicInteger(); - deepReplySearchProfile_assertProfile(depth0, intersectLevelCount, textLevelCount); - assertThat(intersectLevelCount.get(), Matchers.greaterThan(0)); - assertThat(textLevelCount.get(), Matchers.greaterThan(0)); - } - - private void deepReplySearchProfile_assertProfile(Map attr, - AtomicInteger intersectLevelCount, AtomicInteger textLevelCount) { - - String type = (String) attr.get("Type"); - assertThat(type, Matchers.not(Matchers.blankOrNullString())); - - switch (type) { - case "INTERSECT": - assertThat(attr, Matchers.hasKey("Child iterators")); - intersectLevelCount.incrementAndGet(); - deepReplySearchProfile_assertProfile((Map) ((List) attr.get("Child iterators")).get(0), - intersectLevelCount, textLevelCount); - break; - case "TEXT": - assertThat(attr, Matchers.hasKey("Term")); - textLevelCount.incrementAndGet(); - break; + assertThat(profileObject, Matchers.isA(Map.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat(((Map) profileObject).keySet(), Matchers.hasItems("Shards", "Coordinator")); + } } } - @Ignore @Test public void limitedSearchProfile() { assertOK(client.ftCreate(index, TextField.of("t"))); @@ -1475,27 +1365,20 @@ public void limitedSearchProfile() { client.hset("3", "t", "help"); client.hset("4", "t", "helowa"); - Map.Entry> profile = client.ftProfileSearch(index, + Map.Entry reply = client.ftProfileSearch(index, FTProfileParams.profileParams().limited(), "%hell% hel*", FTSearchParams.searchParams().noContent()); - Map depth0 = protocol != RedisProtocol.RESP3 - ? (Map) profile.getValue().get("Iterators profile") - : ((List>) profile.getValue().get("Iterators profile")).get(0); - - assertEquals("INTERSECT", depth0.get("Type")); - assertEquals(3L, depth0.get("Counter")); - - List> depth0_children = (List>) depth0.get("Child iterators"); - assertFalse(depth0_children.isEmpty()); - for (Map depth1 : depth0_children) { - assertEquals("UNION", depth1.get("Type")); - assertNotNull(depth1.get("Query type")); - if (protocol != RedisProtocol.RESP3) { - List depth1_children = (List) depth1.get("Child iterators"); - assertEquals(1, depth1_children.size()); - assertSame(String.class, depth1_children.get(0).getClass()); - } else { - assertSame(String.class, depth1.get("Child iterators").getClass()); + // profile + Object profileObject = reply.getValue().getProfilingInfo(); + if (protocol != RedisProtocol.RESP3) { + assertThat(profileObject, Matchers.isA(List.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat((List) profileObject, Matchers.hasItems("Shards", "Coordinator")); + } + } else { + assertThat(profileObject, Matchers.isA(Map.class)); + if (RedisVersionUtil.getRedisVersion(client).isGreaterThanOrEqualTo(RedisVersion.V8_0_0)) { + assertThat(((Map) profileObject).keySet(), Matchers.hasItems("Shards", "Coordinator")); } } }