Spring AI集成Redis Vector Store删除重建索引报错求助
Redis向量索引删除重建时的ClassCastException问题
我使用Redis存储嵌入向量(embeddings)的索引,想要删除该索引并重新创建,以清除所有现有嵌入向量。编写了如下代码实现:
@Service public class CacheService { private final Logger logger = LoggerFactory.getLogger(CacheService.class); private final RedisVectorStore redisVectorStore; private final JedisPooled jedis; public CacheService( @Qualifier("customRedisVectorStore") VectorStore redisVectorStore ) { this.redisVectorStore = (RedisVectorStore) redisVectorStore; this.jedis = this.redisVectorStore.getJedis(); // RedisVectorStore provides access to JedisPooled } /** * Delete all documents from the vector store */ public void deleteAll() { // Optionally drop and recreate the index try (Connection connection = jedis.getPool().getResource()) { if (connection.isConnected()) { connection.sendCommand(() -> SafeEncoder.encode("FT.DROPINDEX"), SafeEncoder.encode("spring-ai-example"), SafeEncoder.encode("DD")); } else{ logger.warn("Connection is not connected"); } } catch (Exception e) { // Index might not exist, that's okay logger.warn("Failed to drop index", e); } } public void createIndex() { IndexDefinition indexDefinition = new IndexDefinition() .setPrefixes("prefix:"); Schema schema = new Schema() .addTextField("content", 1.0) .addVectorField("embedding", Schema.VectorField.VectorAlgo.HNSW, new HashMap<>() {{ put("TYPE", "FLOAT32"); put("DIM", 128); // Set the dimension of your vectors put("DISTANCE_METRIC", "COSINE"); }}); jedis.ftCreate("spring-ai-example", IndexOptions.defaultOptions().setDefinition(indexDefinition), schema); logger.debug("Index created"); } /** * Delete all documents and recreate the index */ public void deleteAllAndRecreateIndex() { deleteAll(); createIndex(); try { redisVectorStore.afterPropertiesSet(); } catch (Exception e) { throw new RuntimeException("Failed to recreate index", e); } } }
但执行到redisVectorStore.afterPropertiesSet();时抛出如下异常:
java.lang.ClassCastException: class [B cannot be cast to class java.util.List ([B and java.util.List are in module java.base of loader 'bootstrap') at redis.clients.jedis.BuilderFactory$19.build(BuilderFactory.java:284) ~[jedis-5.0.2.jar:na] at redis.clients.jedis.BuilderFactory$19.build(BuilderFactory.java:279) ~[jedis-5.0.2.jar:na] at redis.clients.jedis.Connection.executeCommand(Connection.java:138) ~[jedis-5.0.2.jar:na] at redis.clients.jedis.executors.DefaultCommandExecutor.executeCommand(DefaultCommandExecutor.java:24) ~[jedis-5.0.2.jar:na] at redis.clients.jedis.UnifiedJedis.executeCommand(UnifiedJedis.java:244) ~[jedis-5.0.2.jar:na] at redis.clients.jedis.UnifiedJedis.ftList(UnifiedJedis.java:3883) ~[jedis-5.0.2.jar:na] at org.springframework.ai.vectorstore.RedisVectorStore.afterPropertiesSet(RedisVectorStore.java:428) ~[spring-ai-redis-store-1.0.0-M3.jar:1.0.0-M3] at org.example.service.CacheService.deleteAllAndRecreateIndex(CacheService.java:79) ~[main/:na] at org.example.controller.CacheController.deleteAll(CacheController.java:21) ~[main/:na] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.13.jar:6.1.13] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.13.jar:6.1.13] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.13.jar:6.1.13] at org.springframework.web.servlet.FrameworkServlet.doDelete(FrameworkServlet.java:936) ~[spring-webmvc-6.1.13.jar:6.1.13] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:596) ~[tomcat-embed-core-10.1.30.jar:6.0]
我认为该异常是由于VectorStore不同步导致的,请问是否有更优的实现方式?
解决方案
禁止手动调用
afterPropertiesSet():该方法是Spring容器初始化Bean时的回调方法,手动调用会导致内部状态冲突。从异常栈可以看出,问题出在FT.LIST命令的结果解析上,Jedis 5.0.2与Spring AI 1.0.0-M3的命令返回值解析逻辑不兼容,手动触发初始化会触发这个不兼容的调用。优化索引删除逻辑:不要直接操作底层Connection发送命令,改用JedisPooled提供的官方方法,兼容性更好:
public void deleteAll() { try { // 传入true参数等价于FT.DROPINDEX ... DD,删除索引同时删除关联文档 jedis.ftDropIndex("spring-ai-example", true); } catch (JedisDataException e) { // 仅当异常不是"索引不存在"时记录警告 if (!e.getMessage().contains("Index not found")) { logger.warn("Failed to drop index", e); } } }移除初始化调用,简化重建流程:索引重建完成后,RedisVectorStore后续的操作会自动感知新索引,无需手动触发初始化。优化后的重建方法:
public void deleteAllAndRecreateIndex() { deleteAll(); createIndex(); logger.info("Index deleted and recreated successfully"); }版本兼容性检查:Spring AI 1.0.0-M3属于预览版本,对Jedis 5.x的支持不完善。建议降级到Jedis 4.x系列,或者升级Spring AI到正式发布版本,从根源避免此类兼容性问题。
内容的提问来源于stack exchange,提问作者Jackie
相关产品推荐
相关产品推荐

