33
33
import org .springframework .data .keyvalue .core .SortAccessor ;
34
34
import org .springframework .data .keyvalue .core .SpelSortAccessor ;
35
35
import org .springframework .data .keyvalue .core .query .KeyValueQuery ;
36
+ import org .springframework .data .mapping .PersistentPropertyPath ;
36
37
import org .springframework .data .redis .connection .RedisConnection ;
37
38
import org .springframework .data .redis .connection .RedisGeoCommands .GeoLocation ;
38
39
import org .springframework .data .redis .connection .RedisGeoCommands .GeoRadiusCommandArgs ;
39
40
import org .springframework .data .redis .connection .util .ByteArrayWrapper ;
40
41
import org .springframework .data .redis .core .convert .GeoIndexedPropertyValue ;
42
+ import org .springframework .data .redis .core .convert .RedisConverter ;
41
43
import org .springframework .data .redis .core .convert .RedisData ;
44
+ import org .springframework .data .redis .core .mapping .RedisPersistentProperty ;
42
45
import org .springframework .data .redis .repository .query .RedisOperationChain ;
43
46
import org .springframework .data .redis .repository .query .RedisOperationChain .NearPath ;
44
47
import org .springframework .data .redis .repository .query .RedisOperationChain .PathAndValue ;
45
48
import org .springframework .data .redis .util .ByteUtils ;
46
49
import org .springframework .expression .spel .standard .SpelExpressionParser ;
47
- import org .springframework .lang .NonNullApi ;
48
50
import org .springframework .lang .Nullable ;
49
51
import org .springframework .util .CollectionUtils ;
50
52
@@ -100,7 +102,7 @@ private <T> List<T> doFind(RedisOperationChain criteria, long offset, int rows,
100
102
101
103
RedisCallback <Map <byte [], Map <byte [], byte []>>> callback = connection -> {
102
104
103
- List <byte []> keys = findKeys (criteria , rows , keyspace , connection );
105
+ List <byte []> keys = findKeys (criteria , rows , keyspace , type , connection );
104
106
byte [] keyspaceBin = getRequiredAdapter ().getConverter ().getConversionService ().convert (keyspace + ":" ,
105
107
byte [].class );
106
108
@@ -143,18 +145,35 @@ private <T> List<T> doFind(RedisOperationChain criteria, long offset, int rows,
143
145
return result ;
144
146
}
145
147
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 ) {
147
150
148
151
List <byte []> allKeys = new ArrayList <>();
149
152
150
153
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
+ }
152
166
}
153
167
154
- if (!criteria .getOrSismember ().isEmpty ()) {
168
+ KeySelector keySelector = KeySelector .of (getRequiredAdapter ().getConverter (), criteria .getOrSismember (),
169
+ domainType );
170
+
171
+ if (!keySelector .setValueLookup ().isEmpty ()) {
155
172
allKeys .addAll (connection .sUnion (keys (keyspace + ":" , criteria .getOrSismember ())));
156
173
}
157
174
175
+ allKeys .addAll (keySelector .keys ());
176
+
158
177
if (criteria .getNear () != null ) {
159
178
160
179
GeoRadiusCommandArgs limit = GeoRadiusCommandArgs .newGeoRadiusArgs ();
@@ -170,7 +189,6 @@ private List<byte[]> findKeys(RedisOperationChain criteria, int rows, String key
170
189
}
171
190
}
172
191
173
-
174
192
Set <ByteArrayWrapper > unique = new LinkedHashSet <>(allKeys .size ());
175
193
allKeys .forEach (key -> unique .add (new ByteArrayWrapper (key )));
176
194
@@ -244,4 +262,34 @@ public RedisOperationChain resolve(KeyValueQuery<?> query) {
244
262
return (RedisOperationChain ) query .getCriteria ();
245
263
}
246
264
}
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
+ */
273
+ record KeySelector (Collection <byte []> keys , Set <PathAndValue > setValueLookup ) {
274
+
275
+ static KeySelector of (RedisConverter converter , Set <PathAndValue > pathAndValues , Class <?> domainType ) {
276
+
277
+ Set <byte []> keys = new LinkedHashSet <>();
278
+ Set <PathAndValue > remainder = new LinkedHashSet <>();
279
+
280
+ for (PathAndValue pathAndValue : pathAndValues ) {
281
+
282
+ PersistentPropertyPath <RedisPersistentProperty > path = converter .getMappingContext ()
283
+ .getPersistentPropertyPath (pathAndValue .getPath (), domainType );
284
+ if (path .getLeafProperty ().isIdProperty ()) {
285
+ byte [] key = converter .getConversionService ().convert (pathAndValue .getFirstValue (), byte [].class );
286
+ keys .add (key );
287
+ } else {
288
+ remainder .add (pathAndValue );
289
+ }
290
+ }
291
+
292
+ return new KeySelector (keys , remainder );
293
+ }
294
+ }
247
295
}
0 commit comments