From 963b9dbded4ab244bc982b97057b36574ec49cff Mon Sep 17 00:00:00 2001 From: Solomon Hsu Date: Thu, 29 May 2025 11:29:33 +0800 Subject: [PATCH] fix(qdrant): support Long type in payload by converting to String Qdrant does not support java.lang.Long as a native payload type. Previously, passing a Long value caused the following exception: java.lang.IllegalArgumentException: Unsupported Qdrant value type: class java.lang.Long at org.springframework.ai.vectorstore.qdrant.QdrantValueFactory.value(QdrantValueFactory.java:85) at org.springframework.ai.vectorstore.qdrant.QdrantValueFactory.lambda$toValueMap$1(QdrantValueFactory.java:46) ... To resolve this, Long values are now converted to their String representation in QdrantValueFactory. This preserves precision and avoids serialization issues. test(qdrant): add test to verify Long metadata values are stored as String Adds a test to ensure that Long values in document metadata are safely converted to String before being stored in Qdrant. The test inserts a document with a Long-type "ref_id", performs a similarity search, and verifies that: - the result is not empty, - the retrieved "ref_id" is a String, - the value matches the original Long when parsed. Also ensures cleanup by deleting the inserted document from the store. Signed-off-by: Solomon Hsu (cherry picked from commit f0d4cbf03750469bc992bb8329096132bbef5c96) --- .../qdrant/QdrantValueFactory.java | 3 +++ .../qdrant/QdrantVectorStoreIT.java | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantValueFactory.java b/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantValueFactory.java index b328f4189..c062e1f6c 100644 --- a/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantValueFactory.java +++ b/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantValueFactory.java @@ -75,6 +75,9 @@ final class QdrantValueFactory { return ValueFactory.value((String) value); case "Integer": return ValueFactory.value((Integer) value); + case "Long": + // use String representation + return ValueFactory.value(String.valueOf(value)); case "Double": return ValueFactory.value((Double) value); case "Float": diff --git a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java index 004bf32d2..b2af2ab75 100644 --- a/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java +++ b/vector-stores/spring-ai-qdrant-store/src/test/java/org/springframework/ai/vectorstore/qdrant/QdrantVectorStoreIT.java @@ -314,6 +314,27 @@ public class QdrantVectorStoreIT extends BaseVectorStoreTests { }); } + @Test + void shouldConvertLongToString() { + this.contextRunner.run(context -> { + QdrantVectorStore vectorStore = context.getBean(QdrantVectorStore.class); + var refId = System.currentTimeMillis(); + var doc = new Document("Long type ref_id", Map.of("ref_id", refId)); + vectorStore.add(List.of(doc)); + + List results = vectorStore + .similaritySearch(SearchRequest.builder().query("Long type ref_id").topK(1).build()); + assertThat(results).hasSize(1); + Document resultDoc = results.get(0); + var resultRefId = resultDoc.getMetadata().get("ref_id"); + assertThat(resultRefId).isInstanceOf(String.class); + assertThat(Double.valueOf((String) resultRefId)).isEqualTo(refId); + + // Remove all documents from the store + vectorStore.delete(List.of(resultDoc.getId())); + }); + } + @SpringBootConfiguration public static class TestApplication {