33
33
34
34
/**
35
35
* {@link IndexWriter} takes care of writing <a href="https://redis.io/topics/indexes">secondary index</a> structures to
36
- * Redis. Depending on the type of {@link IndexedData} it uses eg. Sets with specific names to add actually referenced
37
- * keys to. While doing so {@link IndexWriter} also keeps track of all indexes associated with the root types key, which
36
+ * Redis. Depending on the type of {@link IndexedData}, it uses Sets with specific names to add actually referenced keys
37
+ * to. While doing so {@link IndexWriter} also keeps track of all indexes associated with the root types key, which
38
38
* allows to remove the root key from all indexes in case of deletion.
39
39
*
40
40
* @author Christoph Strobl
41
41
* @author Rob Winch
42
+ * @author Mark Paluch
42
43
* @since 1.7
43
44
*/
44
45
class IndexWriter {
45
46
47
+ private static final byte [] SEPARATOR = ":" .getBytes ();
48
+ private static final byte [] IDX = "idx" .getBytes ();
49
+
46
50
private final RedisConnection connection ;
47
51
private final RedisConverter converter ;
48
52
49
53
/**
50
54
* Creates new {@link IndexWriter}.
51
55
*
52
- * @param keyspace The key space to write index values to. Must not be {@literal null}.
53
56
* @param connection must not be {@literal null}.
54
57
* @param converter must not be {@literal null}.
55
58
*/
@@ -127,7 +130,7 @@ public void removeKeyFromIndexes(String keyspace, Object key) {
127
130
Assert .notNull (key , "Key must not be null" );
128
131
129
132
byte [] binKey = toBytes (key );
130
- byte [] indexHelperKey = ByteUtils . concatAll ( toBytes ( keyspace + ":" ) , binKey , toBytes ( ":idx" ) );
133
+ byte [] indexHelperKey = createIndexKey ( keyspace , binKey );
131
134
132
135
for (byte [] indexKey : connection .sMembers (indexHelperKey )) {
133
136
@@ -147,10 +150,10 @@ public void removeKeyFromIndexes(String keyspace, Object key) {
147
150
*/
148
151
public void removeAllIndexes (String keyspace ) {
149
152
150
- Set <byte []> potentialIndex = connection .keys (toBytes (keyspace + ": *" ));
153
+ Set <byte []> potentialIndex = connection .keys (createIndexKey (keyspace , " *" ));
151
154
152
155
if (!potentialIndex .isEmpty ()) {
153
- connection .del (potentialIndex .toArray (new byte [potentialIndex . size () ][]));
156
+ connection .del (potentialIndex .toArray (new byte [0 ][]));
154
157
}
155
158
}
156
159
@@ -162,7 +165,7 @@ private void removeKeyFromExistingIndexes(byte[] key, Iterable<IndexedData> inde
162
165
}
163
166
164
167
/**
165
- * Remove given key from all indexes matching {@link IndexedData#getIndexName()}:
168
+ * Remove given key from all indexes matching {@link IndexedData#getIndexName()}.
166
169
*
167
170
* @param key
168
171
* @param indexedData
@@ -171,8 +174,7 @@ protected void removeKeyFromExistingIndexes(byte[] key, IndexedData indexedData)
171
174
172
175
Assert .notNull (indexedData , "IndexedData must not be null" );
173
176
174
- Set <byte []> existingKeys = connection
175
- .keys (toBytes (indexedData .getKeyspace () + ":" + indexedData .getIndexName () + ":*" ));
177
+ Set <byte []> existingKeys = connection .keys (createIndexKey (indexedData .getKeyPrefix (), "*" ));
176
178
177
179
if (!CollectionUtils .isEmpty (existingKeys )) {
178
180
for (byte [] existingKey : existingKeys ) {
@@ -216,30 +218,66 @@ protected void addKeyToIndex(byte[] key, IndexedData indexedData) {
216
218
return ;
217
219
}
218
220
219
- byte [] indexKey = toBytes (indexedData .getKeyspace () + ":" + indexedData . getIndexName () + ":" );
221
+ byte [] indexKey = toBytes (indexedData .getKeyPrefix (), SEPARATOR );
220
222
indexKey = ByteUtils .concat (indexKey , toBytes (value ));
221
223
connection .sAdd (indexKey , key );
222
224
223
225
// keep track of indexes used for the object
224
- connection .sAdd (ByteUtils . concatAll ( toBytes ( indexedData .getKeyspace () + ":" ) , key , toBytes ( ":idx" ) ), indexKey );
226
+ connection .sAdd (createIndexKey ( indexedData .getKeyspace (), key ), indexKey );
225
227
} else if (indexedData instanceof GeoIndexedPropertyValue propertyValue ) {
226
228
227
229
Object value = propertyValue .getValue ();
228
230
if (value == null ) {
229
231
return ;
230
232
}
231
233
232
- byte [] indexKey = toBytes (indexedData .getKeyspace () + ":" + indexedData . getIndexName ());
234
+ byte [] indexKey = toBytes (indexedData .getKeyPrefix ());
233
235
connection .geoAdd (indexKey , propertyValue .getPoint (), key );
234
236
235
237
// keep track of indexes used for the object
236
- connection .sAdd (ByteUtils . concatAll ( toBytes ( indexedData .getKeyspace () + ":" ) , key , toBytes ( ":idx" ) ), indexKey );
238
+ connection .sAdd (createIndexKey ( indexedData .getKeyspace (), key ), indexKey );
237
239
} else {
238
240
throw new IllegalArgumentException (
239
241
String .format ("Cannot write index data for unknown index type %s" , indexedData .getClass ()));
240
242
}
241
243
}
242
244
245
+ private byte [] createIndexKey (String keyspace , byte [] key ) {
246
+ return createIndexKey (keyspace , key , IDX );
247
+ }
248
+
249
+ private byte [] createIndexKey (Object ... items ) {
250
+
251
+ Object [] elements = new Object [items .length + (items .length - 1 )];
252
+
253
+ int j = 0 ;
254
+ for (int i = 0 ; i < items .length ; i ++) {
255
+
256
+ elements [j ++] = items [i ];
257
+ if (items .length - 1 > i ) {
258
+ elements [j ++] = SEPARATOR ;
259
+ }
260
+ }
261
+
262
+ return toBytes (elements );
263
+ }
264
+
265
+ private byte [] toBytes (Object ... values ) {
266
+
267
+ byte [][] arrays = new byte [values .length ][];
268
+
269
+ for (int i = 0 ; i < values .length ; i ++) {
270
+
271
+ if (values [i ] instanceof byte [] bb ) {
272
+ arrays [i ] = bb ;
273
+ } else {
274
+ arrays [i ] = toBytes (values [i ]);
275
+ }
276
+ }
277
+
278
+ return ByteUtils .concatAll (arrays );
279
+ }
280
+
243
281
private byte [] toBytes (@ Nullable Object source ) {
244
282
245
283
if (source == null ) {
0 commit comments