3333import org .springframework .data .keyvalue .core .SortAccessor ;
3434import org .springframework .data .keyvalue .core .SpelSortAccessor ;
3535import org .springframework .data .keyvalue .core .query .KeyValueQuery ;
36+ import org .springframework .data .mapping .PersistentPropertyPath ;
3637import org .springframework .data .redis .connection .RedisConnection ;
3738import org .springframework .data .redis .connection .RedisGeoCommands .GeoLocation ;
3839import org .springframework .data .redis .connection .RedisGeoCommands .GeoRadiusCommandArgs ;
3940import org .springframework .data .redis .connection .util .ByteArrayWrapper ;
4041import org .springframework .data .redis .core .convert .GeoIndexedPropertyValue ;
42+ import org .springframework .data .redis .core .convert .RedisConverter ;
4143import org .springframework .data .redis .core .convert .RedisData ;
44+ import org .springframework .data .redis .core .mapping .RedisPersistentProperty ;
4245import org .springframework .data .redis .repository .query .RedisOperationChain ;
4346import org .springframework .data .redis .repository .query .RedisOperationChain .NearPath ;
4447import org .springframework .data .redis .repository .query .RedisOperationChain .PathAndValue ;
4548import org .springframework .data .redis .util .ByteUtils ;
4649import org .springframework .expression .spel .standard .SpelExpressionParser ;
47- import org .springframework .lang .NonNullApi ;
4850import org .springframework .lang .Nullable ;
4951import org .springframework .util .CollectionUtils ;
5052
@@ -100,7 +102,7 @@ private <T> List<T> doFind(RedisOperationChain criteria, long offset, int rows,
100102
101103 RedisCallback <Map <byte [], Map <byte [], byte []>>> callback = connection -> {
102104
103- List <byte []> keys = findKeys (criteria , rows , keyspace , connection );
105+ List <byte []> keys = findKeys (criteria , rows , keyspace , type , connection );
104106 byte [] keyspaceBin = getRequiredAdapter ().getConverter ().getConversionService ().convert (keyspace + ":" ,
105107 byte [].class );
106108
@@ -143,18 +145,35 @@ private <T> List<T> doFind(RedisOperationChain criteria, long offset, int rows,
143145 return result ;
144146 }
145147
146- private List <byte []> findKeys (RedisOperationChain criteria , int rows , String keyspace , RedisConnection connection ) {
148+ private List <byte []> findKeys (RedisOperationChain criteria , int rows , String keyspace , Class <?> domainType ,
149+ RedisConnection connection ) {
147150
148151 List <byte []> allKeys = new ArrayList <>();
149152
150153 if (!criteria .getSismember ().isEmpty ()) {
151- allKeys .addAll (connection .sInter (keys (keyspace + ":" , criteria .getSismember ())));
154+
155+ Set <PathAndValue > sismember = criteria .getSismember ();
156+ if (sismember .size () == 1 ) {
157+ KeySelector keySelector = KeySelector .of (getRequiredAdapter ().getConverter (), sismember , domainType );
158+ if (!keySelector .setValueLookup ().isEmpty ()) {
159+ allKeys .addAll (connection .sInter (keys (keyspace + ":" , keySelector .setValueLookup ())));
160+ }
161+
162+ allKeys .addAll (keySelector .keys ());
163+ } else {
164+ allKeys .addAll (connection .sInter (keys (keyspace + ":" , sismember )));
165+ }
152166 }
153167
154- if (!criteria .getOrSismember ().isEmpty ()) {
168+ KeySelector keySelector = KeySelector .of (getRequiredAdapter ().getConverter (), criteria .getOrSismember (),
169+ domainType );
170+
171+ if (!keySelector .setValueLookup ().isEmpty ()) {
155172 allKeys .addAll (connection .sUnion (keys (keyspace + ":" , criteria .getOrSismember ())));
156173 }
157174
175+ allKeys .addAll (keySelector .keys ());
176+
158177 if (criteria .getNear () != null ) {
159178
160179 GeoRadiusCommandArgs limit = GeoRadiusCommandArgs .newGeoRadiusArgs ();
@@ -170,7 +189,6 @@ private List<byte[]> findKeys(RedisOperationChain criteria, int rows, String key
170189 }
171190 }
172191
173-
174192 Set <ByteArrayWrapper > unique = new LinkedHashSet <>(allKeys .size ());
175193 allKeys .forEach (key -> unique .add (new ByteArrayWrapper (key )));
176194
@@ -244,4 +262,35 @@ public RedisOperationChain resolve(KeyValueQuery<?> query) {
244262 return (RedisOperationChain ) query .getCriteria ();
245263 }
246264 }
265+
266+ /**
267+ * Value object capturing the direct object keys and set of values that need to be looked up from the secondary
268+ * indexes.
269+ *
270+ * @param keys
271+ * @param setValueLookup
272+ * @since 3.2.4
273+ */
274+ record KeySelector (Collection <byte []> keys , Set <PathAndValue > setValueLookup ) {
275+
276+ static KeySelector of (RedisConverter converter , Set <PathAndValue > pathAndValues , Class <?> domainType ) {
277+
278+ Set <byte []> keys = new LinkedHashSet <>();
279+ Set <PathAndValue > remainder = new LinkedHashSet <>();
280+
281+ for (PathAndValue pathAndValue : pathAndValues ) {
282+
283+ PersistentPropertyPath <RedisPersistentProperty > path = converter .getMappingContext ()
284+ .getPersistentPropertyPath (pathAndValue .getPath (), domainType );
285+ if (path .getLeafProperty ().isIdProperty ()) {
286+ byte [] key = converter .getConversionService ().convert (pathAndValue .getFirstValue (), byte [].class );
287+ keys .add (key );
288+ } else {
289+ remainder .add (pathAndValue );
290+ }
291+ }
292+
293+ return new KeySelector (keys , remainder );
294+ }
295+ }
247296}
0 commit comments