DATAREDIS-425 - Support distinct indexName
This commit adds support for distinguishing between the property path that is being indexed and the name of the index that should be used. This is useful when you do not want the property path and index name to be the same. For example, if you want to use Spel expressions, it may not be possible to use the path as the name of the index. Original PR #160
This commit is contained in:
committed by
Christoph Strobl
parent
bd7728e6ad
commit
40c2582302
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* allows to remove the root key from all indexes in case of deletion.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Rob Winch
|
||||
* @since 1.7
|
||||
*/
|
||||
class IndexWriter {
|
||||
@@ -113,7 +114,7 @@ class IndexWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove given key from all indexes matching {@link IndexedData#getPath()}:
|
||||
* Remove given key from all indexes matching {@link IndexedData#getIndexName()}:
|
||||
*
|
||||
* @param key
|
||||
* @param indexedData
|
||||
@@ -121,7 +122,8 @@ class IndexWriter {
|
||||
protected void removeKeyFromExistingIndexes(byte[] key, IndexedData indexedData) {
|
||||
|
||||
Assert.notNull(indexedData, "IndexedData must not be null!");
|
||||
Set<byte[]> existingKeys = connection.keys(toBytes(indexedData.getKeySpace() + ":" + indexedData.getPath() + ":*"));
|
||||
Set<byte[]> existingKeys = connection.keys(toBytes(indexedData.getKeySpace() + ":" + indexedData.getIndexName()
|
||||
+ ":*"));
|
||||
|
||||
if (!CollectionUtils.isEmpty(existingKeys)) {
|
||||
for (byte[] existingKey : existingKeys) {
|
||||
@@ -138,7 +140,7 @@ class IndexWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given key to the index for {@link IndexedData#getPath()}.
|
||||
* Adds a given key to the index for {@link IndexedData#getIndexName()}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param indexedData must not be {@literal null}.
|
||||
@@ -156,7 +158,7 @@ class IndexWriter {
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] indexKey = toBytes(indexedData.getKeySpace() + ":" + indexedData.getPath() + ":");
|
||||
byte[] indexKey = toBytes(indexedData.getKeySpace() + ":" + indexedData.getIndexName() + ":");
|
||||
indexKey = ByteUtils.concat(indexKey, toBytes(value));
|
||||
connection.sAdd(indexKey, key);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* {@link IndexResolver} implementation considering properties annotated with {@link Indexed} or paths set up in
|
||||
* {@link IndexConfiguration}.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.7
|
||||
*/
|
||||
@@ -55,7 +55,7 @@ public class IndexResolverImpl implements IndexResolver {
|
||||
|
||||
/**
|
||||
* Creates new {@link IndexResolverImpl} with given {@link IndexConfiguration}.
|
||||
*
|
||||
*
|
||||
* @param mapppingContext must not be {@literal null}.
|
||||
*/
|
||||
public IndexResolverImpl(RedisMappingContext mappingContext) {
|
||||
@@ -166,7 +166,11 @@ public class IndexResolverImpl implements IndexResolver {
|
||||
String path = normalizeIndexPath(propertyPath, property);
|
||||
|
||||
if (indexConfiguration.hasIndexFor(keyspace, path)) {
|
||||
return new SimpleIndexedPropertyValue(keyspace, path, value);
|
||||
// FIXME it seems there is a mis-match between IndexConfiguration
|
||||
// resolving many RedisIndexSetting objects to resolving a single
|
||||
// IndexData in this method.
|
||||
RedisIndexSetting indexSetting = indexConfiguration.getIndexDefinitionsFor(keyspace, path).iterator().next();
|
||||
return new SimpleIndexedPropertyValue(keyspace, indexSetting.getIndexName(), value);
|
||||
}
|
||||
|
||||
else if (property != null && property.isAnnotationPresent(Indexed.class)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,22 +17,23 @@ package org.springframework.data.redis.core.convert;
|
||||
|
||||
/**
|
||||
* {@link IndexedData} represents a secondary index for a property path in a given keyspace.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Rob Winch
|
||||
* @since 1.7
|
||||
*/
|
||||
public interface IndexedData {
|
||||
|
||||
/**
|
||||
* Get the {@link String} representation of the dot path to the referenced property.
|
||||
*
|
||||
* Get the {@link String} representation of the index name.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
String getPath();
|
||||
String getIndexName();
|
||||
|
||||
/**
|
||||
* Get the associated keyspace the index resides in.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getKeySpace();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,33 +19,34 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link IndexedData} implementation indicating storage of data within a Redis Set.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Rob Winch
|
||||
* @since 1.7
|
||||
*/
|
||||
public class SimpleIndexedPropertyValue implements IndexedData {
|
||||
|
||||
private final String keyspace;
|
||||
private final String path;
|
||||
private final String indexName;
|
||||
private final Object value;
|
||||
|
||||
/**
|
||||
* Creates new {@link SimpleIndexedPropertyValue}.
|
||||
*
|
||||
*
|
||||
* @param keyspace must not be {@literal null}.
|
||||
* @param path must not be {@literal null}.
|
||||
* @param indexName must not be {@literal null}.
|
||||
* @param value can be {@literal null}.
|
||||
*/
|
||||
public SimpleIndexedPropertyValue(String keyspace, String path, Object value) {
|
||||
public SimpleIndexedPropertyValue(String keyspace, String indexName, Object value) {
|
||||
|
||||
this.keyspace = keyspace;
|
||||
this.path = path;
|
||||
this.indexName = indexName;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value to index.
|
||||
*
|
||||
*
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
public Object getValue() {
|
||||
@@ -54,11 +55,11 @@ public class SimpleIndexedPropertyValue implements IndexedData {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.convert.IndexedData#getPath()
|
||||
* @see org.springframework.data.redis.core.convert.IndexedData#getIndexName()
|
||||
*/
|
||||
@Override
|
||||
public String getPath() {
|
||||
return path;
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -79,7 +80,7 @@ public class SimpleIndexedPropertyValue implements IndexedData {
|
||||
|
||||
int result = 1;
|
||||
result += ObjectUtils.nullSafeHashCode(keyspace);
|
||||
result += ObjectUtils.nullSafeHashCode(path);
|
||||
result += ObjectUtils.nullSafeHashCode(indexName);
|
||||
result += ObjectUtils.nullSafeHashCode(value);
|
||||
return result;
|
||||
}
|
||||
@@ -105,7 +106,7 @@ public class SimpleIndexedPropertyValue implements IndexedData {
|
||||
if (!ObjectUtils.nullSafeEquals(this.keyspace, that.keyspace)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(this.path, that.path)) {
|
||||
if (!ObjectUtils.nullSafeEquals(this.indexName, that.indexName)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(this.value, that.value);
|
||||
@@ -117,7 +118,7 @@ public class SimpleIndexedPropertyValue implements IndexedData {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleIndexedPropertyValue [keyspace=" + keyspace + ", path=" + path + ", value=" + value + "]";
|
||||
return "SimpleIndexedPropertyValue [keyspace=" + keyspace + ", indexName=" + indexName + ", value=" + value + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ import org.springframework.util.ObjectUtils;
|
||||
/**
|
||||
* {@link IndexConfiguration} allows programmatic setup of indexes. This is suitable for cases where there is no option
|
||||
* to use the equivalent {@link Indexed} annotation.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Rob Winch
|
||||
* @since 1.7
|
||||
*/
|
||||
public class IndexConfiguration {
|
||||
@@ -40,6 +41,7 @@ public class IndexConfiguration {
|
||||
* Creates new empty {@link IndexConfiguration}.
|
||||
*/
|
||||
public IndexConfiguration() {
|
||||
|
||||
this.definitions = new CopyOnWriteArraySet<RedisIndexSetting>();
|
||||
for (RedisIndexSetting initial : initialConfiguration()) {
|
||||
addIndexDefinition(initial);
|
||||
@@ -48,7 +50,7 @@ public class IndexConfiguration {
|
||||
|
||||
/**
|
||||
* Checks if an index is defined for a given keyspace and property path.
|
||||
*
|
||||
*
|
||||
* @param keyspace
|
||||
* @param path
|
||||
* @return true if index is defined.
|
||||
@@ -66,7 +68,7 @@ public class IndexConfiguration {
|
||||
|
||||
/**
|
||||
* Get the list of {@link RedisIndexSetting} for a given keyspace and property path.
|
||||
*
|
||||
*
|
||||
* @param keyspace
|
||||
* @param path
|
||||
* @return never {@literal null}.
|
||||
@@ -86,7 +88,7 @@ public class IndexConfiguration {
|
||||
|
||||
/**
|
||||
* Add given {@link RedisIndexSetting}.
|
||||
*
|
||||
*
|
||||
* @param indexDefinition must not be {@literal null}.
|
||||
*/
|
||||
public void addIndexDefinition(RedisIndexSetting indexDefinition) {
|
||||
@@ -108,7 +110,7 @@ public class IndexConfiguration {
|
||||
|
||||
/**
|
||||
* Customization hook.
|
||||
*
|
||||
*
|
||||
* @return must not return {@literal null}.
|
||||
*/
|
||||
protected Iterable<RedisIndexSetting> initialConfiguration() {
|
||||
@@ -117,12 +119,14 @@ public class IndexConfiguration {
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Rob Winch
|
||||
* @since 1.7
|
||||
*/
|
||||
public static class RedisIndexSetting {
|
||||
|
||||
private final Serializable keyspace;
|
||||
private final String path;
|
||||
private final String indexName;
|
||||
private final IndexType type;
|
||||
|
||||
public RedisIndexSetting(Serializable keyspace, String path) {
|
||||
@@ -130,12 +134,20 @@ public class IndexConfiguration {
|
||||
}
|
||||
|
||||
public RedisIndexSetting(Serializable keyspace, String path, IndexType type) {
|
||||
this(keyspace, path, path, type);
|
||||
}
|
||||
|
||||
public RedisIndexSetting(Serializable keyspace, String path, String indexName, IndexType type) {
|
||||
this.keyspace = keyspace;
|
||||
this.path = path;
|
||||
this.indexName = indexName;
|
||||
this.type = type == null ? IndexType.SIMPLE : type;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public Serializable getKeyspace() {
|
||||
return keyspace;
|
||||
}
|
||||
@@ -153,6 +165,7 @@ public class IndexConfiguration {
|
||||
|
||||
int result = ObjectUtils.nullSafeHashCode(keyspace);
|
||||
result += ObjectUtils.nullSafeHashCode(path);
|
||||
result += ObjectUtils.nullSafeHashCode(indexName);
|
||||
result += ObjectUtils.nullSafeHashCode(type);
|
||||
return result;
|
||||
}
|
||||
@@ -178,6 +191,9 @@ public class IndexConfiguration {
|
||||
if (!ObjectUtils.nullSafeEquals(this.path, that.path)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(this.indexName, that.indexName)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(this.type, that.type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user